@@ -36,6 +36,14 @@ limitations under the License.
36
36
******************************************************************************/
37
37
38
38
const polyplug = function ( ) {
39
+
40
+ /**************************************************************************
41
+ Internal state for PolyPlug.
42
+ **************************************************************************/
43
+
44
+ // Tracks event handler functions.
45
+ const REGISTERED_EVENTS = { } ;
46
+
39
47
/**************************************************************************
40
48
Serialization functions for PolyPlug.
41
49
**************************************************************************/
@@ -330,6 +338,14 @@ const polyplug = function() {
330
338
Event handling functions for PolyPlug.
331
339
**************************************************************************/
332
340
341
+ function getEventKey ( query , eventType , listener ) {
342
+ /*
343
+ Return a unique key to identify a query/eventType/listener combination.
344
+ */
345
+ const sortedQuery = Object . keys ( query ) . sort ( ) . reduce ( ( result , key ) => ( result [ key ] = query [ key ] , result ) , { } ) ;
346
+ return JSON . stringify ( [ sortedQuery , eventType , listener ] ) ;
347
+ }
348
+
333
349
function registerEvent ( query , eventType , listener ) {
334
350
/*
335
351
Register an event listener, given:
@@ -346,19 +362,41 @@ const polyplug = function() {
346
362
expected function in the most appropriate way.
347
363
*/
348
364
const elements = getElements ( query ) ;
349
- elements . forEach ( function ( element ) {
350
- element . addEventListener ( eventType , function ( e ) {
351
- const detail = JSON . stringify ( {
352
- type : e . type ,
353
- target : nodeToJS ( e . target ) ,
354
- listener : listener
355
- } ) ;
356
- const send = new CustomEvent ( "polyplugSend" , { detail : detail } ) ;
357
- document . dispatchEvent ( send ) ;
365
+ const eventHandler = function ( e ) {
366
+ const detail = JSON . stringify ( {
367
+ type : e . type ,
368
+ target : nodeToJS ( e . target ) ,
369
+ listener : listener
358
370
} ) ;
371
+ const send = new CustomEvent ( "polyplugSend" , { detail : detail } ) ;
372
+ document . dispatchEvent ( send ) ;
373
+ }
374
+ const eventKey = getEventKey ( query , eventType , listener ) ;
375
+ REGISTERED_EVENTS [ eventKey ] = eventHandler ;
376
+ elements . forEach ( function ( element ) {
377
+ element . addEventListener ( eventType , eventHandler ) ;
359
378
} ) ;
360
379
}
361
380
381
+ function removeEvent ( query , eventType , listener ) {
382
+ /*
383
+ Remove an event listener, given:
384
+
385
+ * target element[s] via a query object (see getElements),
386
+ * the event type (e.g. "click"), and,
387
+ * the name of the listener to call in the remote interpreter.
388
+ */
389
+ const elements = getElements ( query ) ;
390
+ const eventKey = getEventKey ( query , eventType , listener ) ;
391
+ const eventHandler = REGISTERED_EVENTS [ eventKey ] ;
392
+ if ( eventHandler ) {
393
+ elements . forEach ( function ( element ) {
394
+ element . removeEventListener ( eventType , eventHandler ) ;
395
+ } ) ;
396
+ delete REGISTERED_EVENTS [ eventKey ] ;
397
+ }
398
+ }
399
+
362
400
/**************************************************************************
363
401
Message handling functions for PolyPlug.
364
402
**************************************************************************/
@@ -368,27 +406,34 @@ const polyplug = function() {
368
406
Receive a raw message string (containing JSON). Deserialize it and
369
407
dispatch the message to the appropriate handler function.
370
408
*/
371
- const message = JSON . parse ( raw ) ;
372
- switch ( message . type ) {
373
- case "updateDOM" :
374
- onUpdateDOM ( message ) ;
375
- break ;
376
- case "registerEvent" :
377
- onRegisterEvent ( message ) ;
378
- break ;
379
- case "stdout" :
380
- onStdout ( message ) ;
381
- break ;
382
- case "stderr" :
383
- onStderr ( message ) ;
384
- break ;
385
- case "error" :
386
- onError ( message ) ;
387
- break ;
388
- default :
389
- console . log ( "Unknown message type." )
390
- console . log ( message )
391
- break ;
409
+ try {
410
+ const message = JSON . parse ( raw ) ;
411
+ switch ( message . type ) {
412
+ case "updateDOM" :
413
+ onUpdateDOM ( message ) ;
414
+ break ;
415
+ case "registerEvent" :
416
+ onRegisterEvent ( message ) ;
417
+ break ;
418
+ case "removeEvent" :
419
+ onRemoveEvent ( message ) ;
420
+ break
421
+ case "stdout" :
422
+ onStdout ( message ) ;
423
+ break ;
424
+ case "stderr" :
425
+ onStderr ( message ) ;
426
+ break ;
427
+ case "error" :
428
+ onError ( message ) ;
429
+ break ;
430
+ default :
431
+ console . log ( "Unknown message type." )
432
+ console . log ( message )
433
+ break ;
434
+ }
435
+ } catch ( error ) {
436
+ onError ( error ) ;
392
437
}
393
438
}
394
439
@@ -442,6 +487,24 @@ const polyplug = function() {
442
487
registerEvent ( msg . query , msg . eventType , msg . listener ) ;
443
488
}
444
489
490
+ function onRemoveEvent ( msg ) {
491
+ /*
492
+ Handle requests to unbind the referenced event type on the elements
493
+ matched by the query.
494
+
495
+ Sample message:
496
+
497
+ msg = {
498
+ type: "removeEvent",
499
+ query: {
500
+ id: "idOfDomElement"
501
+ },
502
+ eventType: "click",
503
+ }
504
+ */
505
+ removeEvent ( msg . query , msg . eventType ) ;
506
+ }
507
+
445
508
function onStdout ( msg ) {
446
509
/*
447
510
Handle "normal" STDOUT output.
@@ -505,7 +568,7 @@ const polyplug = function() {
505
568
mutate : mutate ,
506
569
getElements : getElements ,
507
570
registerEvent : registerEvent ,
571
+ removeEvent : removeEvent ,
508
572
receiveMessage : receiveMessage
509
573
}
510
574
} ;
511
-
0 commit comments