]> git.stg.codes - stg.git/blob - doc/xslt/webhelp/template/common/jquery/treeview/jquery.treeview.js
Merge branch 'master' into full-month-stats
[stg.git] / doc / xslt / webhelp / template / common / jquery / treeview / jquery.treeview.js
1 /*
2  * Treeview 1.4 - jQuery plugin to hide and show branches of a tree
3  * 
4  * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
5  * http://docs.jquery.com/Plugins/Treeview
6  *
7  * Copyright (c) 2007 Jörn Zaefferer
8  *
9  * Dual licensed under the MIT and GPL licenses:
10  *   http://www.opensource.org/licenses/mit-license.php
11  *   http://www.gnu.org/licenses/gpl.html
12  *
13  * Revision: $Id: jquery.treeview.js 4684 2008-02-07 19:08:06Z joern.zaefferer $
14  *
15  */
16
17 ;(function($) {
18
19         $.extend($.fn, {
20                 swapClass: function(c1, c2) {
21                         var c1Elements = this.filter('.' + c1);
22                         this.filter('.' + c2).removeClass(c2).addClass(c1);
23                         c1Elements.removeClass(c1).addClass(c2);
24                         return this;
25                 },
26                 replaceClass: function(c1, c2) {
27                         return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
28                 },
29                 hoverClass: function(className) {
30                         className = className || "hover";
31                         return this.hover(function() {
32                                 $(this).addClass(className);
33                         }, function() {
34                                 $(this).removeClass(className);
35                         });
36                 },
37                 heightToggle: function(animated, callback) {
38                         animated ?
39                                 this.animate({ height: "toggle" }, animated, callback) :
40                                 this.each(function(){
41                                         jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
42                                         if(callback)
43                                                 callback.apply(this, arguments);
44                                 });
45                 },
46                 heightHide: function(animated, callback) {
47                         if (animated) {
48                                 this.animate({ height: "hide" }, animated, callback);
49                         } else {
50                                 this.hide();
51                                 if (callback)
52                                         this.each(callback);                            
53                         }
54                 },
55                 prepareBranches: function(settings) {
56                         if (!settings.prerendered) {
57                                 // mark last tree items
58                                 this.filter(":last-child:not(ul)").addClass(CLASSES.last);
59                                 // collapse whole tree, or only those marked as closed, anyway except those marked as open
60                                 this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
61                         }
62                         // return all items with sublists
63                         return this.filter(":has(>ul)");
64                 },
65                 applyClasses: function(settings, toggler) {
66                         this.filter(":has(>ul):not(:has(>a))").find(">span").click(function(event) {
67                                 toggler.apply($(this).next());
68                         }).add( $("a", this) ).hoverClass();
69                         
70                         if (!settings.prerendered) {
71                                 // handle closed ones first
72                                 this.filter(":has(>ul:hidden)")
73                                                 .addClass(CLASSES.expandable)
74                                                 .replaceClass(CLASSES.last, CLASSES.lastExpandable);
75                                                 
76                                 // handle open ones
77                                 this.not(":has(>ul:hidden)")
78                                                 .addClass(CLASSES.collapsable)
79                                                 .replaceClass(CLASSES.last, CLASSES.lastCollapsable);
80                                                 
81                     // create hitarea
82                                 this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea).each(function() {
83                                         var classes = "";
84                                         $.each($(this).parent().attr("class").split(" "), function() {
85                                                 classes += this + "-hitarea ";
86                                         });
87                                         $(this).addClass( classes );
88                                 });
89                         }
90                         
91                         // apply event to hitarea
92                         this.find("div." + CLASSES.hitarea).click( toggler );
93                 },
94                 treeview: function(settings) {
95
96             if(typeof(window.treeCookieId) !== 'undefined' || window.treeCookieId === ""){
97                 treeCookieId = "treeview";
98             }
99
100                         settings = $.extend({
101                                 cookieId: treeCookieId
102                         }, settings);
103                         
104                         if (settings.add) {
105                                 return this.trigger("add", [settings.add]);
106                         }
107                         
108                         if ( settings.toggle ) {
109                                 var callback = settings.toggle;
110                                 settings.toggle = function() {
111                                         return callback.apply($(this).parent()[0], arguments);
112                                 };
113                         }
114                 
115                         // factory for treecontroller
116                         function treeController(tree, control) {
117                                 // factory for click handlers
118                                 function handler(filter) {
119                                         return function() {
120                                                 // reuse toggle event handler, applying the elements to toggle
121                                                 // start searching for all hitareas
122                                                 toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
123                                                         // for plain toggle, no filter is provided, otherwise we need to check the parent element
124                                                         return filter ? $(this).parent("." + filter).length : true;
125                                                 }) );
126                                                 return false;
127                                         };
128                                 }
129                                 // click on first element to collapse tree
130                                 $("a:eq(0)", control).click( handler(CLASSES.collapsable) );
131                                 // click on second to expand tree
132                                 $("a:eq(1)", control).click( handler(CLASSES.expandable) );
133                                 // click on third to toggle tree
134                                 $("a:eq(2)", control).click( handler() ); 
135                         }
136                 
137                         // handle toggle event
138                         function toggler() {
139                                 $(this)
140                                         .parent()
141                                         // swap classes for hitarea
142                                         .find(">.hitarea")
143                                                 .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
144                                                 .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
145                                         .end()
146                                         // swap classes for parent li
147                                         .swapClass( CLASSES.collapsable, CLASSES.expandable )
148                                         .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
149                                         // find child lists
150                                         .find( ">ul" )
151                                         // toggle them
152                                         .heightToggle( settings.animated, settings.toggle );
153                                 if ( settings.unique ) {
154                                         $(this).parent()
155                                                 .siblings()
156                                                 // swap classes for hitarea
157                                                 .find(">.hitarea")
158                                                         .replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
159                                                         .replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
160                                                 .end()
161                                                 .replaceClass( CLASSES.collapsable, CLASSES.expandable )
162                                                 .replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
163                                                 .find( ">ul" )
164                                                 .heightHide( settings.animated, settings.toggle );
165                                 }
166                         }
167                         //Cookie Persistence
168                         function serialize() {
169                                 function binary(arg) {
170                                         return arg ? 1 : 0;
171                                 }
172                                 var data = [];
173                                 branches.each(function(i, e) {
174                                         data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
175                                 });
176                                 $.cookie(settings.cookieId, data.join("") );
177                         }
178                         
179                         function deserialize() {
180                                 var stored = $.cookie(settings.cookieId);
181                                 if ( stored ) {
182                                         var data = stored.split("");
183                                         branches.each(function(i, e) {
184                                                 $(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
185                                         });
186                                 }
187                         }
188                         
189                         // add treeview class to activate styles
190                         this.addClass("treeview");
191                         
192                         // prepare branches and find all tree items with child lists
193                         var branches = this.find("li").prepareBranches(settings);
194                         
195                         switch(settings.persist) {
196                         case "cookie":
197                                 var toggleCallback = settings.toggle;
198                                 settings.toggle = function() {
199                                         serialize();
200                                         if (toggleCallback) {
201                                                 toggleCallback.apply(this, arguments);
202                                         }
203                                 };
204                                 deserialize();
205                                 break;
206                         case "location":
207                                 var current = this.find("a").filter(function() { return this.href.toLowerCase() == location.href.toLowerCase(); });
208                                 if ( current.length ) {
209                                         current.addClass("selected").parents("ul, li").add( current.next() ).show();
210                                 }
211                                 break;
212                         }
213                         
214                         branches.applyClasses(settings, toggler);
215                                 
216                         // if control option is set, create the treecontroller and show it
217                         if ( settings.control ) {
218                                 treeController(this, settings.control);
219                                 $(settings.control).show();
220                         }
221                         
222                         return this.bind("add", function(event, branches) {
223                                 $(branches).prev()
224                                         .removeClass(CLASSES.last)
225                                         .removeClass(CLASSES.lastCollapsable)
226                                         .removeClass(CLASSES.lastExpandable)
227                                 .find(">.hitarea")
228                                         .removeClass(CLASSES.lastCollapsableHitarea)
229                                         .removeClass(CLASSES.lastExpandableHitarea);
230                                 $(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, toggler);
231                         });
232                 }
233         });
234         
235         // classes used by the plugin
236         // need to be styled via external stylesheet, see first example
237         var CLASSES = $.fn.treeview.classes = {
238                 open: "open",
239                 closed: "closed",
240                 expandable: "expandable",
241                 expandableHitarea: "expandable-hitarea",
242                 lastExpandableHitarea: "lastExpandable-hitarea",
243                 collapsable: "collapsable",
244                 collapsableHitarea: "collapsable-hitarea",
245                 lastCollapsableHitarea: "lastCollapsable-hitarea",
246                 lastCollapsable: "lastCollapsable",
247                 lastExpandable: "lastExpandable",
248                 last: "last",
249                 hitarea: "hitarea"
250         };
251         
252         // provide backwards compability
253         $.fn.Treeview = $.fn.treeview;
254         
255 })(jQuery);