1+ /***************************************************************************************
2+ Nested list collapsing script written by Mark Wilton-Jones - 21/11/2003
3+ Version 2.3.0 - this script takes existing HTML nested UL or OL lists, and collapses them
4+ Updated 13/02/2004 to allow links in root of expanding branch
5+ Updated 09/09/2004 to allow state to be saved
6+ Updated 07/10/2004 to allow page address links to be highlighted
7+ Updated 28/11/2004 to allow you to force expand/collapse links to use just the extraHTML
8+ Updated 23/09/2006 to add expandCollapseAll and to allow selfLink to locate custom links
9+ ****************************************************************************************
10+
11+ Please see http: //www.howtocreate.co.uk/jslibs/ for details and a demo of this script
12+ Please see http: //www.howtocreate.co.uk/jslibs/termsOfUse.html for terms of use
13+ _________________________________________________________________________
14+
15+ You can put as many lists on the page as you like, each list may have a different format.
16+
17+ To use:
18+ _________________________________________________________________________
19+
20+ Inbetween the <head> tags, put:
21+
22+ <script src="PATH TO SCRIPT/listCollapse.js" type="text/javascript" language="javascript1.2"></script>
23+ _________________________________________________________________________
24+
25+ Define the HTML. Note that to correctly nest lists, child OLs or ULs should be children of an LI element,
26+ not direct descendents of their parent OL/UL. The text used to expand the branch should be written
27+ between the <li> tag and the <UL/OL/A> tag, and should only contain HTML that is permitted inside an 'A'
28+ element. Note; Opera 7 will lose any style attributes you define in this text - use classes instead.
29+
30+ <ul id="someID">
31+ <li>Book 1
32+ <ul>
33+ <li><a href="someHref">Chapter 1</a></li>
34+ <li><a href="someHref">Chapter 2</a></li>
35+ </ul>
36+ </li>
37+ <li><a href="elsewhere.html">Book 2</a>
38+ <ul>
39+ <li><a href="someHref">Chapter 1</a></li>
40+ <li><a href="someHref">Chapter 2</a></li>
41+ </ul>
42+ </li>
43+ <li>Book 3
44+ <ul>
45+ <li><a href="someHref">Chapter 1</a></li>
46+ <li>Cha<span class="doMore">pt</span>er 2
47+ <ul>
48+ <li><a href="someHref">Sub 1</a></li>
49+ <li><a href="someHref">Sub 2</a></li>
50+ </ul>
51+ </li>
52+ </ul>
53+ </li>
54+ </ul>
55+ ________________________________________________________________________
56+ Now you need to trigger the collapsing, using <body onload, window.onload or by putting the collapse
57+ commands in a script just before the </body> tag. If using either onload technique, you must not use
58+ any other scripts that rely on the onload event.
59+
60+ compactMenu(theRootID,shouldAutoCollapse,extraHTML[,useMinimalLink]);
61+ oID = string: ID of root nest element, must be a UL or OL; this will not be collapsed, but any child
62+ UL/OLs will be (note, if the root nest element is a UL, all child lists should be ULs - the same is
63+ true for OLs; if the root nest element is OL, all child lists should be OLs)
64+ shouldAutoCollapse = bool: auto-collapse unused branches
65+ extraHTML = string: HTML to insert to collapsible branches - usually '± '
66+ useMinimalLink = bool: normally the expand/collapse link will use both extraHTML and the original list
67+ item text - if the list item text is already a link, this will not be included - set this option to
68+ true to force the script to use only the extraHTML as the link, even if the rest of the list item is
69+ not a link - this option will only be respected if you also provide some extraHTML
70+
71+ eg 1.
72+ <body onload="compactMenu('someID',true,'± ');">
73+
74+ eg 2.
75+ <script type="text/javascript" language="javascript1.2"><!--
76+ window.onload = function () { compactMenu('someID',false,'± '); }
77+ //--></script>
78+
79+ eg 3.
80+ <script type="text/javascript" language="javascript1.2"><!--
81+ compactMenu('someID',true,'± ');
82+ //--></script>
83+ </body>
84+
85+ stateToFromStr(theRootID);
86+ oID = string: ID of root nest element, must be a UL or OL; returns a string representing all expanding
87+ branches - can be used with my cookie script to save state when unloading the page
88+ stateToFromStr(theRootID,stringRepresentation);
89+ oID = string: ID of root nest element, must be a UL or OL;
90+ stringRepresentation = string: string representation of expanded branches, as created above
91+ must be called _after_ collapsing the list - values can be recovered from cookies using my cookie script
92+ note: this facility will not be able to take changes in the list structure into account - use session cookies
93+ or short-term cookies to avoid longer term structure change problems
94+
95+ selfLink(theRootID,newClass,shouldExpandBranch[,linkHref]);
96+ theRootID = string: ID of root nest element, must be a UL or OL;
97+ newClass = string: new class name to add to any existing class names
98+ shouldExpandBranch = bool: expand branches to show the first matching link
99+ linkHref = string: by default, it will try to locate links to the current page address - you can
100+ override that here by giving a specific address that it should look for.
101+ Allows you to highlight links to the current page that appear in the list
102+ must be called _after_ collapsing the list
103+ address hash and port are not included in the comparison - links containing href = "#" are always ignored
104+
105+ expandCollapseAll(theRootID,shouldExpand);
106+ theRootID = string: ID of root nest element, must be a UL or OL that has been collapsed using compactMenu
107+ shouldExpand = bool: says if it should expand all branches (true) or collapse all branches (false)
108+ Expands/collapses all branches in a collapsed list. Must not be used with auto-collapsing lists.
109+
110+ My cookie script is available on http: //www.howtocreate.co.uk/jslibs/
111+ <body onload="compactMenu('someID',true,'± ');stateToFromStr(theRootID,retrieveCookie('menuState'));"
112+ onunload="setCookie('menuState',stateToFromStr(theRootID),31536000);">
113+ ____________________________________________________________________________________________________*/
114+ var openLists = [ ] , oIcount = 0 ;
115+ function compactMenu ( oID , oAutoCol , oPlMn , oMinimalLink ) {
116+ if ( ! document . getElementsByTagName || ! document . childNodes || ! document . createElement ) { return ; }
117+ var baseElement = document . getElementById ( oID ) ; if ( ! baseElement ) { return ; }
118+ compactChildren ( baseElement , 0 , oID , oAutoCol , oPlMn , baseElement . tagName . toUpperCase ( ) , oMinimalLink && oPlMn ) ;
119+ }
120+ function compactChildren ( oOb , oLev , oBsID , oCol , oPM , oT , oML ) {
121+ if ( ! oLev ) { oBsID = escape ( oBsID ) ; if ( oCol ) { openLists [ oBsID ] = [ ] ; } }
122+ for ( var x = 0 , y = oOb . childNodes ; x < y . length ; x ++ ) { if ( y [ x ] . tagName ) {
123+ //for each immediate LI child
124+ var theNextUL = y [ x ] . getElementsByTagName ( oT ) [ 0 ] ;
125+ if ( theNextUL ) {
126+ //collapse the first UL/OL child
127+ theNextUL . style . display = 'none' ;
128+ //create a link for expanding/collapsing
129+ var newLink = document . createElement ( 'A' ) ;
130+ newLink . setAttribute ( 'href' , '#' ) ;
131+ newLink . onclick = new Function ( 'clickSmack(this,' + oLev + ',\'' + oBsID + '\',' + oCol + ',\'' + escape ( oT ) + '\');return false;' ) ;
132+ //wrap everything upto the child U/OL in the link
133+ if ( oML ) { var theHTML = '' ; } else {
134+ var theT = y [ x ] . innerHTML . toUpperCase ( ) . indexOf ( '<' + oT ) ;
135+ var theA = y [ x ] . innerHTML . toUpperCase ( ) . indexOf ( '<A' ) ;
136+ var theHTML = y [ x ] . innerHTML . substr ( 0 , ( theA + 1 && theA < theT ) ? theA : theT ) ;
137+ while ( ! y [ x ] . childNodes [ 0 ] . tagName || ( y [ x ] . childNodes [ 0 ] . tagName . toUpperCase ( ) != oT && y [ x ] . childNodes [ 0 ] . tagName . toUpperCase ( ) != 'A' ) ) {
138+ y [ x ] . removeChild ( y [ x ] . childNodes [ 0 ] ) ; }
139+ }
140+ y [ x ] . insertBefore ( newLink , y [ x ] . childNodes [ 0 ] ) ;
141+ y [ x ] . childNodes [ 0 ] . innerHTML = oPM + theHTML . replace ( / ^ \s * | \s * $ / g, '' ) ;
142+ theNextUL . MWJuniqueID = oIcount ++ ;
143+ compactChildren ( theNextUL , oLev + 1 , oBsID , oCol , oPM , oT , oML ) ;
144+ } } } }
145+ function clickSmack ( oThisOb , oLevel , oBsID , oCol , oT ) {
146+ if ( oThisOb . blur ) { oThisOb . blur ( ) ; }
147+ oThisOb = oThisOb . parentNode . getElementsByTagName ( unescape ( oT ) ) [ 0 ] ;
148+ if ( oCol ) {
149+ for ( var x = openLists [ oBsID ] . length - 1 ; x >= oLevel ; x -= 1 ) { if ( openLists [ oBsID ] [ x ] ) {
150+ openLists [ oBsID ] [ x ] . style . display = 'none' ; if ( oLevel != x ) { openLists [ oBsID ] [ x ] = null ; }
151+ } }
152+ if ( oThisOb == openLists [ oBsID ] [ oLevel ] ) { openLists [ oBsID ] [ oLevel ] = null ; }
153+ else { oThisOb . style . display = 'block' ; openLists [ oBsID ] [ oLevel ] = oThisOb ; }
154+ } else { oThisOb . style . display = ( oThisOb . style . display == 'block' ) ? 'none' : 'block' ; }
155+ }
156+ function stateToFromStr ( oID , oFStr ) {
157+ if ( ! document . getElementsByTagName || ! document . childNodes || ! document . createElement ) { return '' ; }
158+ var baseElement = document . getElementById ( oID ) ; if ( ! baseElement ) { return '' ; }
159+ if ( ! oFStr && typeof ( oFStr ) != 'undefined' ) { return '' ; } if ( oFStr ) { oFStr = oFStr . split ( ':' ) ; }
160+ for ( var oStr = '' , l = baseElement . getElementsByTagName ( baseElement . tagName ) , x = 0 ; l [ x ] ; x ++ ) {
161+ if ( oFStr && MWJisInTheArray ( l [ x ] . MWJuniqueID , oFStr ) && l [ x ] . style . display == 'none' ) { l [ x ] . parentNode . getElementsByTagName ( 'a' ) [ 0 ] . onclick ( ) ; }
162+ else if ( l [ x ] . style . display != 'none' ) { oStr += ( oStr ?':' :'' ) + l [ x ] . MWJuniqueID ; }
163+ }
164+ return oStr ;
165+ }
166+ function MWJisInTheArray ( oNeed , oHay ) { for ( var i = 0 ; i < oHay . length ; i ++ ) { if ( oNeed == oHay [ i ] ) { return true ; } } return false ; }
167+ function selfLink ( oRootElement , oClass , oExpand , oLink ) {
168+ var tmpLink ;
169+ if ( ! document . getElementsByTagName || ! document . childNodes ) { return ; }
170+ oRootElement = document . getElementById ( oRootElement ) ;
171+ if ( oLink ) {
172+ tmpLink = document . createElement ( 'a' ) ;
173+ tmpLink . setAttribute ( 'href' , oLink ) ;
174+ }
175+ for ( var x = 0 , y = oRootElement . getElementsByTagName ( 'a' ) ; y [ x ] ; x ++ ) {
176+ if ( y [ x ] . getAttribute ( 'href' ) && ! y [ x ] . href . match ( / # $ / ) && getRealAddress ( y [ x ] ) == getRealAddress ( oLink ?tmpLink :location ) ) {
177+ y [ x ] . className = ( y [ x ] . className ?( y [ x ] . className + ' ' ) :'' ) + oClass ;
178+ if ( oExpand ) {
179+ oExpand = false ;
180+ for ( var oEl = y [ x ] . parentNode , ulStr = '' ; oEl != oRootElement && oEl != document . body ; oEl = oEl . parentNode ) {
181+ if ( oEl . tagName && oEl . tagName == oRootElement . tagName ) { ulStr = oEl . MWJuniqueID + ( ulStr ?( ':' + ulStr ) :'' ) ; } }
182+ stateToFromStr ( oRootElement . id , ulStr ) ;
183+ } } } }
184+ function getRealAddress ( oOb ) { return oOb . protocol + ( ( oOb . protocol . indexOf ( ':' ) + 1 ) ? '' : ':' ) + oOb . hostname + ( ( typeof ( oOb . pathname ) == typeof ( ' ' ) && oOb . pathname . indexOf ( '/' ) != 0 ) ? '/' : '' ) + oOb . pathname + oOb . search ; }
185+ function expandCollapseAll ( oElID , oState ) {
186+ if ( ! document . getElementsByTagName || ! document . childNodes ) { return ; }
187+ var oEl = document . getElementById ( oElID ) ;
188+ var oT = oEl . tagName ;
189+ var oULs = oEl . getElementsByTagName ( oT ) ;
190+ for ( var i = 0 , oLnk ; i < oULs . length ; i ++ ) {
191+ if ( typeof ( oULs [ i ] . MWJuniqueID ) != 'undefined' ) {
192+ oLnk = oULs [ i ] . parentNode . getElementsByTagName ( 'a' ) [ 0 ] ;
193+ if ( oLnk && ( ( oState && oULs [ i ] . style . display == 'none' ) || ( ! oState && oULs [ i ] . style . display != 'none' ) ) ) {
194+ oLnk . onclick ( ) ;
195+ } } } }
196+
197+ jQuery ( function ( $ ) {
198+ compactMenu ( 'tree-list' , true , '' ) ;
199+ } ) ;
0 commit comments