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/interface.js CHANGED
@@ -2,6 +2,7 @@ import * as fs from 'file-saver';
2
2
  import * as d3 from 'd3';
3
3
  import * as bootstrap from 'bootstrap';
4
4
  import * as d3_chrome from 'd3-scale-chromatic';
5
+ import {check_if_color} from "./utils";
5
6
 
6
7
  // D3 viewer Interface that render UI elements(buttons, slider, menu)
7
8
  export default class Interface {
@@ -47,6 +48,10 @@ export default class Interface {
47
48
  this.container_d3.selectAll(".empty_message").remove()
48
49
  this.container_d3.select('#histogram-legend').remove();
49
50
 
51
+ // remove old meta modal with document. function
52
+ document.querySelectorAll('#modal_meta_' + this.container_object.uid).forEach((el) => { el.remove() })
53
+ document.querySelectorAll('#exampleModal' + this.container_object.uid).forEach((el) => { el.remove() })
54
+
50
55
  this.container_d3.select("#menu-node").remove()
51
56
 
52
57
  /*
@@ -108,6 +113,9 @@ export default class Interface {
108
113
  this.add_meta()
109
114
  this.add_settings()
110
115
  this.add_undo()
116
+ this.add_redo()
117
+
118
+
111
119
 
112
120
  // COLOR LEGEND
113
121
  if (this.api.settings.compareMode || (this.viewer.model.settings.style.color_accessor['node'] !== null && this.viewer.model.settings.style.color_accessor['node'] !== 'Topology' )){
@@ -421,25 +429,27 @@ export default class Interface {
421
429
 
422
430
  <br>
423
431
 
424
- <div class="card">
425
432
 
426
- <div class="card-body">
427
-
428
- <h5> <b>Step 3 (Optional) : Add a mapping file </b>
429
- <a href="#" id='menu_help_add_tree' >
430
- <i class="bi-question-circle"></i>
431
- </a> </h5>
432
-
433
- <br>
434
-
435
- STEP3__
436
-
437
-
438
- </div>
439
-
440
-
441
- </div>
442
433
 
434
+ <div class="card">
435
+ <div class="card-body">
436
+ <div style="cursor: pointer;" id="toggleStep3">
437
+ <h5>
438
+ <b>Step 3 (Optional): Add a mapping file</b>
439
+ <a href="#" id="menu_help_add_tree">
440
+ <i class="bi-question-circle"></i>
441
+ </a>
442
+ <i class="bi-caret-down float-end" id="caretStep3"></i>
443
+ <small class="float-end" id="expandStep3">Expand</small>
444
+ </h5>
445
+ </div>
446
+ <br>
447
+ <div id="collapseStep3" style="display: none;">
448
+ STEP3__
449
+ </div>
450
+ </div>
451
+ </div>
452
+
443
453
  <br>
444
454
 
445
455
  <div style="margin: auto; width: fit-content;">
@@ -451,28 +461,29 @@ export default class Interface {
451
461
  </div>
452
462
 
453
463
  </div>
454
-
464
+
465
+
455
466
 
456
467
  `
457
468
 
458
469
 
459
470
  }
460
471
 
461
- add_data_icon(){
472
+ add_data_icon() {
462
473
 
463
474
  this.container_d3.select("#exampleModal" + this.container_object.uid).remove()
464
475
 
465
476
  var b = this.top_left.append('button')
466
477
  .attr('class', ' dashed_button')
467
- .attr('id', 'buttonmodal_' + this.container_object.div_id )
478
+ .attr('id', 'buttonmodal_' + this.container_object.div_id)
468
479
  .attr('data-bs-toggle', 'modal')
469
480
  .attr('data-bs-target', '#exampleModal' + this.container_object.uid)
470
481
  .attr('data-bs-placement', 'right')
471
482
  .attr('title', 'Add a new tree')
472
483
  .append("div")
473
- .attr("class","label")
484
+ .attr("class", "label")
474
485
 
475
- b.html(" <i class='bi bi-plus' style='color:#888'></i> Add tree")
486
+ b.html(" <i class='bi bi-plus' style='color:#888'></i> Add tree")
476
487
 
477
488
  let mod_html = this.get_modal_template()
478
489
 
@@ -482,7 +493,6 @@ export default class Interface {
482
493
  mod_html = mod_html.replace('STEP3__', this.get_modal_meta_corpus())
483
494
 
484
495
 
485
-
486
496
  mod_html = mod_html.replace('exampleFormControlTextarea1s', 'exampleFormControlTextarea1s' + this.container_object.uid)
487
497
  mod_html = mod_html.replace('add_tree_file_input', 'add_tree_file_input' + this.container_object.uid)
488
498
  mod_html = mod_html.replace('exampleModal', 'exampleModal' + this.container_object.uid)
@@ -506,32 +516,53 @@ export default class Interface {
506
516
  mod_html = mod_html.replace('mapping_check_leaf', 'tree_adder_mapping_check_leaf' + this.container_object.uid)
507
517
  mod_html = mod_html.replace('mapping_apply_to_all', 'tree_adder_mapping_apply_to_all' + this.container_object.uid)
508
518
 
519
+
509
520
  mod_html = mod_html.replaceAll('add_mapping_ref_select', 'add_mapping_ref_select' + this.container_object.uid)
510
521
 
511
- document.getElementById(this.container_object.div_id).insertAdjacentHTML('afterend',mod_html)
522
+ mod_html = mod_html.replace('collapseStep3', 'collapse3' + this.container_object.uid)
523
+ mod_html = mod_html.replace('toggleStep3', 'toggle3' + this.container_object.uid)
524
+ mod_html = mod_html.replace('caretStep3', 'caret3' + this.container_object.uid)
525
+ mod_html = mod_html.replace('expandStep3', 'expand3' + this.container_object.uid)
526
+
527
+
528
+ document.getElementById(this.container_object.div_id).insertAdjacentHTML('afterend', mod_html)
529
+
530
+ // Add code for the toggle functionality
512
531
 
532
+ const toggleElement = document.getElementById('toggle3' + this.container_object.uid);
533
+ const contentElement = document.getElementById('collapse3' + this.container_object.uid);
534
+ const caretElement = document.getElementById('caret3' + this.container_object.uid);
535
+ const expandTextElement = document.getElementById('expand3' + this.container_object.uid);
536
+
537
+ toggleElement.addEventListener('click', () => {
538
+ const isHidden = contentElement.style.display === 'none';
539
+ contentElement.style.display = isHidden ? 'block' : 'none';
540
+ caretElement.className = isHidden ? 'bi-caret-up float-end' : 'bi-caret-down float-end';
541
+ expandTextElement.textContent = isHidden ? 'Collapse' : 'Expand';
542
+ });
513
543
 
514
544
 
515
- var modmod = document.getElementById('exampleModal'+ this.container_object.uid);
516
545
 
517
- var thaty = this
546
+ var modmod = document.getElementById('exampleModal' + this.container_object.uid);
518
547
 
519
- const add_tree_helpers = function(container_object, str, format, mapping){
548
+ var thaty = this
549
+
550
+ const add_tree_helpers = function (container_object, str, format, mapping) {
520
551
 
521
552
  var mapping = (typeof mapping == 'undefined') ? false : mapping;
522
553
 
523
- container_object.add_tree(str, {'data_type':format})
524
- container_object.current_model = container_object.models.length-1
554
+ container_object.add_tree(str, {'data_type': format})
555
+ container_object.current_model = container_object.models.length - 1
525
556
 
526
557
  // check if internal_for_branch is checked or not and setup default_internal_label_is_for_branch
527
558
 
528
- if (document.getElementById('internal_for_branch' + container_object.uid).checked){
559
+ if (document.getElementById('internal_for_branch' + container_object.uid).checked) {
529
560
  container_object.models[container_object.current_model].settings.edge_related_data.push('Data');
530
561
  }
531
562
 
532
- if (mapping !== false){
563
+ if (mapping !== false) {
533
564
 
534
- if (mapping.parameters.apply_to_all){
565
+ if (mapping.parameters.apply_to_all) {
535
566
 
536
567
  // apply add_meta_leaves to all models in the container
537
568
  container_object.models.forEach((model) => {
@@ -539,10 +570,10 @@ export default class Interface {
539
570
  model.settings.use_meta_for_leaf = mapping.parameters.use_meta_for_leaf
540
571
  model.settings.use_meta_for_node = mapping.parameters.use_meta_for_node
541
572
 
542
- if (mapping.parameters.use_meta_for_leaf){
573
+ if (mapping.parameters.use_meta_for_leaf) {
543
574
  model.add_meta_leaves(mapping.meta, mapping.parameters.headers, container_object.api, mapping.parameters.reference)
544
575
  }
545
- if (mapping.parameters.use_meta_for_node){
576
+ if (mapping.parameters.use_meta_for_node) {
546
577
  model.add_meta_nodes(mapping.meta, mapping.parameters.headers, container_object.api, mapping.parameters.reference)
547
578
  }
548
579
 
@@ -557,12 +588,11 @@ export default class Interface {
557
588
  moddy.settings.use_meta_for_leaf = mapping.parameters.use_meta_for_leaf
558
589
  moddy.settings.use_meta_for_node = mapping.parameters.use_meta_for_node
559
590
 
560
-
561
- if (moddy.settings.use_meta_for_leaf){
591
+ if (moddy.settings.use_meta_for_leaf) {
562
592
  moddy.add_meta_leaves(mapping.meta, mapping.parameters.headers, container_object.api, mapping.parameters.reference)
563
593
  }
564
594
 
565
- if (moddy.settings.use_meta_for_node){
595
+ if (moddy.settings.use_meta_for_node) {
566
596
  moddy.add_meta_nodes(mapping.meta, mapping.parameters.headers, container_object.api, mapping.parameters.reference)
567
597
  }
568
598
 
@@ -573,7 +603,7 @@ export default class Interface {
573
603
  }
574
604
 
575
605
 
576
- document.querySelector('#exampleModal'+ container_object.uid).style.display = 'none'
606
+ document.querySelector('#exampleModal' + container_object.uid).style.display = 'none'
577
607
  document.querySelectorAll('.modal-backdrop').forEach(elem => {
578
608
  elem.parentNode.removeChild(elem);
579
609
  });
@@ -583,17 +613,17 @@ export default class Interface {
583
613
  container_object.viewer.render(container_object.viewer.hierarchy);
584
614
  //container_object.viewer.update_collapse_level(container_object.models[container_object.current_model].settings.collapse_level)
585
615
 
586
- if (mapping){
616
+ if (mapping) {
587
617
  thaty.open_color_settings()
588
618
  }
589
619
 
590
620
 
591
- if (thaty.api.settings.compute_distance && thaty.api.bound_container.includes(thaty)){
621
+ if (thaty.api.settings.compute_distance && thaty.api.bound_container.includes(thaty)) {
592
622
  thaty.api.send_worker_distance()
593
623
  }
594
624
  }
595
625
 
596
- const add_data_from_modal = (format) => {
626
+ const add_data_from_modal = (format) => {
597
627
 
598
628
  // mapping information
599
629
  var mapping_file = document.getElementById('tree_adder_modal_add_mapping_file_input' + that.container_object.uid).files[0];
@@ -601,7 +631,7 @@ export default class Interface {
601
631
 
602
632
  let s = document.getElementById("exampleFormControlTextarea1s" + this.container_object.uid).value
603
633
 
604
- if (s.length > 0){
634
+ if (s.length > 0) {
605
635
 
606
636
  if (mapping_file) {
607
637
 
@@ -615,30 +645,29 @@ export default class Interface {
615
645
  var meta = []
616
646
  var ref_id = parameters.reference
617
647
 
618
- if (mapping_file.name.split('.').pop() == 'tsv'){
619
- d3.tsvParse(event.target.result, (d) => {meta[d[ref_id]] = d});
648
+ if (mapping_file.name.split('.').pop() == 'tsv') {
649
+ d3.tsvParse(event.target.result, (d) => {
650
+ meta[d[ref_id]] = d
651
+ });
652
+ } else {
653
+ d3.csvParse(event.target.result, (d) => {
654
+ meta[d[ref_id]] = d
655
+ });
620
656
  }
621
- else{
622
- d3.csvParse(event.target.result, (d) => {meta[d[ref_id]] = d});
623
- }
624
-
625
657
 
626
658
 
627
659
  add_tree_helpers(this.container_object, s, format, {'meta': meta, 'parameters': parameters})
628
660
  return
629
661
 
630
662
 
631
-
632
663
  });
633
664
  reader.readAsText(mapping_file);
634
665
 
635
666
 
636
- }
637
- else {
667
+ } else {
638
668
  add_tree_helpers(this.container_object, s, format)
639
- return}
640
-
641
-
669
+ return
670
+ }
642
671
 
643
672
 
644
673
  }
@@ -648,7 +677,7 @@ export default class Interface {
648
677
  if (file) {
649
678
  var reader = new FileReader();
650
679
  reader.readAsText(file, "UTF-8");
651
- reader.onload = (evt) => {
680
+ reader.onload = (evt) => {
652
681
 
653
682
  if (mapping_file) {
654
683
  var parameters = that.get_mapping_parameter_from_UI(true)
@@ -662,26 +691,31 @@ export default class Interface {
662
691
  var ref_id = parameters.reference
663
692
 
664
693
 
665
- if (mapping_file.name.split('.').pop() == 'tsv'){
666
- d3.tsvParse(event.target.result, (d) => {meta[d[ref_id]] = d});
667
- }
668
- else{
669
- d3.csvParse(event.target.result, (d) => {meta[d[ref_id]] = d});
694
+ if (mapping_file.name.split('.').pop() == 'tsv') {
695
+ d3.tsvParse(event.target.result, (d) => {
696
+ meta[d[ref_id]] = d
697
+ });
698
+ } else {
699
+ d3.csvParse(event.target.result, (d) => {
700
+ meta[d[ref_id]] = d
701
+ });
670
702
  }
671
703
 
672
- add_tree_helpers(this.container_object, evt.target.result, format, {'meta': meta, 'parameters': parameters})
704
+ add_tree_helpers(this.container_object, evt.target.result, format, {
705
+ 'meta': meta,
706
+ 'parameters': parameters
707
+ })
673
708
  return
674
709
 
675
710
 
676
-
677
711
  });
678
712
  reader.readAsText(mapping_file);
679
713
 
680
714
 
681
- }
682
- else {
715
+ } else {
683
716
  add_tree_helpers(this.container_object, evt.target.result, format)
684
- return}
717
+ return
718
+ }
685
719
 
686
720
 
687
721
  }
@@ -691,7 +725,6 @@ export default class Interface {
691
725
  }
692
726
 
693
727
 
694
-
695
728
  }
696
729
 
697
730
  document.getElementById('modal_add_tree_final_button' + this.container_object.uid).onclick = () => {
@@ -703,35 +736,34 @@ export default class Interface {
703
736
  }
704
737
 
705
738
  modmod.getElementsByClassName('t1')[0].onclick = () => {
706
- document.getElementById("exampleFormControlTextarea1s"+ this.container_object.uid).value = this.examples.small1
739
+ document.getElementById("exampleFormControlTextarea1s" + this.container_object.uid).value = this.examples.small1
707
740
  document.getElementById('add_tree_str_select' + this.container_object.uid).value = 'newick'
708
741
  };
709
742
 
710
743
  modmod.getElementsByClassName('t1')[0].onclick = () => {
711
- document.getElementById("exampleFormControlTextarea1s"+ this.container_object.uid).value = this.examples.small1
744
+ document.getElementById("exampleFormControlTextarea1s" + this.container_object.uid).value = this.examples.small1
712
745
  document.getElementById('add_tree_str_select' + this.container_object.uid).value = 'newick'
713
746
  };
714
747
 
715
748
  modmod.getElementsByClassName('t2')[0].onclick = () => {
716
- document.getElementById("exampleFormControlTextarea1s"+ this.container_object.uid).value = this.examples.small2
749
+ document.getElementById("exampleFormControlTextarea1s" + this.container_object.uid).value = this.examples.small2
717
750
  document.getElementById('add_tree_str_select' + this.container_object.uid).value = 'newick'
718
751
  };
719
752
 
720
753
  modmod.getElementsByClassName('tbig')[0].onclick = () => {
721
- document.getElementById("exampleFormControlTextarea1s"+ this.container_object.uid).value = this.examples.big
754
+ document.getElementById("exampleFormControlTextarea1s" + this.container_object.uid).value = this.examples.big
722
755
  document.getElementById('add_tree_str_select' + this.container_object.uid).value = 'newick'
723
756
  };
724
757
 
725
758
  modmod.getElementsByClassName('nhx_ex')[0].onclick = () => {
726
- document.getElementById("exampleFormControlTextarea1s"+ this.container_object.uid).value = this.examples.nhx
759
+ document.getElementById("exampleFormControlTextarea1s" + this.container_object.uid).value = this.examples.nhx
727
760
  document.getElementById('add_tree_str_select' + this.container_object.uid).value = 'nhx'
728
761
  };
729
762
 
730
763
 
731
764
  // META DATA UPLOADER
732
- document.getElementById('upload_mapping_validation'+ this.container_object.uid).style.display = 'none'
733
- document.getElementById('upload_mapping_close'+ this.container_object.uid).style.display = 'none'
734
-
765
+ document.getElementById('upload_mapping_validation' + this.container_object.uid).style.display = 'none'
766
+ document.getElementById('upload_mapping_close' + this.container_object.uid).style.display = 'none'
735
767
 
736
768
 
737
769
  var x = modmod.getElementsByClassName('card')
@@ -742,7 +774,7 @@ export default class Interface {
742
774
  // Add JS for modal corpus
743
775
  var that = this
744
776
 
745
- document.getElementById('tree_adder_modal_add_mapping_file_input' + this.container_object.uid).onchange = function() {
777
+ document.getElementById('tree_adder_modal_add_mapping_file_input' + this.container_object.uid).onchange = function () {
746
778
  let input = this.files[0];
747
779
 
748
780
  if (input) {
@@ -755,17 +787,17 @@ export default class Interface {
755
787
 
756
788
  reader.addEventListener("load", parseFile, false);
757
789
  reader.readAsText(input);
758
- function parseFile(){
790
+
791
+ function parseFile() {
759
792
 
760
793
  // load data
761
- if (input.name.split('.').pop() == 'tsv'){
762
- data = d3.tsvParse(reader.result, function(d){
794
+ if (input.name.split('.').pop() == 'tsv') {
795
+ data = d3.tsvParse(reader.result, function (d) {
763
796
  return d;
764
797
  });
765
- }
766
- else{
798
+ } else {
767
799
 
768
- data = d3.csvParse(reader.result, function(d){
800
+ data = d3.csvParse(reader.result, function (d) {
769
801
  return d;
770
802
  });
771
803
 
@@ -776,11 +808,13 @@ export default class Interface {
776
808
  var numerisator = {}
777
809
  numerisator['id'] = 'cat'
778
810
  data['columns'].forEach((currentElement) => {
779
- if (currentElement != 'id'){ numerisator[currentElement] = 'num'}
811
+ if (currentElement != 'id') {
812
+ numerisator[currentElement] = 'num'
813
+ }
780
814
  })
781
815
  data.forEach((currentElement) => {
782
816
  for (var key of Object.keys(numerisator)) {
783
- if (isNaN(currentElement[key])){
817
+ if (isNaN(currentElement[key])) {
784
818
  numerisator[key] = 'cat'
785
819
  }
786
820
  }
@@ -791,7 +825,7 @@ export default class Interface {
791
825
  var select = document.getElementById('add_mapping_ref_select' + that.container_object.uid)
792
826
  select.innerHTML = '';
793
827
 
794
- for (var key of Object.keys(numerisator)){
828
+ for (var key of Object.keys(numerisator)) {
795
829
  var opt = document.createElement('option');
796
830
  opt.value = key;
797
831
  opt.innerHTML = key;
@@ -799,13 +833,12 @@ export default class Interface {
799
833
  }
800
834
 
801
835
 
802
-
803
-
804
836
  // creates radios
805
- var radio_container = document.getElementById( 'tree_adder_mod_meta_card2_radio' + that.container_object.uid)
837
+ var radio_container = document.getElementById('tree_adder_mod_meta_card2_radio' + that.container_object.uid)
806
838
  radio_container.innerHTML = '';
807
839
 
808
- var get_el = function(){return `
840
+ var get_el = function () {
841
+ return `
809
842
 
810
843
  <div style = "padding: 12px 24px 0;"> <span><b style = "margin-right: 12px" > Column: </b> "NAME_"</span> <br>
811
844
 
@@ -824,7 +857,7 @@ export default class Interface {
824
857
  </div>
825
858
 
826
859
  <div class="form-check" style="margin-left: 24px">
827
- <input class="form-check-input" name="flexRadioDefault" type="radio" value="color" id="RADIO_3">
860
+ <input class="form-check-input" name="flexRadioDefault" type="radio" value="color" id="RADIO_3" ATTR_COLOR>
828
861
  <label class="form-check-label" for="RADIO_3">
829
862
  Color
830
863
  </label>
@@ -837,36 +870,43 @@ export default class Interface {
837
870
 
838
871
 
839
872
  </div>
840
- `}
873
+ `
874
+ }
841
875
 
842
- for (var key of Object.keys(numerisator)){
876
+ // clean potential old radiobox
877
+
878
+ for (var key of Object.keys(numerisator)) {
843
879
 
844
880
  var rad = get_el()
845
881
 
846
882
 
847
883
  rad = rad.replace('NAME_', key)
848
- rad = rad.replaceAll('flexRadioDefault', 'tree_adder_flexRadioDefault_' + key + that.container_object.uid )
849
- rad = rad.replace('RADIO_1', that.container_object.uid + 'mapping_header_radiotree_adder_1' + '__' + key )
850
- rad = rad.replace('RADIO_2', that.container_object.uid + 'mapping_header_radiotree_adder_2' + '__' + key )
851
- rad = rad.replace('RADIO_3', that.container_object.uid + 'mapping_header_radiotree_adder_3' + '__' + key )
884
+ rad = rad.replaceAll('flexRadioDefault', 'tree_adder_flexRadioDefault_' + key + that.container_object.uid)
885
+ rad = rad.replace('RADIO_1', that.container_object.uid + 'mapping_header_radiotree_adder_1' + '__' + key)
886
+ rad = rad.replace('RADIO_2', that.container_object.uid + 'mapping_header_radiotree_adder_2' + '__' + key)
887
+ rad = rad.replace('RADIO_3', that.container_object.uid + 'mapping_header_radiotree_adder_3' + '__' + key)
852
888
 
853
889
 
854
-
855
- if (numerisator[key] == 'num'){
890
+ if (numerisator[key] == 'num') {
856
891
  rad = rad.replace('ATTR_NUM', 'checked')
857
892
  rad = rad.replace('ATTR_CAT', '')
893
+ rad = rad.replace('ATTR_COLOR', '')
858
894
  }
859
- else{
895
+ if (check_if_color(key)) {
896
+ rad = rad.replace('ATTR_NUM', '')
897
+ rad = rad.replace('ATTR_CAT', '')
898
+ rad = rad.replace('ATTR_COLOR', 'checked')
899
+ } else {
860
900
  rad = rad.replace('ATTR_NUM', 'disabled')
861
901
  rad = rad.replace('ATTR_CAT', 'checked')
902
+ rad = rad.replace('ATTR_COLOR', '')
862
903
  }
863
904
 
864
905
 
865
-
866
- radio_container.insertAdjacentHTML('beforeend',rad)
906
+ radio_container.insertAdjacentHTML('beforeend', rad)
867
907
 
868
908
  }
869
- radio_container.insertAdjacentHTML('beforeend','<br>')
909
+ radio_container.insertAdjacentHTML('beforeend', '<br>')
870
910
 
871
911
  }
872
912
 
@@ -874,19 +914,16 @@ export default class Interface {
874
914
 
875
915
  };
876
916
 
877
-
878
- document.getElementById("menu_help_add_tree").onclick = function() {
917
+ document.getElementById("menu_help_add_tree").onclick = function () {
879
918
  $('#modal_help').modal('show');
880
919
 
881
920
  };
882
921
 
883
922
 
884
-
885
-
886
923
  }
887
924
 
888
- get_modal_template(){
889
- return `
925
+ get_modal_template() {
926
+ return `
890
927
  <div class="modal" id="exampleModal" tabindex="-1">
891
928
  <div class="modal-dialog modal-dialog-centered modal-lg">
892
929
  <div class="modal-content">
@@ -1050,7 +1087,11 @@ export default class Interface {
1050
1087
  edit_name_ok.style.display = 'none';
1051
1088
  edit_name_trash.style.display = 'none';
1052
1089
  var old_name = this.viewer.model.get_name()
1053
- this.container_object.add_action('Rename tree', this.viewer.model, this.viewer.model.set_name, [old_name], true )
1090
+
1091
+ var undo = {'name': 'Rename tree', 'fonction_obj': this.viewer.model, 'fonct': this.viewer.model.set_name, 'argu': [old_name]}
1092
+ var redo = {'name': 'Rename tree', 'fonction_obj': this.viewer.model, 'fonct': this.viewer.model.set_name, 'argu': [edit_name.textContent]}
1093
+ this.container_object.add_action(undo, redo, true)
1094
+
1054
1095
  this.viewer.model.set_name(edit_name.textContent)
1055
1096
  return false;
1056
1097
  }
@@ -1084,7 +1125,11 @@ export default class Interface {
1084
1125
 
1085
1126
  edit_name_ok.addEventListener('click', (event) => {
1086
1127
  var old_name = this.viewer.model.get_name()
1087
- this.container_object.add_action('Rename tree', this.viewer.model, this.viewer.model.set_name, [old_name], true )
1128
+
1129
+ var undo = {'name': 'Rename tree', 'fonction_obj': this.viewer.model, 'fonct': this.viewer.model.set_name, 'argu': [old_name]}
1130
+ var redo = {'name': 'Rename tree', 'fonction_obj': this.viewer.model, 'fonct': this.viewer.model.set_name, 'argu': [edit_name.textContent]}
1131
+ this.container_object.add_action(undo, redo, true)
1132
+
1088
1133
  this.viewer.model.set_name(edit_name.textContent)
1089
1134
 
1090
1135
  });
@@ -1640,8 +1685,7 @@ export default class Interface {
1640
1685
  </div>
1641
1686
 
1642
1687
  <p style="padding: 0 24px;"><small>
1643
- <b>Accepted format:</b> '.csv' or '.tsv' and must contain column names in the first row.
1644
- You can choose a column as reference for the mapping using the selection widget below, where reference name should matched the leaves and nodes names in the input file.
1688
+ <b>Accepted format:</b> .csv or .tsv with column names in the first row. Use the selector below to choose a reference column matching leaf or node names in the input file.
1645
1689
  </small></p>
1646
1690
 
1647
1691
  <div class="text-center" style="margin-left: 48px;margin-right: 48px;">
@@ -1762,7 +1806,6 @@ export default class Interface {
1762
1806
  mod_html = mod_html.replaceAll('Step 3.1', 'Step 1')
1763
1807
  mod_html = mod_html.replaceAll('Step 3.2', 'Step 2')
1764
1808
 
1765
-
1766
1809
  document.getElementById(this.container_object.div_id).insertAdjacentHTML('afterend',mod_html)
1767
1810
 
1768
1811
  // Add JS for modal corpus
@@ -1848,7 +1891,7 @@ export default class Interface {
1848
1891
  </div>
1849
1892
 
1850
1893
  <div class="form-check" style="margin-left: 24px">
1851
- <input class="form-check-input" name="flexRadioDefault" type="radio" value="color" id="RADIO_3">
1894
+ <input class="form-check-input" name="flexRadioDefault" type="radio" value="color" id="RADIO_3" ATTR_COLOR>
1852
1895
  <label class="form-check-label" for="RADIO_3">
1853
1896
  Color
1854
1897
  </label>
@@ -1875,14 +1918,20 @@ export default class Interface {
1875
1918
  rad = rad.replace('RADIO_3', that.container_object.uid + 'mapping_header_radio3' + '__' + key )
1876
1919
 
1877
1920
 
1878
-
1879
- if (numerisator[key] == 'num'){
1921
+ if (numerisator[key] == 'num') {
1880
1922
  rad = rad.replace('ATTR_NUM', 'checked')
1881
1923
  rad = rad.replace('ATTR_CAT', '')
1924
+ rad = rad.replace('ATTR_COLOR', '')
1925
+ }
1926
+ if (check_if_color(numerisator[key])) {
1927
+ rad = rad.replace('ATTR_NUM', '')
1928
+ rad = rad.replace('ATTR_CAT', '')
1929
+ rad = rad.replace('ATTR_COLOR', 'checked')
1882
1930
  }
1883
- else{
1931
+ else {
1884
1932
  rad = rad.replace('ATTR_NUM', 'disabled')
1885
1933
  rad = rad.replace('ATTR_CAT', 'checked')
1934
+ rad = rad.replace('ATTR_COLOR', '')
1886
1935
  }
1887
1936
 
1888
1937
 
@@ -1960,14 +2009,8 @@ export default class Interface {
1960
2009
 
1961
2010
  }
1962
2011
 
1963
-
1964
-
1965
-
1966
-
1967
-
1968
2012
  that.viewer.interface = new Interface(that.viewer, that.viewer.container_object)
1969
2013
 
1970
-
1971
2014
  that.open_color_settings()
1972
2015
 
1973
2016
  });
@@ -2016,10 +2059,10 @@ export default class Interface {
2016
2059
  var prefix = this.container_object.uid + 'mapping_header_radio'
2017
2060
  }
2018
2061
 
2019
-
2020
2062
  var checkies = document.querySelectorAll(`[id^="${prefix}"]`);
2021
2063
 
2022
2064
 
2065
+
2023
2066
  checkies.forEach(element => {
2024
2067
 
2025
2068
  if (element.checked) {
@@ -2095,7 +2138,7 @@ export default class Interface {
2095
2138
  // ADD THE ACCORDION SYSTEM
2096
2139
 
2097
2140
  this.menu_exportimage_b = this.menu_export.append('button').attr('class', 'accordion').text("Export as Graphic")
2098
- this.menu_exportimage_p = this.menu_export.append('div').attr('class', 'panel').append("div").style("padding", "14px")
2141
+ this.menu_exportimage_p = this.menu_export.append('div').attr('class', 'panel').append("div").style("padding", "6px")
2099
2142
 
2100
2143
  this.export_as = this.menu_exportimage_p.append('div')
2101
2144
  .style('display', 'flex')
@@ -2123,7 +2166,7 @@ export default class Interface {
2123
2166
 
2124
2167
 
2125
2168
  this.menu_exportfile_b = this.menu_export.append('button').attr('class', 'accordion').text("Export as Text")
2126
- this.menu_exportfile_p = this.menu_export.append('div').attr('class', 'panel').append("div").style("padding", "14px")
2169
+ this.menu_exportfile_p = this.menu_export.append('div').attr('class', 'panel').append("div").style("padding", "6px")
2127
2170
 
2128
2171
  this.export_as = this.menu_exportfile_p.append('div')
2129
2172
  .style('display', 'flex')
@@ -2182,25 +2225,28 @@ export default class Interface {
2182
2225
 
2183
2226
  // UNDO
2184
2227
  add_undo(){
2228
+
2185
2229
  var divybuty = this.tr_buttons.append('button')
2186
2230
  .attr('class', ' square_button')
2187
2231
  .attr('id', 'buttonundo_' + this.container_object.div_id )
2188
2232
  .attr('data-bs-placement', 'bottom')
2189
2233
  .attr('title', d=> { return this.container_object.history_actions.length > 0 ? 'Undo ' + this.container_object.get_last_action().name : 'Nothing to undo' })
2190
2234
  .style('margin', '2px')
2191
- .on("click", d => {
2192
- this.api.undoing = true
2235
+ .on("click", d => {
2236
+ this.api.undoing = true;
2193
2237
  var cta = this.container_object.pop_last_action();
2194
- if (cta) {
2238
+ cta = cta.undo
2239
+ if (cta && typeof cta.fonct === 'function') {
2195
2240
  cta.fonct.apply(cta.fonction_obj, cta.argu);
2196
2241
 
2197
- if (cta.refresh_interface){
2198
- let empty = this.container_object.models.length <= 0
2199
- this.container_object.interface = new Interface(this.viewer, this.container_object, empty )
2242
+ if (cta.refresh_interface) {
2243
+ let empty = this.container_object.models.length <= 0;
2244
+ this.container_object.interface = new Interface(this.viewer, this.container_object, empty);
2200
2245
  }
2201
-
2246
+ } else {
2247
+ console.error('Invalid cta or cta.fonct:', cta);
2202
2248
  }
2203
- this.api.undoing = false
2249
+ this.api.undoing = false;
2204
2250
  })
2205
2251
 
2206
2252
 
@@ -2221,6 +2267,43 @@ export default class Interface {
2221
2267
 
2222
2268
  }
2223
2269
 
2270
+ add_redo(){
2271
+
2272
+ var divybuty = this.tr_buttons.append('button')
2273
+ .attr('class', ' square_button')
2274
+ .attr('id', 'buttonredo_' + this.container_object.div_id )
2275
+ .attr('data-bs-placement', 'bottom')
2276
+ .attr('title', d=> { return this.container_object.history_actions.length > 0 ? 'Redo ' + this.container_object.get_last_action().redo.name : 'Nothing to redo' })
2277
+ .style('margin', '2px')
2278
+ .on("click", d => {
2279
+ var cta = this.container_object.pop_redo_action();
2280
+ cta = cta.redo
2281
+ if (cta && typeof cta.fonct === 'function') {
2282
+ cta.fonct.apply(cta.fonction_obj, cta.argu);
2283
+
2284
+ if (cta.refresh_interface) {
2285
+ let empty = this.container_object.models.length <= 0;
2286
+ this.container_object.interface = new Interface(this.viewer, this.container_object, empty);
2287
+ }
2288
+ } else {
2289
+ console.error('Invalid cta or cta.fonct:', cta);
2290
+ }
2291
+ })
2292
+
2293
+ divybuty.append("div")
2294
+ .attr("class","label")
2295
+ .append('i')
2296
+ .style('color', '#888')
2297
+ .attr('class', 'bi-arrow-clockwise')
2298
+
2299
+ divybuty.append('p')
2300
+ .text('Redo')
2301
+ .style('font-size', 'xx-small')
2302
+
2303
+ this.tooltip_undo = new bootstrap.Tooltip(document.getElementById('buttonredo_' + this.container_object.div_id))
2304
+
2305
+ }
2306
+
2224
2307
  toggle_select_node_face(cid){
2225
2308
 
2226
2309
  var acc = document.getElementById("accordion_branch"+cid)
@@ -2297,17 +2380,17 @@ export default class Interface {
2297
2380
  this.menu_tree_b = this.menu_settings.append('button').attr('id', 'accordion_branch'+this.container_object.uid).attr('class', 'accordion').text("Branches & Labels")
2298
2381
  this.menu_tree_p = this.menu_settings.append('div').attr('class', 'panel').append("div").style("padding", "14px")
2299
2382
 
2300
- this.menu_search_b = this.menu_settings.append('button').attr('id', 'accordion_branch'+this.container_object.uid).attr('class', 'accordion').text("Search")
2301
- this.menu_search_p = this.menu_settings.append('div').attr('class', 'panel').append("div").style("padding", "14px")
2302
2383
 
2303
2384
  //this.menu_metadata_b = this.menu_settings.append('button').attr('id', 'accordion_color'+this.container_object.uid).attr('class', 'accordion').text("Additional Information")
2304
2385
  //this.menu_metadata_p = this.menu_settings.append('div').attr('class', 'panel').append("div").style("padding", "14px")
2305
2386
 
2306
2387
  this.menu_coloring_b = this.menu_settings.append('button').attr('id', 'accordion_color'+this.container_object.uid).attr('class', 'accordion').text("Coloring")
2307
2388
  this.menu_coloring_panel = this.menu_settings.append('div').attr('class', 'panel').attr('id', 'coloring_panel' + this.container_object.uid)
2308
-
2309
2389
  this.menu_coloring_p = this.menu_coloring_panel.append("div").style("padding", "14px").attr('id', 'coloring_p' + this.container_object.uid)
2310
2390
 
2391
+ this.menu_search_b = this.menu_settings.append('button').attr('id', 'accordion_branch'+this.container_object.uid).attr('class', 'accordion').text("Search options")
2392
+ this.menu_search_p = this.menu_settings.append('div').attr('class', 'panel').append("div").style("padding", "14px")
2393
+
2311
2394
  if (this.viewer.model.settings.has_histogram_data && this.viewer.model.settings.show_histogram ) {
2312
2395
  this.menu_stack_b = this.menu_settings.append('button').attr('class', 'accordion').text("Bar Graph")
2313
2396
  this.menu_stack_p = this.menu_settings.append('div').attr('class', 'panel').append("div").style("padding", "14px")
@@ -2420,7 +2503,7 @@ export default class Interface {
2420
2503
 
2421
2504
  // ADD TOGGLE BRANCH LENGTH
2422
2505
  if(this.viewer.model.settings.has_branch_lenght){
2423
- this.add_swicth_UI(this.menu_general_p, this.viewer.model.settings.use_branch_lenght,"Use branch length", this.viewer.toggle_use_length.bind(this.viewer))
2506
+ this.add_swicth_UI(this.menu_general_p, !this.viewer.model.settings.use_branch_lenght,"Ignore branch length", this.viewer.toggle_use_length.bind(this.viewer))
2424
2507
  }
2425
2508
 
2426
2509
  this.add_swicth_UI(this.menu_general_p, this.viewer.model.settings.align_tip,"Align leaves", this.viewer.toggle_align_tip.bind(this.viewer))
@@ -2437,8 +2520,11 @@ export default class Interface {
2437
2520
  */
2438
2521
 
2439
2522
 
2440
- this.buttons_height = this.add_quartet_buttons(this.menu_general_p, "Tree height", "buton_vertical_size_", this.container_object.modify_node_size_percent, 'vertical')
2441
- this.buttons_width = this.add_quartet_buttons(this.menu_general_p, "Tree width", "buton_horyzontal_size_", this.container_object.modify_node_size_percent, 'horizontal')
2523
+ //this.buttons_height = this.add_quartet_buttons(this.menu_general_p, "Tree height", "buton_vertical_size_", this.container_object.modify_node_size_percent, 'vertical')
2524
+ //this.buttons_width = this.add_quartet_buttons(this.menu_general_p, "Tree width", "buton_horyzontal_size_", this.container_object.modify_node_size_percent, 'horizontal')
2525
+
2526
+ this.add_quartet_buttons_single_line(this.menu_general_p, "Tree height", "buton_vertical_size_", this.container_object.modify_node_size_percent, 'vertical')
2527
+ this.add_quartet_buttons_single_line(this.menu_general_p, "Tree width", "buton_horyzontal_size_", this.container_object.modify_node_size_percent, 'horizontal')
2442
2528
 
2443
2529
 
2444
2530
  // ADD SELECT LEFT NODE LABEL
@@ -2448,6 +2534,9 @@ export default class Interface {
2448
2534
  //this.add_swicth_UI(this.menu_tree_p, this.viewer.model.settings.display_internal_label,"Show internal label", this.viewer.toggle_internal_label.bind(this.viewer))
2449
2535
 
2450
2536
 
2537
+ // ADD TOGGLE show internal name for triangle
2538
+ this.add_swicth_UI(this.menu_tree_p, this.viewer.model.settings.use_internal_node_name_for_triangles,"Show collapsed subtrees name", this.viewer.toggle_triangle_name.bind(this.viewer))
2539
+
2451
2540
  // ADD TOGGLE tooltips
2452
2541
  this.add_swicth_UI(this.menu_tree_p, this.viewer.model.settings.subsample_label,"Subsample labels", this.viewer.toggle_subsample.bind(this.viewer))
2453
2542
 
@@ -2458,7 +2547,7 @@ export default class Interface {
2458
2547
  this.add_swicth_UI(this.menu_tree_p, this.viewer.model.settings.display_leaves,"Show node labels", this.viewer.toggle_node_labels.bind(this.viewer))
2459
2548
 
2460
2549
  // ADD TOGGLE tooltips
2461
- this.add_swicth_UI(this.menu_tree_p, this.viewer.model.settings.show_tooltips,"Show tooltips", this.viewer.toggle_tooltips.bind(this.viewer))
2550
+ this.add_swicth_UI(this.menu_tree_p, this.viewer.model.settings.show_tooltips,"Show data tooltips", this.viewer.toggle_tooltips.bind(this.viewer))
2462
2551
 
2463
2552
  if (this.viewer.model.settings.has_duplications){
2464
2553
  // ADD TOGGLE DUPLICATION
@@ -2466,10 +2555,12 @@ export default class Interface {
2466
2555
 
2467
2556
  }
2468
2557
 
2469
- this.add_quartet_buttons(this.menu_tree_p, "Node radius", "buton_node_radius_", this.container_object.update_node_radius_percent )
2558
+ //this.add_quartet_buttons(this.menu_tree_p, "Node radius", "buton_node_radius_", this.container_object.update_node_radius_percent )
2559
+ this.add_quartet_buttons_single_line(this.menu_tree_p, "Node radius", "buton_node_radius_", this.container_object.update_node_radius_percent)
2470
2560
 
2471
2561
 
2472
- this.add_quartet_buttons(this.menu_tree_p, "Line width", "buton_line_width_", this.container_object.update_line_width_percent)
2562
+ //this.add_quartet_buttons(this.menu_tree_p, "Line width", "buton_line_width_", this.container_object.update_line_width_percent)
2563
+ this.add_quartet_buttons_single_line(this.menu_tree_p, "Line width", "buton_line_width_", this.container_object.update_line_width_percent)
2473
2564
 
2474
2565
 
2475
2566
 
@@ -2678,12 +2769,137 @@ export default class Interface {
2678
2769
  }
2679
2770
  else {
2680
2771
  drop.style('float','right').append('label').text("No Data available");
2681
- this.menu_coloring_p.append('br')
2772
+ container_div.append('br')
2682
2773
 
2683
2774
  }
2684
2775
 
2685
2776
  }
2686
2777
 
2778
+ add_color_collapsing(container_div) {
2779
+
2780
+ var that = this;
2781
+
2782
+ // Add button for collapse uncolored taxon
2783
+ this.collapse_color_button_div = container_div.append('div')
2784
+ .style('display', 'flex')
2785
+ .style('margin-top', '0px')
2786
+
2787
+
2788
+ this.collapse_color_button_div.append('button')
2789
+ .attr('class', ' square_button')
2790
+ .attr('id', 'collapse_color_search' + this.viewer.uid)
2791
+ .on("click", d => {
2792
+ this.container_object.collapse_node_not_colored()
2793
+ this.viewer.build_d3_cluster()
2794
+ this.viewer.render(this.viewer.hierarchy)
2795
+ this.viewer.maximise_zoom()
2796
+ })
2797
+ .style('margin', '12px 0px')
2798
+ .style('flex-grow', '1')
2799
+ .append("text")
2800
+ .text("Collapse uncolored subtrees ")
2801
+
2802
+ // Add select for select uncolored
2803
+
2804
+ var color_triangle_div = container_div.append('div')
2805
+ .style('display','flex')
2806
+ .style('float', 'right')
2807
+
2808
+
2809
+ var options_triangle = ['Leaves', 'Nodes', 'Both'];
2810
+
2811
+ color_triangle_div.append('label')
2812
+ .text("Using")
2813
+ .style('margin-right', '8px')
2814
+
2815
+ var selectcoloring_triangle = color_triangle_div.append('select')
2816
+ .attr('id','selectcol_uncol' + this.container_object.uid )
2817
+ .attr('class','select')
2818
+ .style('float','right')
2819
+ .on('change', function(){
2820
+ that.viewer.model.settings.selected_collapse_uncolored = this.value;
2821
+
2822
+ /*
2823
+ that.container_object.collapse_node_not_colored()
2824
+ that.viewer.build_d3_cluster()
2825
+ that.viewer.render(that.viewer.hierarchy)
2826
+ that.viewer.maximise_zoom()
2827
+
2828
+ */
2829
+
2830
+ })
2831
+
2832
+
2833
+ selectcoloring_triangle.selectAll('option').data(options_triangle).enter()
2834
+ .append('option')
2835
+ .attr('value', function (d) {
2836
+ return d; })
2837
+ .property("selected", (d) => { return d == this.viewer.model.settings.selected_collapse_uncolored })
2838
+ .text(function (d) { return d; });
2839
+
2840
+ container_div.append('br')
2841
+
2842
+
2843
+ // Add button for collapse unicolored taxon
2844
+ this.collapse_unicolor_button_div = container_div.append('div')
2845
+ .style('display', 'flex')
2846
+ .style('margin-top', '0px')
2847
+
2848
+ this.collapse_unicolor_button_div.append('button')
2849
+ .attr('class', ' square_button')
2850
+ .attr('id', 'collapse_unicolor_search' + this.viewer.uid)
2851
+ .on("click", d => {
2852
+ this.container_object.collapse_node_same_color()
2853
+ this.viewer.build_d3_cluster()
2854
+ this.viewer.render(this.viewer.hierarchy)
2855
+ this.viewer.maximise_zoom()
2856
+ })
2857
+ .style('margin', '12px 0px')
2858
+ .style('flex-grow', '1')
2859
+ .append("text")
2860
+ .text("Collapse monocolored subtrees ")
2861
+
2862
+ // Add select for select unicolored
2863
+
2864
+ var color_unicolor_div = container_div.append('div')
2865
+ .style('display','flex')
2866
+ .style('float', 'right')
2867
+
2868
+ var _options_triangle = ['Leaves', 'Nodes', 'Both'];
2869
+
2870
+ color_unicolor_div.append('label')
2871
+ .text("Using")
2872
+ .style('margin-right', '8px')
2873
+
2874
+ var selectcoloring_mono = color_unicolor_div.append('select')
2875
+ .attr('id','selectcol_uncol' + this.container_object.uid )
2876
+ .attr('class','select')
2877
+ .style('float','right')
2878
+
2879
+ .on('change', function(){
2880
+ that.viewer.model.settings.selected_collapse_monocolored = this.value;
2881
+ /*
2882
+ that.container_object.collapse_node_same_color()
2883
+ that.viewer.build_d3_cluster()
2884
+ that.viewer.render(that.viewer.hierarchy)
2885
+ that.viewer.maximise_zoom()
2886
+
2887
+ */
2888
+ })
2889
+
2890
+
2891
+
2892
+
2893
+ selectcoloring_mono.selectAll('option').data(_options_triangle).enter()
2894
+ .append('option')
2895
+ .attr('value', function (d) {
2896
+ return d; })
2897
+ .property("selected", (d) => { return d == this.viewer.model.settings.selected_collapse_monocolored })
2898
+ .text(function (d) { return d; });
2899
+
2900
+ container_div.append('br')
2901
+ }
2902
+
2687
2903
  add_settings_coloring(){
2688
2904
 
2689
2905
  var that = this;
@@ -2847,51 +3063,15 @@ export default class Interface {
2847
3063
 
2848
3064
  this.add_node_coloring_UI(this.menu_coloring_p)
2849
3065
 
2850
-
2851
3066
  this.menu_coloring_p.append('hr').style('margin', '20px 0px 4px 0px')
2852
3067
 
2853
- // Add button for collapse uncolored taxon
2854
- this.collapse_color_button_div = this.menu_coloring_p.append('div')
2855
- .style('display', 'flex')
2856
- .style('margin-top', '0px')
2857
-
2858
-
2859
- this.collapse_color_button_div.append('button')
2860
- .attr('class', ' square_button')
2861
- .attr('id', 'collapse_color_search' + this.viewer.uid)
2862
- .on("click", d => {
2863
- this.container_object.collapse_node_not_colored()
2864
- this.viewer.build_d3_cluster()
2865
- this.viewer.render(this.viewer.hierarchy)
2866
- this.viewer.maximise_zoom()
2867
- })
2868
- .style('margin', '12px 0px')
2869
- .style('flex-grow', '1')
2870
- .append("text")
2871
- .text("Collapse uncolored sub-tree ")
2872
-
2873
- // Add button for collapse unicolored taxon
2874
- this.collapse_unicolor_button_div = this.menu_coloring_p.append('div')
2875
- .style('display', 'flex')
2876
- .style('margin-top', '0px')
3068
+ this.add_color_collapsing(this.menu_coloring_p)
2877
3069
 
2878
- this.collapse_unicolor_button_div.append('button')
2879
- .attr('class', ' square_button')
2880
- .attr('id', 'collapse_unicolor_search' + this.viewer.uid)
2881
- .on("click", d => {
2882
- this.container_object.collapse_node_same_color()
2883
- this.viewer.build_d3_cluster()
2884
- this.viewer.render(this.viewer.hierarchy)
2885
- this.viewer.maximise_zoom()
2886
- })
2887
- .style('margin', '12px 0px')
2888
- .style('flex-grow', '1')
2889
- .append("text")
2890
- .text("Collapse monocolored sub-tree ")
3070
+ this.menu_coloring_p.append('hr').style('margin', '20px 0px 4px 0px')
2891
3071
 
2892
3072
 
2893
3073
  // add sync coloring
2894
- this.add_swicth_UI(this.menu_coloring_p, this.viewer.model.settings.sync_coloring,"Sync branches and leaves coloring", this.viewer.toggle_sync_coloring.bind(this.viewer))
3074
+ this.add_swicth_UI(this.menu_coloring_p, this.viewer.model.settings.sync_coloring,"Link branch & leaf coloring", this.viewer.toggle_sync_coloring.bind(this.viewer))
2895
3075
 
2896
3076
  var color_triangle_div = this.menu_coloring_p.append('div')
2897
3077
  .style('display','block')
@@ -3706,7 +3886,7 @@ export default class Interface {
3706
3886
 
3707
3887
 
3708
3888
  var butty_putty1 = buttons.append('button')
3709
- .attr('class', ' square_button')
3889
+ .attr('class', ' square_button mini')
3710
3890
  .style('border-radius', '0px')
3711
3891
  .style('padding', '2px')
3712
3892
  .attr('id', id + 'first' + this.container_object.uid )
@@ -3715,19 +3895,16 @@ export default class Interface {
3715
3895
  .style('flex-grow', '1')
3716
3896
 
3717
3897
 
3718
- butty_putty1.append("div").append('i')
3719
- .style('color', '#888')
3720
- .style('font-size', '12px')
3721
- .attr('class', 'bi bi-dash')
3898
+
3722
3899
 
3723
3900
  butty_putty1.append('p')
3724
- .text('-50%')
3901
+ .text('- 50%')
3725
3902
  .style('font-size', 'xx-small')
3726
3903
  .style('line-height', 'normal')
3727
3904
  .style('margin-bottom', '4px')
3728
3905
 
3729
3906
  var butty_putty2 = buttons.append('button')
3730
- .attr('class', ' square_button')
3907
+ .attr('class', ' square_button mini')
3731
3908
  .style('border-radius', '0px')
3732
3909
  .style('padding', '2px')
3733
3910
  .attr('id', id + 'second' + this.container_object.uid )
@@ -3736,20 +3913,16 @@ export default class Interface {
3736
3913
  .style('flex-grow', '1')
3737
3914
 
3738
3915
 
3739
- butty_putty2.append("div").append('i')
3740
- .style('color', '#888')
3741
- .style('font-size', '8px')
3742
- .attr('class', ' bi bi-dash ')
3743
3916
 
3744
3917
  butty_putty2.append('p')
3745
- .text('-20%')
3918
+ .text('- 20%')
3746
3919
  .style('font-size', 'xx-small')
3747
3920
  .style('line-height', 'normal')
3748
3921
  .style('margin-bottom', '4px')
3749
3922
 
3750
3923
 
3751
3924
  var butty_putty3 = buttons.append('button')
3752
- .attr('class', ' square_button')
3925
+ .attr('class', ' square_button mini')
3753
3926
  .style('border-radius', '0px')
3754
3927
  .style('padding', '2px')
3755
3928
  .attr('id', id + 'third' + this.container_object.uid )
@@ -3759,13 +3932,9 @@ export default class Interface {
3759
3932
 
3760
3933
 
3761
3934
 
3762
- butty_putty3.append("div").append('i')
3763
- .style('color', '#888')
3764
- .style('font-size', '8px')
3765
- .attr('class', ' bi bi-plus ')
3766
3935
 
3767
3936
  butty_putty3.append('p')
3768
- .text('+20%')
3937
+ .text('+ 20%')
3769
3938
  .style('font-size', 'xx-small')
3770
3939
  .style('line-height', 'normal')
3771
3940
  .style('margin-bottom', '4px')
@@ -3773,7 +3942,7 @@ export default class Interface {
3773
3942
 
3774
3943
 
3775
3944
  var butty_putty4 = buttons.append('button')
3776
- .attr('class', ' square_button')
3945
+ .attr('class', ' square_button mini')
3777
3946
  .style('border-radius', '0px')
3778
3947
  .style('padding', '2px')
3779
3948
  .attr('id', id + 'fourth' + this.container_object.uid )
@@ -3783,13 +3952,8 @@ export default class Interface {
3783
3952
 
3784
3953
 
3785
3954
 
3786
- butty_putty4.append("div").append('i')
3787
- .style('color', '#888')
3788
- .style('font-size', '12px')
3789
- .attr('class', ' bi bi-plus ')
3790
-
3791
3955
  butty_putty4.append('p')
3792
- .text('+50%')
3956
+ .text('+ 50%')
3793
3957
  .style('font-size', 'xx-small')
3794
3958
  .style('line-height', 'normal')
3795
3959
  .style('margin-bottom', '4px')