@@ -11,14 +11,7 @@ HTMLWidgets.widget({
11
11
// devtools::use_data(Schema, overwrite = T, internal = T)
12
12
// console.log(JSON.stringify(Plotly.PlotSchema.get()));
13
13
14
- return {
15
- // Push JavaScript closures onto this list, and renderValue
16
- // will pop them off and run them one at a time the next
17
- // time it runs. Use this to dispose of e.g. old event
18
- // registrations.
19
- onNextRender : [ ]
20
- } ;
21
-
14
+ return { } ;
22
15
} ,
23
16
24
17
resize : function ( el , width , height , instance ) {
@@ -30,11 +23,6 @@ HTMLWidgets.widget({
30
23
} ,
31
24
32
25
renderValue : function ( el , x , instance ) {
33
-
34
- // Release previously registered crosstalk event listeners
35
- while ( instance . onNextRender . length > 0 ) {
36
- instance . onNextRender . pop ( ) ( ) ;
37
- }
38
26
39
27
var shinyMode ;
40
28
if ( typeof ( window ) !== "undefined" ) {
@@ -317,7 +305,63 @@ HTMLWidgets.widget({
317
305
}
318
306
}
319
307
320
- if ( allSets . length > 0 ) {
308
+ // register event listeners for all sets
309
+ for ( var i = 0 ; i < allSets . length ; i ++ ) {
310
+
311
+ var set = allSets [ i ] ;
312
+ var selection = new crosstalk . SelectionHandle ( set ) ;
313
+ var filter = new crosstalk . FilterHandle ( set ) ;
314
+
315
+ var filterChange = function ( e ) {
316
+ removeBrush ( el ) ;
317
+ traceManager . updateFilter ( set , e . value ) ;
318
+ } ;
319
+ filter . on ( "change" , filterChange ) ;
320
+
321
+
322
+ var selectionChange = function ( e ) {
323
+
324
+ // array of "event objects" tracking the selection history
325
+ // this is used to avoid adding redundant selections
326
+ var selectionHistory = crosstalk . var ( "plotlySelectionHistory" ) . get ( ) || [ ] ;
327
+
328
+ // Construct an event object "defining" the current event.
329
+ var event = {
330
+ receiverID : traceManager . gd . id ,
331
+ plotlySelectionColour : crosstalk . group ( set ) . var ( "plotlySelectionColour" ) . get ( )
332
+ } ;
333
+ event [ set ] = e . value ;
334
+ // TODO: is there a smarter way to check object equality?
335
+ if ( selectionHistory . length > 0 ) {
336
+ var ev = JSON . stringify ( event ) ;
337
+ for ( var i = 0 ; i < selectionHistory . length ; i ++ ) {
338
+ var sel = JSON . stringify ( selectionHistory [ i ] ) ;
339
+ if ( sel == ev ) {
340
+ return ;
341
+ }
342
+ }
343
+ }
344
+
345
+ // accumulate history for persistent selection
346
+ if ( ! x . highlight . persistent ) {
347
+ selectionHistory = [ event ] ;
348
+ } else {
349
+ selectionHistory . push ( event ) ;
350
+ }
351
+ crosstalk . var ( "plotlySelectionHistory" ) . set ( selectionHistory ) ;
352
+
353
+ // do the actual updating of traces, frames, and the selectize widget
354
+ traceManager . updateSelection ( set , e . value ) ;
355
+ // https://github.com/selectize/selectize.js/blob/master/docs/api.md#methods_items
356
+ if ( x . selectize ) {
357
+ if ( ! x . highlight . persistent || e . value === null ) {
358
+ selectize . clear ( true ) ;
359
+ }
360
+ selectize . addItems ( e . value , true ) ;
361
+ selectize . close ( ) ;
362
+ }
363
+ }
364
+ selection . on ( "change" , selectionChange ) ;
321
365
322
366
// Set a crosstalk variable selection value, triggering an update
323
367
graphDiv . on ( x . highlight . on , function turnOn ( e ) {
@@ -326,11 +370,9 @@ HTMLWidgets.widget({
326
370
// Keys are group names, values are array of selected keys from group.
327
371
for ( var set in selectedKeys ) {
328
372
if ( selectedKeys . hasOwnProperty ( set ) ) {
329
- crosstalk . group ( set ) . var ( "selection" )
330
- . set ( selectedKeys [ set ] . value , { sender : el } ) ;
373
+ selection . set ( selectedKeys [ set ] . value , { sender : el } ) ;
331
374
}
332
375
}
333
-
334
376
}
335
377
} ) ;
336
378
@@ -340,113 +382,59 @@ HTMLWidgets.widget({
340
382
// remove any selection history
341
383
crosstalk . var ( "plotlySelectionHistory" ) . set ( null ) ;
342
384
// trigger the actual removal of selection traces
343
- for ( var i = 0 ; i < allSets . length ; i ++ ) {
344
- crosstalk . group ( allSets [ i ] ) . var ( "selection" ) . set ( null , { sender : el } ) ;
345
- }
385
+ selection . set ( null , { sender : el } ) ;
346
386
} ) ;
347
-
348
-
349
- for ( var i = 0 ; i < allSets . length ; i ++ ) {
350
- ( function ( ) {
351
- var set = allSets [ i ] ;
352
- var grp = crosstalk . group ( set ) ;
353
387
354
- // Create a selectize widget for each group
355
- if ( x . selectize ) {
356
- var selectizeID = Object . keys ( x . selectize ) [ i ] ;
357
- var items = x . selectize [ selectizeID ] . items ;
358
- var first = [ { value : "" , label : "(All)" } ] ;
359
- var opts = {
360
- options : first . concat ( items ) ,
361
- searchField : "label" ,
362
- valueField : "value" ,
363
- labelField : "label" ,
364
- maxItems : 50
365
- } ;
366
- var select = $ ( "#" + selectizeID ) . find ( "select" ) [ 0 ] ;
367
- var selectize = $ ( select ) . selectize ( opts ) [ 0 ] . selectize ;
368
- // NOTE: this callback is triggered when *directly* altering
369
- // dropdown items
370
- selectize . on ( "change" , function ( ) {
371
- var currentItems = traceManager . groupSelections [ set ] || [ ] ;
372
- if ( ! x . highlight . persistent ) {
373
- removeBrush ( el ) ;
374
- for ( var i = 0 ; i < currentItems . length ; i ++ ) {
375
- selectize . removeItem ( currentItems [ i ] , true ) ;
376
- }
377
- }
378
- var newItems = selectize . items . filter ( function ( idx ) {
379
- return currentItems . indexOf ( idx ) < 0 ;
380
- } ) ;
381
- if ( newItems . length > 0 ) {
382
- traceManager . updateSelection ( set , newItems ) ;
383
- } else {
384
- // Item has been removed...
385
- // TODO: this logic won't work for dynamically changing palette
386
- traceManager . updateSelection ( set , null ) ;
387
- traceManager . updateSelection ( set , selectize . items ) ;
388
- }
389
- } ) ;
390
- }
391
-
392
-
393
- var crosstalkSelectionChange = function ( e ) {
394
-
395
- // array of "event objects" tracking the selection history
396
- // this is used to avoid adding redundant selections
397
- var selectionHistory = crosstalk . var ( "plotlySelectionHistory" ) . get ( ) || [ ] ;
398
-
399
- // Construct an event object "defining" the current event.
400
- var event = {
401
- receiverID : traceManager . gd . id ,
402
- plotlySelectionColour : crosstalk . group ( set ) . var ( "plotlySelectionColour" ) . get ( )
403
- } ;
404
- event [ set ] = e . value ;
405
- // TODO: is there a smarter way to check object equality?
406
- if ( selectionHistory . length > 0 ) {
407
- var ev = JSON . stringify ( event ) ;
408
- for ( var i = 0 ; i < selectionHistory . length ; i ++ ) {
409
- var sel = JSON . stringify ( selectionHistory [ i ] ) ;
410
- if ( sel == ev ) {
411
- return ;
412
- }
413
- }
414
- }
415
-
416
- // accumulate history for persistent selection
417
- if ( ! x . highlight . persistent ) {
418
- selectionHistory = [ event ] ;
419
- } else {
420
- selectionHistory . push ( event ) ;
421
- }
422
- crosstalk . var ( "plotlySelectionHistory" ) . set ( selectionHistory ) ;
423
-
424
-
425
- traceManager . updateSelection ( set , e . value ) ;
426
- // https://github.com/selectize/selectize.js/blob/master/docs/api.md#methods_items
427
- if ( x . selectize ) {
428
- if ( ! x . highlight . persistent || e . value === null ) {
429
- selectize . clear ( true ) ;
430
- }
431
- selectize . addItems ( e . value , true ) ;
432
- selectize . close ( ) ;
388
+ // register a callback for selectize so that there is bi-directional
389
+ // communication between the widget and direct manipulation events
390
+ if ( x . selectize ) {
391
+ var selectizeID = Object . keys ( x . selectize ) [ i ] ;
392
+ var items = x . selectize [ selectizeID ] . items ;
393
+ var first = [ { value : "" , label : "(All)" } ] ;
394
+ var opts = {
395
+ options : first . concat ( items ) ,
396
+ searchField : "label" ,
397
+ valueField : "value" ,
398
+ labelField : "label" ,
399
+ maxItems : 50
400
+ } ;
401
+ var select = $ ( "#" + selectizeID ) . find ( "select" ) [ 0 ] ;
402
+ var selectize = $ ( select ) . selectize ( opts ) [ 0 ] . selectize ;
403
+ // NOTE: this callback is triggered when *directly* altering
404
+ // dropdown items
405
+ selectize . on ( "change" , function ( ) {
406
+ var currentItems = traceManager . groupSelections [ set ] || [ ] ;
407
+ if ( ! x . highlight . persistent ) {
408
+ removeBrush ( el ) ;
409
+ for ( var i = 0 ; i < currentItems . length ; i ++ ) {
410
+ selectize . removeItem ( currentItems [ i ] , true ) ;
433
411
}
434
-
435
412
}
436
-
437
- grp . var ( "selection" ) . on ( "change" , crosstalkSelectionChange ) ;
438
-
439
-
440
- grp . var ( "filter" ) . on ( "change" , function crosstalk_filter_change ( e ) {
441
- removeBrush ( el ) ;
442
- traceManager . updateFilter ( set , e . value ) ;
413
+ var newItems = selectize . items . filter ( function ( idx ) {
414
+ return currentItems . indexOf ( idx ) < 0 ;
443
415
} ) ;
444
-
445
- } ) ( ) ;
416
+ if ( newItems . length > 0 ) {
417
+ traceManager . updateSelection ( set , newItems ) ;
418
+ } else {
419
+ // Item has been removed...
420
+ // TODO: this logic won't work for dynamically changing palette
421
+ traceManager . updateSelection ( set , null ) ;
422
+ traceManager . updateSelection ( set , selectize . items ) ;
423
+ }
424
+ } ) ;
446
425
}
426
+
427
+
428
+
429
+
430
+
431
+
432
+
433
+
447
434
}
448
- }
449
- } ) ;
435
+
436
+ } // end of renderValue
437
+ } ) ; // end of widget definition
450
438
451
439
/**
452
440
* @param graphDiv The Plotly graph div
0 commit comments