2024-01-08 21:41:43 +00:00
/ * *
* BBTreeview
* @ version v0 . 1.2 . 011 ( 2024 / 01 / 07 0208 )
* /
2024-01-09 02:12:51 +00:00
class BBTreeview { constructor ( a ) { this . Options = null ; this . initialiseComponents ( a ) } initialiseComponents ( a ) { this . Options = Object . assign ( { ID : null , ShowCheckbox : ! 1 , ShowSelection : ! 0 , EnablePullUp : ! 1 , ShowIcon : ! 0 } , a ) } get Container ( ) { let a = document . getElementsByTagName ( "body" ) ; if ( 0 >= a . length ) return null ; a = a [ 0 ] . querySelectorAll ( this . Options . ID ) ; if ( ! ( 0 >= a . length || ( a [ 0 ] . innerHTML = '<ul class="bbtreeview"></ul>' , a [ 0 ] . querySelectorAll ( "ul.bbtreeview" ) , 0 >= a . length ) ) ) return a [ 0 ] } AddItem ( a ) { a = this . getOptions ( a ) ; 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 . GetChildNode ( ) ; if ( null == b ) return ! 1 ; const c = this . generateNodeHtml ( a ) ; this . appendHtml ( b , c ) ; this . Find ( a . ID ) ; 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 &&
2024-01-08 23:45:52 +00:00
this . GetAllNodes ( ) . forEach ( function ( b ) { b . IsChecked = a } ) } Find ( a ) { if ( null == this . Container ) console . log ( "BBTreeview container not found" ) ; else { a = this . Container . querySelectorAll ( "li[data-bbtv-id='" + a + "']" ) ; if ( 0 >= a . length ) return null ; var b = new BBTreeviewNode ( this ) ; b . Load ( a [ 0 ] ) ; return b } } 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 . Checked && 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 . Highlighted ) return a =
b , ! 1 } ) ; return a } appendHtml ( a , b ) { let c = document . createElement ( "template" ) ; c . innerHTML = b ; c = c . content . firstChild ; a . appendChild ( c ) } 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 ?
2024-01-09 02:12:51 +00:00
( 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>" } getNode ( a ) { a = ( this . isTag ( a , "li" ) ? a : this . parentsUntilTagName ( a , "li" ) ) . getAttribute ( "data-bbtv-id" ) ; return this . isNullOrWhitespace ( a ) ? null : this . Find ( a ) } getOptions ( 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 = "" ) ; return a } 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 ) { this . Treeview = a ; this . Value = this . Label = this . Container = this . Node = this . ID = null ; this . Hint = this . Name = "" ; this . ParentID = null ; this . Highlighted = this . IsChecked = ! 1 ; this . Tag = null ; this . initialiseComponents ( ) } initialiseComponents ( ) { } get IsChecked ( ) { return this . Treeview . Options . ShowCheckbox ? this . Node . classList . contains ( "x" ) : ! 1 } set IsChecked ( 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 !=
2024-01-08 23:45:52 +00:00
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 ) } } 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 Tag ( ) { let a = this . Node . getAttribute ( "data-bbtv-tag" ) ;
return this . Treeview . isNullOrWhitespace ( a ) ? null : JSON . parse ( decodeURIComponent ( a ) ) } get ParentNodeID ( ) { const a = this . ParentNode ; return null == a ? null : a . getAttribute ( "data-bbtv-id" ) } get ParentNode ( ) { return this . parentsUntilTagName ( this . Node , "li" ) } Load ( a ) { this . ID = a . getAttribute ( "data-bbtv-id" ) ; this . Node = a ; this . Container = a . querySelectorAll ( "div.li" ) [ 0 ] ; this . Label = a . querySelectorAll ( "span" ) [ 0 ] ; this . Value = a . getAttribute ( "data-bbtv-value" ) ; this . Name = this . Label . textContent ; this . Hint = this . Label . getAttribute ( "title" ) ;
this . ParentID = this . ParentNodeID ; this . IsChecked = this . IsChecked ; this . Highlighted = this . IsHighlighted ; this . Tag = this . Tag ; this . initialiseComponents _Events ( ) } Collapse ( ) { this . Node . classList . contains ( "e" ) && ( this . Node . classList . remove ( "e" ) , this . Node . classList . add ( "c" ) ) ; this . GetChildNodes ( ) . forEach ( function ( a ) { a . classList . add ( "hidden" ) } ) } Expand ( ) { this . Node . classList . contains ( "c" ) && ( this . Node . classList . remove ( "c" ) , this . Node . classList . add ( "e" ) ) ; this . GetChildNodes ( ) . forEach ( function ( a ) { a . classList . remove ( "hidden" ) } ) } GetCheckbox ( ) { if ( ! this . Treeview . Options . ShowCheckbox ) return null ;
const a = this . Node . querySelectorAll ( "div.icon.checkbox" ) ; return "undefined" == typeof a ? null : a [ 0 ] } GetChildNode ( ) { let a = this . Node . querySelectorAll ( "ul" ) ; return 0 >= a . length ? null : a [ 0 ] } GetChildNodes ( ) { const a = this . GetChildNode ( ) ; 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 } 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 ) } Toggle ( ) { switch ( this . IsExpanded ) { case ! 0 : this . Collapse ( ) ; break ; case ! 1 : this . Expand ( ) } } initialiseComponents _Events ( ) { 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 . GetCheckbox ( ) . addEventListener ( "mousedown" , function ( b ) { b . stopPropagation ( ) ; b . preventDefault ( ) ; a . IsChecked = ! a . IsChecked } ) , a . GetCheckbox ( ) . addEventListener ( "click" , function ( b ) { b . stopPropagation ( ) ; b . preventDefault ( ) } ) , a . GetCheckbox ( ) . 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 ( ) } 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" ) } } ;