@@ -26,12 +26,12 @@ import kotlin.reflect.KClass
26
26
27
27
@KWebDSL
28
28
open class Element (
29
- override val browser : WebBrowser ,
30
- val creator : ElementCreator <* >? ,
31
- val tag : String? = null ,
32
- @Volatile var id : String
29
+ override val browser : WebBrowser ,
30
+ val creator : ElementCreator <* >? ,
31
+ val tag : String? = null ,
32
+ @Volatile var id : String
33
33
) :
34
- EventGenerator <Element > {
34
+ EventGenerator <Element > {
35
35
constructor (element: Element ) : this (element.browser, element.creator, tag = element.tag, id = element.id)
36
36
37
37
/* *
@@ -56,7 +56,11 @@ open class Element(
56
56
*
57
57
* This uses the same template mechanism as [callJsFunction]
58
58
*/
59
- suspend fun <O > callJsFunctionWithResult (js : String , outputMapper : (JsonElement ) -> O , vararg args : JsonElement ): O ? {
59
+ suspend fun <O > callJsFunctionWithResult (
60
+ js : String ,
61
+ outputMapper : (JsonElement ) -> O ,
62
+ vararg args : JsonElement
63
+ ): O ? {
60
64
val result = browser.callJsFunctionWithResult(js, * args)
61
65
return outputMapper.invoke(result)
62
66
}
@@ -98,7 +102,7 @@ open class Element(
98
102
* A utility function to set multiple attributes in a single call, in the
99
103
* style of [mapOf]. This is a wrapper around [setAttribute].
100
104
*/
101
- fun setAttributes (vararg pair : Pair <String , JsonPrimitive >) : Element {
105
+ fun setAttributes (vararg pair : Pair <String , JsonPrimitive >): Element {
102
106
pair.forEach { (k, v) -> setAttribute(k, v) }
103
107
return this
104
108
}
@@ -111,20 +115,22 @@ open class Element(
111
115
* with the specified namespace. If null then Kweb will use [Element.createElement](https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute).
112
116
113
117
*/
114
- fun setAttribute (name : String , value : JsonPrimitive , namespace : String? = null): Element {
118
+ fun setAttribute (name : String , value : JsonPrimitive , namespace : String? = null): Element {
115
119
val jsoupDoc = browser.htmlDocument.get()
116
- val setAttributeJavaScript = when (namespace) {
120
+ val setAttributeJavaScript = when (namespace) {
117
121
null -> " document.getElementById({}).setAttribute({}, {});"
118
122
else -> " document.getElementById({}).setAttributeNS(\" $namespace \" , {}, {});"
119
123
}
120
124
when {
121
125
jsoupDoc != null && (browser.isCatchingOutbound() == null || browser.isCatchingOutbound() == RENDER ) -> {
122
126
jsoupDoc.getElementById(this .id)!! .attr(name, value.content)
123
127
}
128
+
124
129
else -> {
125
130
callJsFunction(
126
131
setAttributeJavaScript,
127
- id.json, name.json, value)
132
+ id.json, name.json, value
133
+ )
128
134
}
129
135
}
130
136
if (name.equals(" id" , ignoreCase = true )) {
@@ -134,29 +140,22 @@ open class Element(
134
140
}
135
141
136
142
@Deprecated(" use setAttribute() instead" , replaceWith = ReplaceWith (expression = " setAttribute(name, value)" ))
137
- fun setAttributeRaw (name : String , value : JsonPrimitive )
138
- = setAttribute(name, value)
143
+ fun setAttributeRaw (name : String , value : JsonPrimitive ) = setAttribute(name, value)
139
144
140
145
@Deprecated(" use setAttribute() instead" , replaceWith = ReplaceWith (expression = " setAttribute(name, value)" ))
141
- fun setAttributeRaw (name : String , value : String )
142
- = setAttribute(name, JsonPrimitive (value))
146
+ fun setAttributeRaw (name : String , value : String ) = setAttribute(name, JsonPrimitive (value))
143
147
144
148
@Deprecated(" use setAttribute() instead" , replaceWith = ReplaceWith (expression = " setAttribute(name, value)" ))
145
- fun setAttributeRaw (name : String , value : Boolean )
146
- = setAttribute(name, JsonPrimitive (value))
149
+ fun setAttributeRaw (name : String , value : Boolean ) = setAttribute(name, JsonPrimitive (value))
147
150
148
151
@Deprecated(" use setAttribute() instead" , replaceWith = ReplaceWith (expression = " setAttribute(name, value)" ))
149
- fun setAttributeRaw (name : String , value : Number )
150
- = setAttribute(name, JsonPrimitive (value))
152
+ fun setAttributeRaw (name : String , value : Number ) = setAttribute(name, JsonPrimitive (value))
151
153
152
- fun setAttribute (name : String , value : String )
153
- = setAttribute(name, JsonPrimitive (value))
154
+ fun setAttribute (name : String , value : String ) = setAttribute(name, JsonPrimitive (value))
154
155
155
- fun setAttribute (name : String , value : Boolean )
156
- = setAttribute(name, JsonPrimitive (value))
156
+ fun setAttribute (name : String , value : Boolean ) = setAttribute(name, JsonPrimitive (value))
157
157
158
- fun setAttribute (name : String , value : Number )
159
- = setAttribute(name, JsonPrimitive (value))
158
+ fun setAttribute (name : String , value : Number ) = setAttribute(name, JsonPrimitive (value))
160
159
161
160
/* *
162
161
* Set an attribute to the value in a [KVal], if the value changes the attribute
@@ -179,6 +178,7 @@ open class Element(
179
178
jsoupDoc != null && (browser.isCatchingOutbound() == null || browser.isCatchingOutbound() == RENDER ) -> {
180
179
jsoupDoc.getElementById(id)!! .removeAttr(name)
181
180
}
181
+
182
182
else -> {
183
183
callJsFunction(" document.getElementById({}).removeAttribute({})" , id.json, JsonPrimitive (name))
184
184
}
@@ -198,6 +198,7 @@ open class Element(
198
198
val thisEl = jsoupDoc.getElementById(this .id)!!
199
199
thisEl.html(html)
200
200
}
201
+
201
202
else -> {
202
203
callJsFunction(" document.getElementById({}).innerHTML = {}" , id.json, JsonPrimitive (html))
203
204
}
@@ -234,7 +235,7 @@ open class Element(
234
235
* A convenience function to set the [class attribute](https://www.w3schools.com/html/html_classes.asp),
235
236
* this is a wrapper around [setAttribute].
236
237
*/
237
- fun classes (value : KVal <String >) = setAttribute(" class" , value.map { it.json })
238
+ fun classes (value : KVal <String >) = setAttribute(" class" , value.map { it.json })
238
239
239
240
/* *
240
241
* A convenience function to set the [class attribute](https://www.w3schools.com/html/html_classes.asp),
@@ -256,19 +257,32 @@ open class Element(
256
257
*/
257
258
fun addClasses (vararg classes : String , onlyIf : Boolean = true): Element {
258
259
if (onlyIf) {
259
- for (class_ in classes) {
260
- if (class_.contains(' ' )) {
261
- error(" Class names must not contain spaces" )
260
+ val jsoupDoc = browser.htmlDocument.get()
261
+ when {
262
+ jsoupDoc != null && (browser.isCatchingOutbound() == null || browser.isCatchingOutbound() == RENDER ) -> {
263
+ val thisEl = jsoupDoc.getElementById(this .id)!!
264
+ classes.forEach { thisEl.addClass(it) }
262
265
}
263
- // language=JavaScript
264
- callJsFunction("""
266
+ else -> {
267
+ for (class_ in classes) {
268
+ if (class_.contains(' ' )) {
269
+ error(" Class names must not contain spaces" )
270
+ }
271
+ // language=JavaScript
272
+ callJsFunction(
273
+ """
265
274
let id = {};
266
275
let className = {};
267
276
let el = document.getElementById(id);
268
277
if (el.classList) el.classList.add(className);
269
278
else if (!hasClass(el, className)) el.className += " " + className;
270
- """ .trimIndent(), id.json, JsonPrimitive (class_))
279
+ """ .trimIndent(), id.json, JsonPrimitive (class_)
280
+ )
281
+ }
282
+ }
271
283
}
284
+
285
+
272
286
}
273
287
return this
274
288
}
@@ -285,7 +299,8 @@ open class Element(
285
299
error(" Class names must not contain spaces" )
286
300
}
287
301
// language=JavaScript
288
- callJsFunction("""
302
+ callJsFunction(
303
+ """
289
304
let id = {};
290
305
let className = {};
291
306
let el = document.getElementById(id);
@@ -294,7 +309,8 @@ open class Element(
294
309
var reg = new RegExp("(\\s|^)" + className + "(\\s|${' $' } )");
295
310
el.className = el.className.replace(reg, " ");
296
311
}
297
- """ .trimIndent(), id.json, JsonPrimitive (class_))
312
+ """ .trimIndent(), id.json, JsonPrimitive (class_)
313
+ )
298
314
}
299
315
}
300
316
return this
@@ -325,26 +341,29 @@ open class Element(
325
341
when {
326
342
jsoupDoc != null && (browser.isCatchingOutbound() == null || browser.isCatchingOutbound() == RENDER ) -> {
327
343
val jsoupElement = jsoupDoc.getElementById(this .id)
328
- jsoupElement!! .children().remove()
344
+ jsoupElement!! .children().remove()
329
345
}
346
+
330
347
else -> {
331
348
// language=JavaScript
332
- callJsFunction("""
349
+ callJsFunction(
350
+ """
333
351
let id = {};
334
352
if (document.getElementById(id) != null) {
335
353
let element = document.getElementById(id);
336
354
while (element.firstChild) {
337
355
element.removeChild(element.firstChild);
338
356
}
339
357
}
340
- """ .trimIndent(), id.json)
358
+ """ .trimIndent(), id.json
359
+ )
341
360
}
342
361
}
343
362
344
363
return this
345
364
}
346
365
347
- fun removeChildrenBetweenSpans (startSpanId : String , endSpanId : String ) : Element {
366
+ fun removeChildrenBetweenSpans (startSpanId : String , endSpanId : String ): Element {
348
367
val jsoupDoc = browser.htmlDocument.get()
349
368
when {
350
369
jsoupDoc != null && (browser.isCatchingOutbound() == null || browser.isCatchingOutbound() == RENDER ) -> {
@@ -359,17 +378,20 @@ open class Element(
359
378
}
360
379
}
361
380
}
381
+
362
382
else -> {
363
383
// language=JavaScript
364
- callJsFunction("""
384
+ callJsFunction(
385
+ """
365
386
let startSpan = document.getElementById({});
366
387
let endSpan = document.getElementById({});
367
388
let nextSibling = startSpan.nextSibling;
368
389
while(nextSibling != endSpan) {
369
390
startSpan.parentNode.removeChild(startSpan.nextSibling);
370
391
nextSibling = startSpan.nextSibling;
371
392
}
372
- """ .trimIndent(), JsonPrimitive (startSpanId), JsonPrimitive (endSpanId))
393
+ """ .trimIndent(), JsonPrimitive (startSpanId), JsonPrimitive (endSpanId)
394
+ )
373
395
}
374
396
}
375
397
return this
@@ -384,11 +406,14 @@ open class Element(
384
406
.children()[position]
385
407
.remove()
386
408
}
409
+
387
410
else -> {
388
- callJsFunction("""
411
+ callJsFunction(
412
+ """
389
413
let element = document.getElementById({});
390
414
element.removeChild(element.children[{}]);
391
- """ .trimIndent(), id.json, position.json)
415
+ """ .trimIndent(), id.json, position.json
416
+ )
392
417
}
393
418
}
394
419
return this
@@ -407,6 +432,7 @@ open class Element(
407
432
val element = jsoupDoc.getElementById(this .id)
408
433
element!! .text(value)
409
434
}
435
+
410
436
else -> {
411
437
callJsFunction(setTextJS, id.json, JsonPrimitive (value))
412
438
}
@@ -451,6 +477,7 @@ open class Element(
451
477
val element = jsoupDoc.getElementById(this .id)
452
478
element!! .appendText(value)
453
479
}
480
+
454
481
else -> {
455
482
callJsFunction(createTextNodeJs, JsonPrimitive (value), id.json)
456
483
}
@@ -467,10 +494,17 @@ open class Element(
467
494
browser.callJsFunction(wrappedJS, id.json, JsonPrimitive (eventName))
468
495
}
469
496
470
- override fun addEventListener (eventName : String , returnEventFields : Set <String >, retrieveJs : String? , preventDefault : Boolean , callback : (JsonElement ) -> Unit ): Element {
497
+ override fun addEventListener (
498
+ eventName : String ,
499
+ returnEventFields : Set <String >,
500
+ retrieveJs : String? ,
501
+ preventDefault : Boolean ,
502
+ callback : (JsonElement ) -> Unit
503
+ ): Element {
471
504
val callbackId = abs(random.nextInt())
472
505
val retrievedJs = if (retrieveJs != null ) " , \" retrieved\" : ($retrieveJs )" else " "
473
- val eventObject = " {" + returnEventFields.joinToString(separator = " , " ) { " \" $it \" : event.$it " } + retrievedJs + " }"
506
+ val eventObject =
507
+ " {" + returnEventFields.joinToString(separator = " , " ) { " \" $it \" : event.$it " } + retrievedJs + " }"
474
508
/* It'd be nice to make eventObject a parameter, but it doesn't work.
475
509
eventObject is a map that has entries that look like { "buttons" : event.buttons }
476
510
the event field accessed here is the event parameter from the "function(event)" in the javascript
@@ -510,8 +544,17 @@ open class Element(
510
544
* @param updateOnEvent The event to listen for that signifies this element has been updated
511
545
* @param initialValue The initial value of the KVar
512
546
*/
513
- fun bind (accessor : (elementId : String ) -> String , updateOnEvent : String , initialValue : JsonElement = JsonPrimitive ("")) : KVar <JsonElement > {
514
- return bind(reader = { accessor(it) }, writer = { id, value -> " ${accessor(id)} = $value " }, updateOnEvent = updateOnEvent, initialValue = initialValue)
547
+ fun bind (
548
+ accessor : (elementId: String ) -> String ,
549
+ updateOnEvent : String ,
550
+ initialValue : JsonElement = JsonPrimitive ("")
551
+ ): KVar <JsonElement > {
552
+ return bind(
553
+ reader = { accessor(it) },
554
+ writer = { id, value -> " ${accessor(id)} = $value " },
555
+ updateOnEvent = updateOnEvent,
556
+ initialValue = initialValue
557
+ )
515
558
}
516
559
517
560
/* *
@@ -526,19 +569,24 @@ open class Element(
526
569
* @param updateOnEvent The event to listen for that signifies this element has been updated
527
570
* @param initialValue The initial value of the KVar
528
571
*/
529
- fun bind (reader : (elementId : String ) -> String , writer : (elementId : String , value : String ) -> String , updateOnEvent : String , initialValue : JsonElement = JsonPrimitive ("")) : KVar <JsonElement > {
572
+ fun bind (
573
+ reader : (elementId: String ) -> String ,
574
+ writer : (elementId: String , value: String ) -> String ,
575
+ updateOnEvent : String ,
576
+ initialValue : JsonElement = JsonPrimitive ("")
577
+ ): KVar <JsonElement > {
530
578
val kv = KVar (initialValue)
531
579
on(retrieveJs = reader(this .id)).event<Event >(updateOnEvent) { event ->
532
580
kv.value = event.retrieved
533
581
}
534
582
val kvChangeHandler = kv.addListener { old, new ->
535
- callJsFunction(writer(this .id, " {}" )+ " ;" , new)
583
+ callJsFunction(writer(this .id, " {}" ) + " ;" , new)
536
584
}
537
585
creator?.onCleanup(true ) {
538
586
kv.removeListener(kvChangeHandler)
539
587
kv.close(CloseReason (" Ancestor ElementCreator cleaned up" ))
540
588
}
541
- callJsFunction(writer(this .id, " {}" )+ " ;" , initialValue)
589
+ callJsFunction(writer(this .id, " {}" ) + " ;" , initialValue)
542
590
return kv
543
591
}
544
592
@@ -548,10 +596,12 @@ open class Element(
548
596
*/
549
597
fun delete () {
550
598
// language=JavaScript
551
- callJsFunction("""
599
+ callJsFunction(
600
+ """
552
601
let element = document.getElementById({});
553
602
element.parentNode.removeChild(element);
554
- """ .trimIndent(), id.json)
603
+ """ .trimIndent(), id.json
604
+ )
555
605
}
556
606
557
607
/* *
@@ -560,13 +610,15 @@ open class Element(
560
610
*/
561
611
fun deleteIfExists () {
562
612
// language=JavaScript
563
- callJsFunction("""
613
+ callJsFunction(
614
+ """
564
615
let id = {}
565
616
if (document.getElementById(id)) {
566
617
let element = document.getElementById(id);
567
618
element.parentNode.removeChild(element);
568
619
}
569
- """ .trimIndent(), id.json)
620
+ """ .trimIndent(), id.json
621
+ )
570
622
}
571
623
572
624
/* *
@@ -579,7 +631,7 @@ open class Element(
579
631
*/
580
632
val style get() = StyleReceiver (this )
581
633
582
- val flags : ConcurrentSkipListSet <String > by lazy { ConcurrentSkipListSet () }
634
+ val flags: ConcurrentSkipListSet <String > by lazy { ConcurrentSkipListSet () }
583
635
584
636
/* *
585
637
* See [here](https://docs.kweb.io/en/latest/dom.html#listening-for-events).
0 commit comments