Treeoutline.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. export class TreeOutline extends Common.Object{constructor(){super();this._createRootElement();this.selectedTreeElement=null;this.expandTreeElementsWhenArrowing=false;this._comparator=null;this.contentElement=this._rootElement._childrenListNode;this.contentElement.addEventListener('keydown',this._treeKeyDown.bind(this),false);this._preventTabOrder=false;this._showSelectionOnKeyboardFocus=false;this.setFocusable(true);this.element=this.contentElement;UI.ARIAUtils.markAsTree(this.element);}
  2. setShowSelectionOnKeyboardFocus(show,preventTabOrder){this.contentElement.classList.toggle('hide-selection-when-blurred',show);this._preventTabOrder=!!preventTabOrder;if(this._focusable){this.contentElement.tabIndex=!!preventTabOrder?-1:0;}
  3. this._showSelectionOnKeyboardFocus=show;}
  4. _createRootElement(){this._rootElement=new TreeElement();this._rootElement.treeOutline=this;this._rootElement.root=true;this._rootElement.selectable=false;this._rootElement.expanded=true;this._rootElement._childrenListNode.classList.remove('children');}
  5. rootElement(){return this._rootElement;}
  6. firstChild(){return this._rootElement.firstChild();}
  7. _lastDescendent(){let last=this._rootElement.lastChild();while(last.expanded&&last.childCount()){last=last.lastChild();}
  8. return last;}
  9. appendChild(child){this._rootElement.appendChild(child);}
  10. insertChild(child,index){this._rootElement.insertChild(child,index);}
  11. removeChild(child){this._rootElement.removeChild(child);}
  12. removeChildren(){this._rootElement.removeChildren();}
  13. treeElementFromPoint(x,y){const node=this.contentElement.ownerDocument.deepElementFromPoint(x,y);if(!node){return null;}
  14. const listNode=node.enclosingNodeOrSelfWithNodeNameInArray(['ol','li']);if(listNode){return listNode.parentTreeElement||listNode.treeElement;}
  15. return null;}
  16. treeElementFromEvent(event){return event?this.treeElementFromPoint(event.pageX,event.pageY):null;}
  17. setComparator(comparator){this._comparator=comparator;}
  18. setFocusable(focusable){this._focusable=focusable;this.updateFocusable();}
  19. updateFocusable(){if(this._focusable){this.contentElement.tabIndex=(this._preventTabOrder||!!this.selectedTreeElement)?-1:0;if(this.selectedTreeElement){this.selectedTreeElement._setFocusable(true);}}else{this.contentElement.removeAttribute('tabIndex');if(this.selectedTreeElement){this.selectedTreeElement._setFocusable(false);}}}
  20. focus(){if(this.selectedTreeElement){this.selectedTreeElement.listItemElement.focus();}else{this.contentElement.focus();}}
  21. useLightSelectionColor(){this._useLightSelectionColor=true;}
  22. _bindTreeElement(element){if(element.treeOutline){console.error('Binding element for the second time: '+new Error().stack);}
  23. element.treeOutline=this;element.onbind();}
  24. _unbindTreeElement(element){if(!element.treeOutline){console.error('Unbinding element that was not bound: '+new Error().stack);}
  25. element.deselect();element.onunbind();element.treeOutline=null;}
  26. selectPrevious(){let nextSelectedElement=this.selectedTreeElement.traversePreviousTreeElement(true);while(nextSelectedElement&&!nextSelectedElement.selectable){nextSelectedElement=nextSelectedElement.traversePreviousTreeElement(!this.expandTreeElementsWhenArrowing);}
  27. if(!nextSelectedElement){return false;}
  28. nextSelectedElement.select(false,true);return true;}
  29. selectNext(){let nextSelectedElement=this.selectedTreeElement.traverseNextTreeElement(true);while(nextSelectedElement&&!nextSelectedElement.selectable){nextSelectedElement=nextSelectedElement.traverseNextTreeElement(!this.expandTreeElementsWhenArrowing);}
  30. if(!nextSelectedElement){return false;}
  31. nextSelectedElement.select(false,true);return true;}
  32. forceSelect(omitFocus=false,selectedByUser=true){if(this.selectedTreeElement){this.selectedTreeElement.deselect();}
  33. this._selectFirst(omitFocus,selectedByUser);}
  34. _selectFirst(omitFocus=false,selectedByUser=true){let first=this.firstChild();while(first&&!first.selectable){first=first.traverseNextTreeElement(true);}
  35. if(!first){return false;}
  36. first.select(omitFocus,selectedByUser);return true;}
  37. _selectLast(){let last=this._lastDescendent();while(last&&!last.selectable){last=last.traversePreviousTreeElement(true);}
  38. if(!last){return false;}
  39. last.select(false,true);return true;}
  40. _treeKeyDown(event){if(event.shiftKey||event.metaKey||event.ctrlKey||UI.isEditing()){return;}
  41. let handled=false;if(!this.selectedTreeElement){if(event.key==='ArrowUp'&&!event.altKey){handled=this._selectLast();}else if(event.key==='ArrowDown'&&!event.altKey){handled=this._selectFirst();}}else if(event.key==='ArrowUp'&&!event.altKey){handled=this.selectPrevious();}else if(event.key==='ArrowDown'&&!event.altKey){handled=this.selectNext();}else if(event.key==='ArrowLeft'){handled=this.selectedTreeElement.collapseOrAscend(event.altKey);}else if(event.key==='ArrowRight'){if(!this.selectedTreeElement.revealed()){this.selectedTreeElement.reveal();handled=true;}else{handled=this.selectedTreeElement.descendOrExpand(event.altKey);}}else if(event.keyCode===8||event.keyCode===46){handled=this.selectedTreeElement.ondelete();}else if(isEnterKey(event)){handled=this.selectedTreeElement.onenter();}else if(event.keyCode===UI.KeyboardShortcut.Keys.Space.code){handled=this.selectedTreeElement.onspace();}else if(event.key==='Home'){handled=this._selectFirst();}else if(event.key==='End'){handled=this._selectLast();}
  42. if(handled){event.consume(true);}}
  43. _deferredScrollIntoView(treeElement,center){if(!this._treeElementToScrollIntoView){this.element.window().requestAnimationFrame(deferredScrollIntoView.bind(this));}
  44. this._treeElementToScrollIntoView=treeElement;this._centerUponScrollIntoView=center;function deferredScrollIntoView(){this._treeElementToScrollIntoView.listItemElement.scrollIntoViewIfNeeded(this._centerUponScrollIntoView);delete this._treeElementToScrollIntoView;delete this._centerUponScrollIntoView;}}}
  45. const Events={ElementAttached:Symbol('ElementAttached'),ElementsDetached:Symbol('ElementsDetached'),ElementExpanded:Symbol('ElementExpanded'),ElementCollapsed:Symbol('ElementCollapsed'),ElementSelected:Symbol('ElementSelected')};export class TreeOutlineInShadow extends TreeOutline{constructor(){super();this.contentElement.classList.add('tree-outline');this.element=createElement('div');this._shadowRoot=UI.createShadowRootWithCoreStyles(this.element,'ui/treeoutline.css');this._disclosureElement=this._shadowRoot.createChild('div','tree-outline-disclosure');this._disclosureElement.appendChild(this.contentElement);this._renderSelection=true;}
  46. registerRequiredCSS(cssFile){UI.appendStyle(this._shadowRoot,cssFile);}
  47. hideOverflow(){this._disclosureElement.classList.add('tree-outline-disclosure-hide-overflow');}
  48. makeDense(){this.contentElement.classList.add('tree-outline-dense');}}
  49. export class TreeElement{constructor(title,expandable){this.treeOutline=null;this.parent=null;this.previousSibling=null;this.nextSibling=null;this._boundOnFocus=this._onFocus.bind(this);this._boundOnBlur=this._onBlur.bind(this);this._listItemNode=createElement('li');this.titleElement=this._listItemNode.createChild('span','tree-element-title');this._listItemNode.treeElement=this;if(title){this.title=title;}
  50. this._listItemNode.addEventListener('mousedown',this._handleMouseDown.bind(this),false);this._listItemNode.addEventListener('click',this._treeElementToggled.bind(this),false);this._listItemNode.addEventListener('dblclick',this._handleDoubleClick.bind(this),false);UI.ARIAUtils.markAsTreeitem(this._listItemNode);this._childrenListNode=createElement('ol');this._childrenListNode.parentTreeElement=this;this._childrenListNode.classList.add('children');UI.ARIAUtils.markAsGroup(this._childrenListNode);this._hidden=false;this._selectable=true;this.expanded=false;this.selected=false;this.setExpandable(expandable||false);this._collapsible=true;}
  51. hasAncestor(ancestor){if(!ancestor){return false;}
  52. let currentNode=this.parent;while(currentNode){if(ancestor===currentNode){return true;}
  53. currentNode=currentNode.parent;}
  54. return false;}
  55. hasAncestorOrSelf(ancestor){return this===ancestor||this.hasAncestor(ancestor);}
  56. isHidden(){if(this.hidden){return true;}
  57. let currentNode=this.parent;while(currentNode){if(currentNode.hidden){return true;}
  58. currentNode=currentNode.parent;}
  59. return false;}
  60. children(){return this._children||[];}
  61. childCount(){return this._children?this._children.length:0;}
  62. firstChild(){return this._children?this._children[0]:null;}
  63. lastChild(){return this._children?this._children[this._children.length-1]:null;}
  64. childAt(index){return this._children?this._children[index]:null;}
  65. indexOfChild(child){return this._children?this._children.indexOf(child):-1;}
  66. appendChild(child){if(!this._children){this._children=[];}
  67. let insertionIndex;if(this.treeOutline&&this.treeOutline._comparator){insertionIndex=this._children.lowerBound(child,this.treeOutline._comparator);}else{insertionIndex=this._children.length;}
  68. this.insertChild(child,insertionIndex);}
  69. insertChild(child,index){if(!this._children){this._children=[];}
  70. if(!child){throw'child can\'t be undefined or null';}
  71. console.assert(!child.parent,'Attempting to insert a child that is already in the tree, reparenting is not supported.');const previousChild=(index>0?this._children[index-1]:null);if(previousChild){previousChild.nextSibling=child;child.previousSibling=previousChild;}else{child.previousSibling=null;}
  72. const nextChild=this._children[index];if(nextChild){nextChild.previousSibling=child;child.nextSibling=nextChild;}else{child.nextSibling=null;}
  73. this._children.splice(index,0,child);this.setExpandable(true);child.parent=this;if(this.treeOutline){this.treeOutline._bindTreeElement(child);}
  74. for(let current=child.firstChild();this.treeOutline&&current;current=current.traverseNextTreeElement(false,child,true)){this.treeOutline._bindTreeElement(current);}
  75. child.onattach();child._ensureSelection();if(this.treeOutline){this.treeOutline.dispatchEventToListeners(Events.ElementAttached,child);}
  76. const nextSibling=child.nextSibling?child.nextSibling._listItemNode:null;this._childrenListNode.insertBefore(child._listItemNode,nextSibling);this._childrenListNode.insertBefore(child._childrenListNode,nextSibling);if(child.selected){child.select();}
  77. if(child.expanded){child.expand();}}
  78. removeChildAtIndex(childIndex){if(childIndex<0||childIndex>=this._children.length){throw'childIndex out of range';}
  79. const child=this._children[childIndex];this._children.splice(childIndex,1);const parent=child.parent;if(this.treeOutline&&this.treeOutline.selectedTreeElement&&this.treeOutline.selectedTreeElement.hasAncestorOrSelf(child)){if(child.nextSibling){child.nextSibling.select(true);}else if(child.previousSibling){child.previousSibling.select(true);}else if(parent){parent.select(true);}}
  80. if(child.previousSibling){child.previousSibling.nextSibling=child.nextSibling;}
  81. if(child.nextSibling){child.nextSibling.previousSibling=child.previousSibling;}
  82. child.parent=null;if(this.treeOutline){this.treeOutline._unbindTreeElement(child);}
  83. for(let current=child.firstChild();this.treeOutline&&current;current=current.traverseNextTreeElement(false,child,true)){this.treeOutline._unbindTreeElement(current);}
  84. child._detach();if(this.treeOutline){this.treeOutline.dispatchEventToListeners(Events.ElementsDetached);}}
  85. removeChild(child){if(!child){throw'child can\'t be undefined or null';}
  86. if(child.parent!==this){return;}
  87. const childIndex=this._children.indexOf(child);if(childIndex===-1){throw'child not found in this node\'s children';}
  88. this.removeChildAtIndex(childIndex);}
  89. removeChildren(){if(!this.root&&this.treeOutline&&this.treeOutline.selectedTreeElement&&this.treeOutline.selectedTreeElement.hasAncestorOrSelf(this)){this.select(true);}
  90. for(let i=0;this._children&&i<this._children.length;++i){const child=this._children[i];child.previousSibling=null;child.nextSibling=null;child.parent=null;if(this.treeOutline){this.treeOutline._unbindTreeElement(child);}
  91. for(let current=child.firstChild();this.treeOutline&&current;current=current.traverseNextTreeElement(false,child,true)){this.treeOutline._unbindTreeElement(current);}
  92. child._detach();}
  93. this._children=[];if(this.treeOutline){this.treeOutline.dispatchEventToListeners(Events.ElementsDetached);}}
  94. get selectable(){if(this.isHidden()){return false;}
  95. return this._selectable;}
  96. set selectable(x){this._selectable=x;}
  97. get listItemElement(){return this._listItemNode;}
  98. get childrenListElement(){return this._childrenListNode;}
  99. get title(){return this._title;}
  100. set title(x){if(this._title===x){return;}
  101. this._title=x;if(typeof x==='string'){this.titleElement.textContent=x;this.tooltip=x;}else{this.titleElement=x;this.tooltip='';}
  102. this._listItemNode.removeChildren();if(this._leadingIconsElement){this._listItemNode.appendChild(this._leadingIconsElement);}
  103. this._listItemNode.appendChild(this.titleElement);if(this._trailingIconsElement){this._listItemNode.appendChild(this._trailingIconsElement);}
  104. this._ensureSelection();}
  105. titleAsText(){if(!this._title){return'';}
  106. if(typeof this._title==='string'){return this._title;}
  107. return this._title.textContent;}
  108. startEditingTitle(editingConfig){UI.InplaceEditor.startEditing((this.titleElement),editingConfig);this.treeOutline._shadowRoot.getSelection().selectAllChildren(this.titleElement);}
  109. setLeadingIcons(icons){if(!this._leadingIconsElement&&!icons.length){return;}
  110. if(!this._leadingIconsElement){this._leadingIconsElement=createElementWithClass('div','leading-icons');this._leadingIconsElement.classList.add('icons-container');this._listItemNode.insertBefore(this._leadingIconsElement,this.titleElement);this._ensureSelection();}
  111. this._leadingIconsElement.removeChildren();for(const icon of icons){this._leadingIconsElement.appendChild(icon);}}
  112. setTrailingIcons(icons){if(!this._trailingIconsElement&&!icons.length){return;}
  113. if(!this._trailingIconsElement){this._trailingIconsElement=createElementWithClass('div','trailing-icons');this._trailingIconsElement.classList.add('icons-container');this._listItemNode.appendChild(this._trailingIconsElement);this._ensureSelection();}
  114. this._trailingIconsElement.removeChildren();for(const icon of icons){this._trailingIconsElement.appendChild(icon);}}
  115. get tooltip(){return this._tooltip||'';}
  116. set tooltip(x){if(this._tooltip===x){return;}
  117. this._tooltip=x;this._listItemNode.title=x;}
  118. isExpandable(){return this._expandable;}
  119. setExpandable(expandable){if(this._expandable===expandable){return;}
  120. this._expandable=expandable;this._listItemNode.classList.toggle('parent',expandable);if(!expandable){this.collapse();UI.ARIAUtils.unsetExpandable(this._listItemNode);}else{UI.ARIAUtils.setExpanded(this._listItemNode,false);}}
  121. setCollapsible(collapsible){if(this._collapsible===collapsible){return;}
  122. this._collapsible=collapsible;this._listItemNode.classList.toggle('always-parent',!collapsible);if(!collapsible){this.expand();}}
  123. get hidden(){return this._hidden;}
  124. set hidden(x){if(this._hidden===x){return;}
  125. this._hidden=x;this._listItemNode.classList.toggle('hidden',x);this._childrenListNode.classList.toggle('hidden',x);if(x&&this.treeOutline&&this.treeOutline.selectedTreeElement&&this.treeOutline.selectedTreeElement.hasAncestorOrSelf(this)){const hadFocus=this.treeOutline.selectedTreeElement.listItemElement.hasFocus();this.treeOutline.forceSelect(!hadFocus,false);}}
  126. invalidateChildren(){if(this._children){this.removeChildren();this._children=null;}}
  127. _ensureSelection(){if(!this.treeOutline||!this.treeOutline._renderSelection){return;}
  128. if(!this._selectionElement){this._selectionElement=createElementWithClass('div','selection fill');}
  129. this._listItemNode.insertBefore(this._selectionElement,this.listItemElement.firstChild);}
  130. _treeElementToggled(event){const element=event.currentTarget;if(element.treeElement!==this||element.hasSelection()){return;}
  131. console.assert(!!this.treeOutline);const showSelectionOnKeyboardFocus=this.treeOutline?this.treeOutline._showSelectionOnKeyboardFocus:false;const toggleOnClick=this.toggleOnClick&&(showSelectionOnKeyboardFocus||!this.selectable);const isInTriangle=this.isEventWithinDisclosureTriangle(event);if(!toggleOnClick&&!isInTriangle){return;}
  132. if(this.expanded){if(event.altKey){this.collapseRecursively();}else{this.collapse();}}else{if(event.altKey){this.expandRecursively();}else{this.expand();}}
  133. event.consume();}
  134. _handleMouseDown(event){const element=event.currentTarget;if(!element){return;}
  135. if(!this.selectable){return;}
  136. if(element.treeElement!==this){return;}
  137. if(this.isEventWithinDisclosureTriangle(event)){return;}
  138. this.selectOnMouseDown(event);}
  139. _handleDoubleClick(event){const element=event.currentTarget;if(!element||element.treeElement!==this){return;}
  140. const handled=this.ondblclick(event);if(handled){return;}
  141. if(this._expandable&&!this.expanded){this.expand();}}
  142. _detach(){this._listItemNode.remove();this._childrenListNode.remove();}
  143. collapse(){if(!this.expanded||!this._collapsible){return;}
  144. this._listItemNode.classList.remove('expanded');this._childrenListNode.classList.remove('expanded');UI.ARIAUtils.setExpanded(this._listItemNode,false);this.expanded=false;this.oncollapse();if(this.treeOutline){this.treeOutline.dispatchEventToListeners(Events.ElementCollapsed,this);}
  145. const selectedTreeElement=this.treeOutline.selectedTreeElement;if(selectedTreeElement&&selectedTreeElement.hasAncestor(this)){this.select(true,true);}}
  146. collapseRecursively(){let item=this;while(item){if(item.expanded){item.collapse();}
  147. item=item.traverseNextTreeElement(false,this,true);}}
  148. collapseChildren(){if(!this._children){return;}
  149. for(const child of this._children){child.collapseRecursively();}}
  150. expand(){if(!this._expandable||(this.expanded&&this._children)){return;}
  151. this.expanded=true;this._populateIfNeeded();this._listItemNode.classList.add('expanded');this._childrenListNode.classList.add('expanded');UI.ARIAUtils.setExpanded(this._listItemNode,true);if(this.treeOutline){this.onexpand();this.treeOutline.dispatchEventToListeners(Events.ElementExpanded,this);}}
  152. async expandRecursively(maxDepth){let item=this;const info={};let depth=0;if(isNaN(maxDepth)){maxDepth=3;}
  153. while(item){await item._populateIfNeeded();if(depth<maxDepth){item.expand();}
  154. item=item.traverseNextTreeElement(false,this,(depth>=maxDepth),info);depth+=info.depthChange;}}
  155. collapseOrAscend(altKey){if(this.expanded&&this._collapsible){if(altKey){this.collapseRecursively();}else{this.collapse();}
  156. return true;}
  157. if(!this.parent||this.parent.root){return false;}
  158. if(!this.parent.selectable){this.parent.collapse();return true;}
  159. let nextSelectedElement=this.parent;while(nextSelectedElement&&!nextSelectedElement.selectable){nextSelectedElement=nextSelectedElement.parent;}
  160. if(!nextSelectedElement){return false;}
  161. nextSelectedElement.select(false,true);return true;}
  162. descendOrExpand(altKey){if(!this._expandable){return false;}
  163. if(!this.expanded){if(altKey){this.expandRecursively();}else{this.expand();}
  164. return true;}
  165. let nextSelectedElement=this.firstChild();while(nextSelectedElement&&!nextSelectedElement.selectable){nextSelectedElement=nextSelectedElement.nextSibling;}
  166. if(!nextSelectedElement){return false;}
  167. nextSelectedElement.select(false,true);return true;}
  168. reveal(center){let currentAncestor=this.parent;while(currentAncestor&&!currentAncestor.root){if(!currentAncestor.expanded){currentAncestor.expand();}
  169. currentAncestor=currentAncestor.parent;}
  170. this.treeOutline._deferredScrollIntoView(this,!!center);}
  171. revealed(){let currentAncestor=this.parent;while(currentAncestor&&!currentAncestor.root){if(!currentAncestor.expanded){return false;}
  172. currentAncestor=currentAncestor.parent;}
  173. return true;}
  174. selectOnMouseDown(event){if(this.select(false,true)){event.consume(true);}
  175. if(this._listItemNode.draggable&&this._selectionElement){const marginLeft=this.treeOutline.element.getBoundingClientRect().left-this._listItemNode.getBoundingClientRect().left;this._selectionElement.style.setProperty('margin-left',marginLeft+'px');}}
  176. select(omitFocus,selectedByUser){if(!this.treeOutline||!this.selectable||this.selected){if(!omitFocus){this.listItemElement.focus();}
  177. return false;}
  178. const lastSelected=this.treeOutline.selectedTreeElement;this.treeOutline.selectedTreeElement=null;if(this.treeOutline._rootElement===this){if(lastSelected){lastSelected.deselect();}
  179. if(!omitFocus){this.listItemElement.focus();}
  180. return false;}
  181. this.selected=true;this.treeOutline.selectedTreeElement=this;this.treeOutline.updateFocusable();if(!omitFocus||this.treeOutline.contentElement.hasFocus()){this.listItemElement.focus();}
  182. this._listItemNode.classList.add('selected');this.treeOutline.dispatchEventToListeners(Events.ElementSelected,this);if(lastSelected){lastSelected.deselect();}
  183. return this.onselect(selectedByUser);}
  184. _setFocusable(focusable){if(focusable){this._listItemNode.setAttribute('tabIndex',this.treeOutline&&this.treeOutline._preventTabOrder?-1:0);this._listItemNode.addEventListener('focus',this._boundOnFocus,false);this._listItemNode.addEventListener('blur',this._boundOnBlur,false);}else{this._listItemNode.removeAttribute('tabIndex');this._listItemNode.removeEventListener('focus',this._boundOnFocus,false);this._listItemNode.removeEventListener('blur',this._boundOnBlur,false);}}
  185. _onFocus(){if(this.treeOutline._useLightSelectionColor){return;}
  186. if(!this.treeOutline.contentElement.classList.contains('hide-selection-when-blurred')){this._listItemNode.classList.add('force-white-icons');}}
  187. _onBlur(){if(this.treeOutline._useLightSelectionColor){return;}
  188. if(!this.treeOutline.contentElement.classList.contains('hide-selection-when-blurred')){this._listItemNode.classList.remove('force-white-icons');}}
  189. revealAndSelect(omitFocus){this.reveal(true);this.select(omitFocus);}
  190. deselect(){const hadFocus=this._listItemNode.hasFocus();this.selected=false;this._listItemNode.classList.remove('selected');this._setFocusable(false);if(this.treeOutline&&this.treeOutline.selectedTreeElement===this){this.treeOutline.selectedTreeElement=null;this.treeOutline.updateFocusable();if(hadFocus){this.treeOutline.focus();}}}
  191. async _populateIfNeeded(){if(this.treeOutline&&this._expandable&&!this._children){this._children=[];await this.onpopulate();}}
  192. async onpopulate(){}
  193. onenter(){return false;}
  194. ondelete(){return false;}
  195. onspace(){return false;}
  196. onbind(){}
  197. onunbind(){}
  198. onattach(){}
  199. onexpand(){}
  200. oncollapse(){}
  201. ondblclick(e){return false;}
  202. onselect(selectedByUser){return false;}
  203. traverseNextTreeElement(skipUnrevealed,stayWithin,dontPopulate,info){if(!dontPopulate){this._populateIfNeeded();}
  204. if(info){info.depthChange=0;}
  205. let element=skipUnrevealed?(this.revealed()?this.firstChild():null):this.firstChild();if(element&&(!skipUnrevealed||(skipUnrevealed&&this.expanded))){if(info){info.depthChange=1;}
  206. return element;}
  207. if(this===stayWithin){return null;}
  208. element=skipUnrevealed?(this.revealed()?this.nextSibling:null):this.nextSibling;if(element){return element;}
  209. element=this;while(element&&!element.root&&!(skipUnrevealed?(element.revealed()?element.nextSibling:null):element.nextSibling)&&element.parent!==stayWithin){if(info){info.depthChange-=1;}
  210. element=element.parent;}
  211. if(!element||element.root){return null;}
  212. return(skipUnrevealed?(element.revealed()?element.nextSibling:null):element.nextSibling);}
  213. traversePreviousTreeElement(skipUnrevealed,dontPopulate){let element=skipUnrevealed?(this.revealed()?this.previousSibling:null):this.previousSibling;if(!dontPopulate&&element){element._populateIfNeeded();}
  214. while(element&&(skipUnrevealed?(element.revealed()&&element.expanded?element.lastChild():null):element.lastChild())){if(!dontPopulate){element._populateIfNeeded();}
  215. element=(skipUnrevealed?(element.revealed()&&element.expanded?element.lastChild():null):element.lastChild());}
  216. if(element){return element;}
  217. if(!this.parent||this.parent.root){return null;}
  218. return this.parent;}
  219. isEventWithinDisclosureTriangle(event){const paddingLeftValue=window.getComputedStyle(this._listItemNode).paddingLeft;console.assert(paddingLeftValue.endsWith('px'));const computedLeftPadding=parseFloat(paddingLeftValue);const left=this._listItemNode.totalOffsetLeft()+computedLeftPadding;return event.pageX>=left&&event.pageX<=left+TreeElement._ArrowToggleWidth&&this._expandable;}}
  220. TreeElement._ArrowToggleWidth=10;(function(){const img=new Image();img.src='Images/treeoutlineTriangles.svg';TreeElement._imagePreload=img;})();self.UI=self.UI||{};UI=UI||{};UI.TreeOutline=TreeOutline;UI.TreeOutline.Events=Events;UI.TreeElement=TreeElement;UI.TreeOutlineInShadow=TreeOutlineInShadow;