Item.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. export class Item {
  2. constructor( ...data ) {
  3. this.children = [];
  4. this.isOpen = true;
  5. this.childrenContainer = null;
  6. this.parent = null;
  7. this.domElement = document.createElement( 'div' );
  8. this.domElement.className = 'list-item-wrapper';
  9. this.itemRow = document.createElement( 'div' );
  10. this.itemRow.className = 'list-item-row';
  11. this.userData = {};
  12. this.data = data;
  13. this.data.forEach( ( cellData ) => {
  14. const cell = document.createElement( 'div' );
  15. cell.className = 'list-item-cell';
  16. if ( cellData instanceof HTMLElement ) {
  17. cell.appendChild( cellData );
  18. } else {
  19. cell.append( String( cellData ) );
  20. }
  21. this.itemRow.appendChild( cell );
  22. } );
  23. this.domElement.appendChild( this.itemRow );
  24. // Bindings
  25. this.onItemClick = this.onItemClick.bind( this );
  26. }
  27. onItemClick( e ) {
  28. if ( e.target.closest( 'button, a, input, label' ) ) return;
  29. this.toggle();
  30. }
  31. add( item, index = this.children.length ) {
  32. if ( item.parent !== null ) {
  33. item.parent.remove( item );
  34. }
  35. item.parent = this;
  36. this.children.splice( index, 0, item );
  37. this.itemRow.classList.add( 'collapsible' );
  38. if ( ! this.childrenContainer ) {
  39. this.childrenContainer = document.createElement( 'div' );
  40. this.childrenContainer.className = 'list-children-container';
  41. this.childrenContainer.classList.toggle( 'closed', ! this.isOpen );
  42. this.domElement.appendChild( this.childrenContainer );
  43. this.itemRow.addEventListener( 'click', this.onItemClick );
  44. }
  45. this.childrenContainer.insertBefore(
  46. item.domElement,
  47. this.childrenContainer.children[ index ] || null
  48. );
  49. this.updateToggler();
  50. return this;
  51. }
  52. remove( item ) {
  53. const index = this.children.indexOf( item );
  54. if ( index !== - 1 ) {
  55. this.children.splice( index, 1 );
  56. this.childrenContainer.removeChild( item.domElement );
  57. item.parent = null;
  58. if ( this.children.length === 0 ) {
  59. this.itemRow.classList.remove( 'collapsible' );
  60. this.itemRow.removeEventListener( 'click', this.onItemClick );
  61. this.childrenContainer.remove();
  62. this.childrenContainer = null;
  63. }
  64. this.updateToggler();
  65. }
  66. return this;
  67. }
  68. updateToggler() {
  69. const firstCell = this.itemRow.querySelector( '.list-item-cell:first-child' );
  70. let toggler = this.itemRow.querySelector( '.item-toggler' );
  71. if ( this.children.length > 0 ) {
  72. if ( ! toggler ) {
  73. toggler = document.createElement( 'span' );
  74. toggler.className = 'item-toggler';
  75. firstCell.prepend( toggler );
  76. }
  77. if ( this.isOpen ) {
  78. this.itemRow.classList.add( 'open' );
  79. }
  80. } else if ( toggler ) {
  81. toggler.remove();
  82. }
  83. }
  84. toggle() {
  85. this.isOpen = ! this.isOpen;
  86. this.itemRow.classList.toggle( 'open', this.isOpen );
  87. if ( this.childrenContainer ) {
  88. this.childrenContainer.classList.toggle( 'closed', ! this.isOpen );
  89. }
  90. return this;
  91. }
  92. close() {
  93. if ( this.isOpen ) {
  94. this.toggle();
  95. }
  96. return this;
  97. }
  98. }
粤ICP备19079148号