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); |