phyloio 2.1.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/Examples/Website/phyloio.html +73 -71
  2. package/Examples/Website/src_worker_bcn_js.phylo.js +8093 -0
  3. package/Examples/Website/src_worker_distance_js.phylo.js +6257 -0
  4. package/README.md +16 -2
  5. package/dist/phylo.js +7 -7
  6. package/dist/src_worker_bcn_js.phylo.js +2 -2
  7. package/dist/src_worker_distance_js.phylo.js +1 -1
  8. package/{src_phylo_compare → dist-jest}/phylo.js +68 -132
  9. package/{src_phylo_compare → dist-jest}/src_utils_js.phylo.js +1 -1
  10. package/dist-jest/src_worker_bcn_js.phylo.js +350 -0
  11. package/dist-jest/src_worker_distance_js.phylo.js +219 -0
  12. package/{src_phylo_compare/vendors-node_modules_biojs-io-newick_src_index_js-node_modules_minhashjs_index_js.phylo.js → dist-jest/vendors-node_modules_biojs-io-newick_src_index_js-node_modules_minhashjs_index_js-node_module-7b40e5.phylo.js} +25 -15
  13. package/package-lock.json +19607 -0
  14. package/package.json +1 -1
  15. package/rerooting.test.js +297 -0
  16. package/src/api.js +19 -9
  17. package/src/container.js +408 -64
  18. package/src/interface.css +6 -0
  19. package/src/interface.js +371 -207
  20. package/src/model.js +19 -20
  21. package/src/tmp +12 -0
  22. package/src/utils.js +31 -1
  23. package/src/viewer.js +177 -88
  24. package/src_phylo_compare/fonts/fa-brands-400.eot +0 -0
  25. package/src_phylo_compare/fonts/fa-brands-400.svg +0 -3717
  26. package/src_phylo_compare/fonts/fa-brands-400.ttf +0 -0
  27. package/src_phylo_compare/fonts/fa-brands-400.woff +0 -0
  28. package/src_phylo_compare/fonts/fa-brands-400.woff2 +0 -0
  29. package/src_phylo_compare/fonts/fa-regular-400.eot +0 -0
  30. package/src_phylo_compare/fonts/fa-regular-400.svg +0 -801
  31. package/src_phylo_compare/fonts/fa-regular-400.ttf +0 -0
  32. package/src_phylo_compare/fonts/fa-regular-400.woff +0 -0
  33. package/src_phylo_compare/fonts/fa-regular-400.woff2 +0 -0
  34. package/src_phylo_compare/fonts/fa-solid-900.eot +0 -0
  35. package/src_phylo_compare/fonts/fa-solid-900.svg +0 -5034
  36. package/src_phylo_compare/fonts/fa-solid-900.ttf +0 -0
  37. package/src_phylo_compare/fonts/fa-solid-900.woff +0 -0
  38. package/src_phylo_compare/fonts/fa-solid-900.woff2 +0 -0
  39. package/src_phylo_compare/fonts/fa-v4compatibility.ttf +0 -0
  40. package/src_phylo_compare/fonts/fa-v4compatibility.woff2 +0 -0
  41. package/src_phylo_compare/src_worker_bcn_js.phylo.js +0 -341
  42. package/src_phylo_compare/src_worker_distance_js.phylo.js +0 -227
  43. package/src_phylo_compare.zip +0 -0
  44. /package/{src_phylo_compare → dist-jest}/vendors-node_modules_d3_index_js-node_modules_file-saver_dist_FileSaver_min_js.phylo.js +0 -0
package/src/container.js CHANGED
@@ -3,7 +3,7 @@ import Model from './model.js'
3
3
  import Interface from "./interface";
4
4
  import * as bootstrap from "bootstrap";
5
5
  import * as d3 from "d3";
6
- const { build_table, save_file_as } = require('./utils.js')
6
+ const { build_table, save_file_as, colorDifference } = require('./utils.js')
7
7
  var parser = require("biojs-io-newick");
8
8
 
9
9
 
@@ -24,6 +24,7 @@ export default class Container {
24
24
  this.current_model = 0; // current model index
25
25
  this.viewer = new Viewer(this); // attach Viewer()
26
26
  this.history_actions = [] // for Undo feature
27
+ this.undone_actions = [] // for Undo feature
27
28
  this.api = api
28
29
  this.message_loader = null
29
30
 
@@ -38,14 +39,24 @@ export default class Container {
38
39
 
39
40
  }
40
41
 
41
- add_action(name, fn_object, counter_fn, argu, refresh_interface){
42
+ add_action(undo, redo, refresh_interface){
42
43
 
43
- var refresh_interface = (typeof refresh_interface !== 'undefined') ? refresh_interface : false;
44
+ /* undo and redo object - {'name': X, 'fonct': X, 'fonction_obj': X, 'argu': X} */
44
45
 
45
- if (!this.api.undoing){
46
- this.history_actions.push({'name': name, 'fonct':counter_fn, 'fonction_obj':fn_object, 'argu': argu, 'refresh_interface' : refresh_interface})
46
+ if (this.api.undoing) {
47
+ return
47
48
  }
48
49
 
50
+
51
+ this.history_actions.push(
52
+ {
53
+ 'undo': undo,
54
+ 'redo': redo,
55
+ 'refresh_interface' : (typeof refresh_interface !== 'undefined') ? refresh_interface : false,
56
+ }
57
+ )
58
+
59
+
49
60
  }
50
61
 
51
62
  get_last_action(){
@@ -53,7 +64,13 @@ export default class Container {
53
64
  }
54
65
 
55
66
  pop_last_action(){
56
- return this.history_actions.pop()
67
+ var pop = this.history_actions.pop()
68
+ this.undone_actions.push(pop)
69
+ return pop
70
+ }
71
+
72
+ pop_redo_action(){
73
+ return this.undone_actions.pop()
57
74
  }
58
75
 
59
76
 
@@ -145,7 +162,7 @@ export default class Container {
145
162
 
146
163
  if (this.current_model + offset >= 0 && this.current_model + offset <= this.models.length -1 ) {
147
164
 
148
- this.add_action('Change tree', this, this.shift_model, [-offset, store_old] )
165
+ //this.add_action('Change tree', this, this.shift_model, [-offset, store_old] )
149
166
 
150
167
  if (store_old){
151
168
  // store the current zoom information
@@ -191,7 +208,21 @@ export default class Container {
191
208
  var m = this.models[this.current_model];
192
209
 
193
210
  if (action === 'collapse') {
194
- this.add_action('Collapse this node', this, this.trigger_, [action, data, node] )
211
+
212
+ var name_undo,name_redo;
213
+
214
+ if (data.children && data.collapse){
215
+ name_undo = 'Collapse this node';
216
+ name_redo = 'Expand this node';
217
+ }
218
+ else {
219
+ name_undo = 'Expand this node';
220
+ name_redo = 'Collapse this node';
221
+ }
222
+
223
+ var undo = {'name': name_undo, 'fonction_obj': this, 'fonct': this.trigger_, 'argu': [action, data, node]}
224
+ var redo = {'name': name_redo, 'fonction_obj': this, 'fonct': this.trigger_, 'argu': [action, data, node]}
225
+ this.add_action(undo, redo)
195
226
  m.collapse(data)
196
227
  this.viewer.apply_collapse_from_data_to_d3(data, node)
197
228
  this.viewer.build_d3_cluster()
@@ -199,7 +230,11 @@ export default class Container {
199
230
 
200
231
  }
201
232
  else if (action === 'collapseAll') {
202
- this.add_action('Collapse All', this, this.trigger_, ['expandAll', data, node] )
233
+
234
+ var undo = {'name': 'Expand All', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': ['expandAll', data, node]}
235
+ var redo = {'name': 'Collapse All', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': [action, data, node]}
236
+ this.add_action(undo, redo)
237
+
203
238
  m.collapseAll(data, true)
204
239
  this.viewer.apply_collapseAll_from_data_to_d3(data, node)
205
240
  this.viewer.build_d3_cluster()
@@ -207,7 +242,11 @@ export default class Container {
207
242
 
208
243
  }
209
244
  else if (action === 'expandAll') {
210
- this.add_action('Expand All', this, this.trigger_, ['collapseAll', data, node] )
245
+
246
+ var undo = {'name': 'Collapse All', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': ['collapseAll', data, node]}
247
+ var redo = {'name': 'Expand All', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': [action, data, node]}
248
+ this.add_action(undo, redo)
249
+
211
250
  m.collapseAll(data, false)
212
251
  this.viewer.apply_expandAll_from_data_to_d3(data, node)
213
252
  this.viewer.build_d3_cluster()
@@ -215,7 +254,11 @@ export default class Container {
215
254
 
216
255
  }
217
256
  else if (action === 'swap') {
218
- this.add_action('Swap', this, this.trigger_, ['unswap', data, node] )
257
+
258
+ var undo = {'name': 'Unswap', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': ['unswap', data, node]}
259
+ var redo = {'name': 'Swap', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': [action, data, node]}
260
+ this.add_action(undo, redo)
261
+
219
262
  m.swap_subtrees(data)
220
263
  this.viewer.apply_swap_from_data_to_d3(data, node)
221
264
  this.viewer.build_d3_cluster()
@@ -233,7 +276,10 @@ export default class Container {
233
276
  }
234
277
  else if (action === 'reroot'){
235
278
 
236
- this.add_action('Reroot', this, this.trigger_, ['reroot', this.viewer.hierarchy.children[0].data, null] )
279
+ var undo = {'name': 'Reroot', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': ['reroot', this.viewer.hierarchy.children[0].data, null]}
280
+ var redo = {'name': 'Reroot', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': [action, data, node]}
281
+ this.add_action(undo, redo)
282
+
237
283
  m.reroot(data)
238
284
  m.rooted = true
239
285
  this.viewer.set_data(m)
@@ -255,7 +301,12 @@ export default class Container {
255
301
  }
256
302
  else if (action === 'trim'){
257
303
  var untrim_data = m.trim(data.data)
258
- this.add_action('Trim', this, this.trigger_, ['untrim', untrim_data, null] )
304
+
305
+
306
+ var undo = {'name': 'Untrim', 'fonction_obj': this, 'fonct': this.trigger_, 'argu':['untrim', untrim_data, null]}
307
+ var redo = {'name': 'Trim', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': [action, data, node]}
308
+ this.add_action(undo, redo)
309
+
259
310
  this.viewer.set_data(m)
260
311
  m.hierarchy_mockup = m.build_hierarchy_mockup()
261
312
  m.table = build_table(m.hierarchy_mockup)
@@ -282,7 +333,10 @@ export default class Container {
282
333
  }
283
334
  else if (action === 'force_show_label'){
284
335
 
285
- this.add_action('Show Label', this, this.trigger_, ['force_show_label', data, node] )
336
+ var undo = {'name': 'Toggle Label', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': [action, data, node]}
337
+ var redo = {'name': 'Toggle Label', 'fonction_obj': this, 'fonct': this.trigger_, 'argu': [action, data, node]}
338
+ this.add_action(undo, redo)
339
+
286
340
  m.toggle_show_label(data)
287
341
  this.viewer.apply_show_label_from_data_to_d3(data, node)
288
342
  this.viewer.build_d3_cluster()
@@ -290,9 +344,52 @@ export default class Container {
290
344
 
291
345
 
292
346
  }
347
+ else if (action === 'BCN'){
348
+
349
+ var other_container = this.api.bound_container[0] === this ? this.api.bound_container[1] : this.api.bound_container[0]
350
+
351
+ // get BCN node
352
+ var target_node = node.data.elementBCN[other_container.viewer.model.uid]
353
+
354
+ if (!target_node){
355
+ console.log('No BCN node found for this container')
356
+ return
357
+ }
358
+
359
+ var target_hierarchy = this.getHierarchyNodeFromModelNode(target_node, other_container.viewer.hierarchy)
360
+
361
+
362
+ other_container.expandToRoot(target_node)
363
+ other_container.viewer.centerNode(target_hierarchy)
364
+
365
+ target_node._show_BCN = true
366
+ other_container.viewer.blinking = 6
367
+ other_container.viewer.render(other_container.viewer.hierarchy)
368
+
369
+ }
293
370
 
294
371
  }
295
372
 
373
+ expandToRoot(node_model ) {
374
+
375
+ var model = this.viewer.model;
376
+ var hierarchy = this.viewer.hierarchy;
377
+
378
+ var node = node_model
379
+ while (node) {
380
+ model.collapse(node, false)
381
+
382
+ var node_hierarchy = this.getHierarchyNodeFromModelNode(node, hierarchy)
383
+ this.viewer.apply_collapse_from_data_to_d3(node, node_hierarchy)
384
+ node = node.parent; // Move to the parent node
385
+ }
386
+
387
+ }
388
+
389
+
390
+
391
+
392
+
296
393
  // collapse all node from depth
297
394
  collapse_depth(depth, tree){
298
395
 
@@ -334,109 +431,336 @@ export default class Container {
334
431
  collapse_node_not_colored(){
335
432
 
336
433
  var model = this.models[this.current_model];
337
- var viewer = this.viewer;
434
+ var viewer = this.viewer;
435
+ var f_pre, f_post;
338
436
 
339
- var f_pre = function(node, children){
437
+ var is_leaf = function(node) {
438
+ return !node.children && !node._children;
439
+ }
440
+
441
+ switch (model.settings.selected_collapse_uncolored) {
442
+
443
+ case 'Leaves':
340
444
 
341
- node.colored = false;
445
+ f_pre = function(node, children){
342
446
 
343
- var acc_node = node.data.extended_informations[model.settings.style.color_accessor['node']]
344
- var acc_leaf = node.data.extended_informations[model.settings.style.color_accessor['leaf']]
447
+ node.colored = false;
448
+ node.data.colored = false;
449
+
450
+ if (is_leaf(node) && node.data.extended_informations[model.settings.style.color_accessor['leaf']] !== undefined ){
451
+ node.colored = true;
452
+ node.data.colored = true;
453
+ }
345
454
 
346
- if (acc_node !== undefined || acc_leaf !== undefined ){
347
- node.colored = true;
348
455
  }
349
456
 
350
- }
457
+ f_post = function(child, node){
351
458
 
352
- var f_post = function(child, node){
459
+ // go through node.data.leaves and check if one colored break
460
+ var leaves = child.data.leaves ? child.data.leaves : []
461
+ for (const leafKey in leaves) {
462
+ const leaf = leaves[leafKey];
463
+ if (leaf.colored) {
464
+ return
465
+ }
466
+ }
467
+
468
+ model.collapse(child.data, true)
469
+ viewer.apply_collapse_from_data_to_d3(child.data, child)
470
+ }
353
471
 
354
- if (child.children || child._children){
472
+ break;
355
473
 
356
- var children_list = child.children ? child.children : child._children
474
+ case 'Nodes':
357
475
 
358
- var colored = false;
359
- for (const childrenListKey in children_list) {
476
+ var f_pre = function(node, children){
360
477
 
361
- var e = children_list[childrenListKey]
478
+ node.colored = false;
479
+ node.data.colored = false;
362
480
 
363
- if (e.colored){
364
- colored = true;
365
- break
481
+ if ( !is_leaf(node) && node.data.extended_informations[model.settings.style.color_accessor['node']] !== undefined ){
482
+ node.colored = true;
483
+ node.data.colored = true;
366
484
  }
367
485
 
368
486
  }
369
487
 
488
+ var f_post = function(child, node){
489
+
490
+ if (is_leaf(child)){ return }
491
+
492
+ var children_list = child.children ? child.children : child._children
493
+
494
+ for (const childrenListKey in children_list) {
495
+
496
+ var e = children_list[childrenListKey]
497
+
498
+ if (is_leaf(e)){continue}
499
+
500
+ if (e.colored) {
501
+ return
502
+ }
503
+
504
+ }
370
505
 
371
- if (colored){
372
- model.collapse(child.data, false)
373
- child.colored = true;
374
- }
375
- else {
376
506
  model.collapse(child.data, true)
377
- child.colored = false;
507
+ viewer.apply_collapse_from_data_to_d3(child.data, child)
508
+ }
509
+
510
+ break;
511
+ case 'Both':
512
+
513
+ var f_pre = function(node, children){
514
+
515
+ node.colored = false;
516
+ node.data.colored = false;
517
+
518
+ if ( !is_leaf(node) && node.data.extended_informations[model.settings.style.color_accessor['node']] !== undefined ){
519
+ node.colored = true;
520
+ node.data.colored = true;
521
+ }
522
+ else if (is_leaf(node) && node.data.extended_informations[model.settings.style.color_accessor['leaf']] !== undefined ){
523
+ node.colored = true;
524
+ node.data.colored = true;
525
+ }
378
526
 
379
527
  }
380
- viewer.apply_collapse_from_data_to_d3(child.data, child)
381
- }
382
528
 
529
+ var f_post = function(child, node){
530
+
531
+ if (is_leaf(child)){return}
532
+
533
+ var children_list = child.children ? child.children : child._children
534
+
535
+ for (const childrenListKey in children_list) {
536
+
537
+ var e = children_list[childrenListKey]
538
+
539
+ if (e.colored) {
540
+ return
541
+ }
542
+
543
+ }
544
+
545
+ model.collapse(child.data, true)
546
+ viewer.apply_collapse_from_data_to_d3(child.data, child)
547
+ }
548
+
549
+ break;
550
+ default:
551
+ console.log('Unknown collapse option: ' + model.settings.selected_collapse_uncolored)
552
+ return;
383
553
 
384
554
  }
385
555
 
386
- this.models[this.current_model].traverse_hierarchy(this.viewer.hierarchy,f_pre, f_post)
556
+ this.models[this.current_model].traverse_hierarchy(this.viewer.hierarchy,f_pre, f_post)
387
557
 
388
558
  }
389
559
 
560
+ monocolored_check_and_collapse(colors,child ){
561
+
562
+ var model = this.models[this.current_model]
563
+
564
+ switch (colors.size) {
565
+ case 0:
566
+ break; // no color, do nothing
567
+ case 1:
568
+ model.collapse(child.data, true)
569
+ this.viewer.apply_collapse_from_data_to_d3(child.data, child)
570
+ break;
571
+ default:
572
+ // compute the all pair of colorDifference in colors. If one above 10% return
573
+ var colorArray = Array.from(colors)
574
+ for (let i = 0; i < colorArray.length; i++) {
575
+ for (let j = i + 1; j < colorArray.length; j++) {
576
+ if (colorDifference(colorArray[i], colorArray[j]) > 0.05) {
577
+ return; // multiple colors, do not collapse
578
+ }
579
+ }
580
+ }
581
+ model.collapse(child.data, true)
582
+ this.viewer.apply_collapse_from_data_to_d3(child.data, child)
583
+ break
584
+ }
585
+ }
586
+
390
587
  collapse_node_same_color(){
391
588
 
589
+ var that = this
590
+
392
591
  var model = this.models[this.current_model];
393
592
  var viewer = this.viewer;
394
593
  var compared_model = viewer.get_compared_model()
594
+ var f_pre, f_post;
395
595
 
396
- var f_pre = function(node, children){
596
+ var is_leaf = function(node) {
597
+ return !node.children && !node._children;
598
+ }
397
599
 
398
- node.colored = false;
399
600
 
400
- var acc_node = node.data.extended_informations[model.settings.style.color_accessor['node']]
401
- var acc_leaf = node.data.extended_informations[model.settings.style.color_accessor['leaf']]
601
+ switch (model.settings.selected_collapse_monocolored) {
402
602
 
403
- if (acc_node !== undefined || acc_leaf !== undefined ){
404
- node.colored = true;
405
- node.renderedColor = viewer.color_edge(node, compared_model);
406
- node.coloredValue = node.data.extended_informations[model.settings.style.color_accessor['node']];
407
- }
603
+ case 'Leaves':
408
604
 
409
- }
605
+ f_pre = function(node, children){
410
606
 
411
- var f_post = function(child, node){
607
+ node.renderedColor = false;
608
+ node.data.renderedColor = false;
412
609
 
413
- if (child.children || child._children){
610
+ if (is_leaf(node) && node.data.extended_informations[model.settings.style.color_accessor['leaf']] !== undefined ){
611
+ node.renderedColor = viewer.get_color_label(node)
612
+ node.data.renderedColor = viewer.get_color_label(node)
414
613
 
415
- var children_list = child.children ? child.children : child._children
614
+ }
416
615
 
417
- var renderedColors = Array.from(children_list).filter(e => e.coloredValue).map(e => e.coloredValue)
616
+ }
418
617
 
419
- // check if difference between min and max value > 10% of the max value
420
- var min = Math.min(...renderedColors)
421
- var max = Math.max(...renderedColors)
422
- var unicolored = (max - min) < 0.1 * max
618
+ f_post = function(child, node){
423
619
 
620
+ var colors = new Set()
621
+
622
+ var leaves = child.data.leaves ? child.data.leaves : []
623
+
624
+ for (const leafKey in leaves) {
625
+ const leaf = leaves[leafKey];
626
+
627
+ if (!leaf.renderedColor) {
628
+ continue
629
+ }
630
+
631
+ colors.add(leaf.renderedColor)
632
+ }
633
+
634
+
635
+
636
+ that.monocolored_check_and_collapse(colors,child )
637
+
638
+ viewer.apply_collapse_from_data_to_d3(child.data, child)
424
639
 
425
- if (unicolored){
426
- model.collapse(child.data, true)
427
640
  }
428
- else {
429
- model.collapse(child.data, false)
641
+
642
+ break;
643
+
644
+ case 'Nodes':
645
+
646
+ f_pre = function(node, children){
647
+
648
+
649
+ node.renderedColor = false;
650
+ node.data.renderedColor = false;
651
+
652
+ if ( !is_leaf(node) && node.data.extended_informations[model.settings.style.color_accessor['node']] !== undefined ){
653
+ node.renderedColor = viewer.color_edge(node, compared_model);
654
+ node.data.renderedColor = viewer.color_edge(node, compared_model);
655
+ }
430
656
 
431
657
  }
432
- viewer.apply_collapse_from_data_to_d3(child.data, child)
433
- }
434
658
 
659
+ f_post = function(child, node){
660
+
661
+ if (is_leaf(child)){ return }
662
+
663
+ var children_list = child.children ? child.children : child._children
664
+
665
+ // check if all children_list are leaf return
666
+ if (children_list.length === 0 || children_list.every(is_leaf)) {
667
+ return;
668
+ }
669
+
670
+ child.colors = new Set()
671
+
672
+ for (const childrenListKey in children_list) {
673
+
674
+ var e = children_list[childrenListKey]
675
+
676
+ if (is_leaf(e)){continue}
677
+
678
+
679
+ if (e.colors){
680
+ child.colors = new Set([...child.colors, ...e.colors]);
681
+
682
+ }
683
+ else if (e.renderedColor){
684
+ child.colors.add(e.renderedColor)
685
+ }
686
+ else{
687
+ child.colors = new Set()
688
+ return
689
+ }
690
+
691
+
692
+ }
693
+
694
+ that.monocolored_check_and_collapse(child.colors,child )
695
+
696
+
697
+ }
698
+
699
+ break;
700
+
701
+ case 'Both':
702
+
703
+ f_pre = function(node, children){
704
+
705
+
706
+ node.renderedColor = false;
707
+ node.data.renderedColor = false;
708
+
709
+ if ( is_leaf(node) && node.data.extended_informations[model.settings.style.color_accessor['node']] !== undefined ){
710
+ node.renderedColor = viewer.color_edge(node, compared_model);
711
+ node.data.renderedColor = viewer.color_edge(node, compared_model);
712
+ }
713
+ else if (is_leaf(node) && node.data.extended_informations[model.settings.style.color_accessor['leaf']] !== undefined ){
714
+ node.renderedColor = viewer.get_color_label(node)
715
+ node.data.renderedColor = viewer.get_color_label(node)
716
+ }
717
+
718
+ }
719
+
720
+ f_post = function(child, node){
721
+
722
+ if (is_leaf(child)){ return }
723
+
724
+ var children_list = child.children ? child.children : child._children
725
+
726
+ child.colors = new Set()
727
+
728
+ for (const childrenListKey in children_list) {
729
+
730
+ var e = children_list[childrenListKey]
731
+
732
+ if (e.colors){
733
+ child.colors = new Set([...child.colors, ...e.colors]);
734
+
735
+ }
736
+ else if (e.renderedColor){
737
+ child.colors.add(e.renderedColor)
738
+ }
739
+ else{
740
+ child.colors = new Set()
741
+ return
742
+ }
743
+
744
+
745
+
746
+ }
747
+
748
+ that.monocolored_check_and_collapse(child.colors,child )
749
+
750
+ }
751
+
752
+ break;
753
+ default:
754
+ console.log('Unknown collapse option: ' + model.settings.selected_collapse_uncolored)
755
+ return;
435
756
 
436
757
  }
437
758
 
438
759
  this.models[this.current_model].traverse_hierarchy(this.viewer.hierarchy,f_pre, f_post)
439
760
 
761
+
762
+
763
+
440
764
  }
441
765
 
442
766
  highlight_node(name){
@@ -845,6 +1169,26 @@ export default class Container {
845
1169
 
846
1170
  }
847
1171
 
1172
+ traverseAllNodes(node, callback) {
1173
+ callback(node); // Apply the callback to the current node
1174
+ const children = node.children || node._children; // Include both expanded and collapsed nodes
1175
+ if (children) {
1176
+ children.forEach((child) => this.traverseAllNodes(child, callback));
1177
+ }
1178
+ }
1179
+
1180
+ getHierarchyNodeFromModelNode(modelNode, hierarchy) {
1181
+ let equivalentNode = null;
1182
+
1183
+ this.traverseAllNodes(hierarchy, (d) => {
1184
+ if (d.data === modelNode) {
1185
+ equivalentNode = d;
1186
+ }
1187
+ });
1188
+
1189
+ return equivalentNode;
1190
+ }
1191
+
848
1192
 
849
1193
 
850
1194
 
package/src/interface.css CHANGED
@@ -22,6 +22,12 @@
22
22
  height: 56px;
23
23
  }
24
24
 
25
+ .square_button.mini{
26
+
27
+ width: 42px;
28
+ height: 42px;
29
+ }
30
+
25
31
  .square_button:hover{
26
32
  background-color: #ddd;
27
33
  }