2024-01-08 21:41:43 +00:00
/ * *
* BBTreeview
2024-01-09 21:26:40 +00:00
* @ version v0 . 1.2 . 044 ( 2024 / 01 / 09 2118 )
2024-01-08 21:41:43 +00:00
* /
2024-01-09 21:26:40 +00:00
class BBTreeview { constructor ( a ) { this . Options = { } ; this . initialiseComponents ( a ) } initialiseComponents ( a ) { this . Options = Object . assign ( { ID : null , ShowCheckbox : ! 1 , ShowSelection : ! 0 , EnablePullUp : ! 1 , ShowIcon : ! 0 } , a ) ; this . createTreeview ( ) } get Container ( ) { return this . getTreeview ( ) } AddItem ( a ) { a = Object . assign ( { ID : null , ParentID : null , Name : "" , Hint : "" , Value : "" , Icon : "folder" , Checked : ! 1 , Tag : null } , a ) ; null == a . ID && ( a . ID = this . generateID ( ) ) ; null == a . Tag && ( a . Tag = "" ) ; if ( null != this . Find ( a . ID ) ) return ! 1 ; let b = null ; if ( null != a . ParentID &&
( b = this . Find ( a . ParentID ) , null == b ) ) return ! 1 ; b = null == b ? this . Container : b . ChildNode ; const c = this . generateNodeHtml ( a ) ; this . appendHtml ( b , c ) ; this . Find ( a . ID ) . InvalidateEvents ( ) ; return ! 0 } Remove ( a ) { a = this . Find ( a ) ; if ( null == a ) return ! 1 ; a . Remove ( ) ; return ! 0 } Clear ( ) { this . initialiseComponents ( this . Options ) } CollapseAll ( ) { this . GetAllNodes ( ) . forEach ( function ( a ) { a . Collapse ( ) } ) } ExpandAll ( ) { this . GetAllNodes ( ) . forEach ( function ( a ) { a . Expand ( ) } ) } CheckAll ( a ) { this . Options . ShowCheckbox && this . GetAllNodes ( ) . forEach ( function ( b ) { b . Check ( a ) } ) } Find ( a ) { if ( null ==
this . Container ) console . log ( "BBTreeview container not found" ) ; else return a = this . Container . querySelectorAll ( "li[data-bbtv-id='" + a + "']" ) , 0 >= a . length ? null : new BBTreeviewNode ( this , a [ 0 ] ) } FindByName ( a ) { let b = [ ] ; this . GetAllNodes ( ) . forEach ( function ( c ) { c . Name == a && b . push ( c ) } ) ; return b } FindByValue ( a ) { let b = [ ] ; this . GetAllNodes ( ) . forEach ( function ( c ) { c . Value == a && b . push ( c ) } ) ; return b } GetAllNodes ( ) { const a = this , b = a . Container . querySelectorAll ( "li" ) ; if ( 0 >= b . length ) return [ ] ; let c = [ ] ; b . forEach ( function ( d ) { d = d . getAttribute ( "data-bbtv-id" ) ;
a . isNullOrWhitespace ( d ) || ( d = a . Find ( d ) , null != d && c . push ( d ) ) } ) ; return c } GetCheckedNodes ( ) { let a = [ ] ; this . GetAllNodes ( ) . forEach ( function ( b ) { b . IsChecked && a . push ( b ) } ) ; return a } GetCheckedValues ( ) { let a = [ ] ; this . GetCheckedNodes ( ) . map ( function ( b ) { a . push ( b . Value ) } ) ; return a } GetCheckedTags ( ) { let a = [ ] ; this . GetCheckedNodes ( ) . map ( function ( b ) { a . push ( b . Tag ) } ) ; return a } GetSelectedNode ( ) { let a = null ; this . GetAllNodes ( ) . forEach ( function ( b ) { if ( b . IsHighlighted ) return a = b , ! 1 } ) ; return a } appendHtml ( a , b ) { let c = document . createElement ( "template" ) ;
c . innerHTML = b ; c = c . content . firstChild ; a . appendChild ( c ) } createTreeview ( ) { let a = this . getContainer ( ) ; null != a && ( a . innerHTML = '<ul class="bbtreeview"></ul>' ) } generateID ( ) { return "treeviewItem" + ( Math . floor ( 1000001 * Math . random ( ) ) + 100 ) . toString ( ) } generateNodeHtml ( a ) { var b = "" ; this . isNullOrWhitespace ( a . Tag ) || ( b = encodeURIComponent ( JSON . stringify ( a . Tag ) ) ) ; b = '<li data-bbtv-id="' + a . ID + '" data-bbtv-value="' + a . Value + '" data-bbtv-tag="' + b + '">' ; b += '<div class="li">' ; this . Options . ShowCheckbox && ( b += '<div class="icon checkbox"></div>' ) ;
this . Options . ShowIcon ? ( b += '<div class="icon ' + a . Icon + '"></div>' , b += '<span title="' + a . Hint + '">' + a . Name + "</span>" ) : b += '<span class="noicon" title="' + a . Hint + '">' + a . Name + "</span>" ; return b + "</div><ul></ul></li>" } getContainer ( ) { let a = document . getElementsByTagName ( "body" ) ; if ( ! ( 0 >= a . length || ( a = a [ 0 ] , a = a . querySelectorAll ( this . Options . ID ) , 0 >= a . length ) ) ) return a = a [ 0 ] } getNode ( a ) { a = ( this . isTag ( a , "li" ) ? a : this . parentsUntilTagName ( a , "li" ) ) . getAttribute ( "data-bbtv-id" ) ; return this . isNullOrWhitespace ( a ) ? null : this . Find ( a ) } getTreeview ( ) { let a =
this . getContainer ( ) ; if ( null != a && ( a = a . querySelectorAll ( "ul.bbtreeview" ) , ! ( 0 >= a . length ) ) ) return a = a [ 0 ] } isNullOrWhitespace ( a ) { return "undefined" == typeof a || null == a ? ! 0 : 0 >= a . toString ( ) . trim ( ) . length } isTag ( a , b ) { return a . tagName . toLowerCase ( ) == b } parentsUntilTagName ( a , b ) { for ( ; "undefined" != typeof a . parentNode ; ) { a = a . parentNode ; if ( "undefined" == typeof a ) break ; if ( this . isTag ( a , "ul" ) && a . classList . contains ( "bbtreeview" ) ) return null ; if ( this . isTag ( a , b ) ) break } return a } } ; class BBTreeviewNode { constructor ( a , b ) { this . Treeview = a ; this . Node = b } get Checkbox ( ) { if ( ! this . Treeview . Options . ShowCheckbox ) return null ; const a = this . Node . querySelectorAll ( "div.icon.checkbox" ) ; return "undefined" == typeof a ? null : a [ 0 ] } get ChildNode ( ) { let a = this . Node . querySelectorAll ( "ul" ) ; return 0 >= a . length ? null : a [ 0 ] } get ChildNodes ( ) { const a = this . ChildNode ; if ( null == a ) return [ ] ; let b = a . querySelectorAll ( "li" ) ; if ( 0 >= b . length ) return [ ] ; let c = [ ] ; b . forEach ( function ( d ) { "undefined" != typeof d . parentNode && d . parentNode ==
a && c . push ( d ) } ) ; return c } get IsChecked ( ) { return this . Treeview . Options . ShowCheckbox ? this . Node . classList . contains ( "x" ) : ! 1 } get Container ( ) { return this . Node . querySelectorAll ( "div.li" ) [ 0 ] } get Hint ( ) { return this . Label . getAttribute ( "title" ) } get ID ( ) { return this . Node . getAttribute ( "data-bbtv-id" ) } get IsExpanded ( ) { return this . Node . classList . contains ( "e" ) ? ! 0 : this . Node . classList . contains ( "c" ) ? ! 1 : null } get IsHighlighted ( ) { return this . Container . classList . contains ( "highlighted" ) } get Label ( ) { return this . Node . querySelectorAll ( "span" ) [ 0 ] } get Name ( ) { return this . Label . textContent } get ParentID ( ) { const a =
this . ParentNode ; return null == a ? null : a . getAttribute ( "data-bbtv-id" ) } get ParentNode ( ) { return this . parentsUntilTagName ( this . Node , "li" ) } get Tag ( ) { let a = this . Node . getAttribute ( "data-bbtv-tag" ) ; return this . Treeview . isNullOrWhitespace ( a ) ? null : JSON . parse ( decodeURIComponent ( a ) ) } get Value ( ) { return this . Node . getAttribute ( "data-bbtv-value" ) } Check ( a ) { const b = this ; b . setCheckbox ( b . Node , a ) ; b . Node . querySelectorAll ( "li" ) . forEach ( function ( d ) { b . setCheckbox ( d , a ) } ) ; let c = b . ParentNode ; if ( null != c ) if ( b . Treeview . Options . EnablePullUp ) for ( ; ; ) { const d =
0 < c . querySelectorAll ( "li.x" ) . length ; b . setCheckbox ( c , d ) ; c = b . Treeview . getNode ( c ) ; c = c . ParentNode ; if ( null == c ) break } else { let d = 0 ; c . querySelectorAll ( "li" ) . forEach ( function ( e ) { e . classList . contains ( "x" ) || d ++ } ) ; b . setCheckbox ( c , 0 >= d ) } } Collapse ( ) { this . Node . classList . contains ( "e" ) && ( this . Node . classList . remove ( "e" ) , this . Node . classList . add ( "c" ) ) ; this . ChildNodes . forEach ( function ( a ) { a . classList . add ( "hidden" ) } ) } Expand ( ) { this . Node . classList . contains ( "c" ) && ( this . Node . classList . remove ( "c" ) , this . Node . classList . add ( "e" ) ) ;
this . ChildNodes . forEach ( function ( a ) { a . classList . remove ( "hidden" ) } ) } Remove ( ) { null != this . ParentNode && ( this . ParentNode . classList . contains ( "e" ) && this . ParentNode . classList . remove ( "e" ) , this . ParentNode . classList . contains ( "c" ) && this . ParentNode . classList . remove ( "c" ) ) ; this . Node . parentNode . removeChild ( this . Node ) } InvalidateEvents ( ) { const a = this ; a . Node . addEventListener ( "click" , function ( b ) { b . stopPropagation ( ) ; b . preventDefault ( ) ; ! a . isTag ( b . target , "li" ) || 0 > b . offsetX || 16 < b . offsetX || 0 > b . offsetY || 16 < b . offsetY || ( b = a . Treeview . getNode ( b . target ) ,
null != b && b . Toggle ( ) ) } ) ; a . Container . addEventListener ( "dblclick" , function ( b ) { b . stopPropagation ( ) ; b . preventDefault ( ) ; b = a . Treeview . getNode ( b . target ) ; null != b && b . Toggle ( ) } ) ; a . Treeview . Options . ShowCheckbox && ( a . Checkbox . addEventListener ( "mousedown" , function ( b ) { b . stopPropagation ( ) ; b . preventDefault ( ) ; a . Check ( ! a . IsChecked ) } ) , a . Checkbox . addEventListener ( "click" , function ( b ) { b . stopPropagation ( ) ; b . preventDefault ( ) } ) , a . Checkbox . addEventListener ( "dblclick" , function ( b ) { b . stopPropagation ( ) ; b . preventDefault ( ) } ) ) ; a . Container . addEventListener ( "mousedown" ,
function ( b ) { b . stopPropagation ( ) ; b . preventDefault ( ) ; b = a . Treeview . getNode ( b . target ) ; null != b && ( a . Treeview . Container . querySelectorAll ( "div.highlighted" ) . forEach ( function ( c ) { c . classList . remove ( "highlighted" ) } ) , a . Treeview . Options . ShowSelection && b . Container . classList . add ( "highlighted" ) ) } ) ; a . invalidateCollapsible ( ) } Toggle ( ) { switch ( this . IsExpanded ) { case ! 0 : this . Collapse ( ) ; break ; case ! 1 : this . Expand ( ) } } invalidateCollapsible ( ) { null != this . ParentNode && ( this . ParentNode . classList . contains ( "c" ) ? this . Node . classList . add ( "hidden" ) :
( this . ParentNode . classList . contains ( "e" ) || this . ParentNode . classList . add ( "e" ) , this . Node . classList . remove ( "hidden" ) ) ) } isTag ( a , b ) { return a . tagName . toLowerCase ( ) == b } parentsUntilTagName ( a , b ) { for ( ; "undefined" != typeof a . parentNode ; ) { a = a . parentNode ; if ( "undefined" == typeof a ) break ; if ( this . isTag ( a , "ul" ) && a . classList . contains ( "bbtreeview" ) ) return null ; if ( this . isTag ( a , b ) ) break } return a } setCheckbox ( a , b ) { b ? a . classList . contains ( "x" ) || a . classList . add ( "x" ) : a . classList . contains ( "x" ) && a . classList . remove ( "x" ) } } ;