1/* 2 * Treeview 1.5pre - 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 5759 2008-07-01 07:50:28Z joern.zaefferer $ 14 * 15 */ 16 17;(function($) { 18 19 // TODO rewrite as a widget, removing all the extra plugins 20 $.extend($.fn, { 21 swapClass: function(c1, c2) { 22 var c1Elements = this.filter('.' + c1); 23 this.filter('.' + c2).removeClass(c2).addClass(c1); 24 c1Elements.removeClass(c1).addClass(c2); 25 return this; 26 }, 27 replaceClass: function(c1, c2) { 28 return this.filter('.' + c1).removeClass(c1).addClass(c2).end(); 29 }, 30 hoverClass: function(className) { 31 className = className || "hover"; 32 return this.hover(function() { 33 $(this).addClass(className); 34 }, function() { 35 $(this).removeClass(className); 36 }); 37 }, 38 heightToggle: function(animated, callback) { 39 animated ? 40 this.animate({ height: "toggle" }, animated, callback) : 41 this.each(function(){ 42 jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ](); 43 if(callback) 44 callback.apply(this, arguments); 45 }); 46 }, 47 heightHide: function(animated, callback) { 48 if (animated) { 49 this.animate({ height: "hide" }, animated, callback); 50 } else { 51 this.hide(); 52 if (callback) 53 this.each(callback); 54 } 55 }, 56 prepareBranches: function(settings) { 57 if (!settings.prerendered) { 58 // mark last tree items 59 this.filter(":last-child:not(ul)").addClass(CLASSES.last); 60 // collapse whole tree, or only those marked as closed, anyway except those marked as open 61 this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide(); 62 } 63 // return all items with sublists 64 return this.filter(":has(>ul)"); 65 }, 66 applyClasses: function(settings, toggler) { 67 // TODO use event delegation 68 this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) { 69 // don't handle click events on children, eg. checkboxes 70 if ( this == event.target ) 71 toggler.apply($(this).next()); 72 }).add( $("a", this) ).hoverClass(); 73 74 if (!settings.prerendered) { 75 // handle closed ones first 76 this.filter(":has(>ul:hidden)") 77 .addClass(CLASSES.expandable) 78 .replaceClass(CLASSES.last, CLASSES.lastExpandable); 79 80 // handle open ones 81 this.not(":has(>ul:hidden)") 82 .addClass(CLASSES.collapsable) 83 .replaceClass(CLASSES.last, CLASSES.lastCollapsable); 84 85 // create hitarea if not present 86 var hitarea = this.find("div." + CLASSES.hitarea); 87 if (!hitarea.length) 88 hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea); 89 hitarea.removeClass().addClass(CLASSES.hitarea).each(function() { 90 var classes = ""; 91 $.each($(this).parent().attr("class").split(" "), function() { 92 classes += this + "-hitarea "; 93 }); 94 $(this).addClass( classes ); 95 }) 96 } 97 98 // apply event to hitarea 99 this.find("div." + CLASSES.hitarea).click( toggler ); 100 }, 101 treeview: function(settings) { 102 103 settings = $.extend({ 104 cookieId: "treeview" 105 }, settings); 106 107 if ( settings.toggle ) { 108 var callback = settings.toggle; 109 settings.toggle = function() { 110 return callback.apply($(this).parent()[0], arguments); 111 }; 112 } 113 114 // factory for treecontroller 115 function treeController(tree, control) { 116 // factory for click handlers 117 function handler(filter) { 118 return function() { 119 // reuse toggle event handler, applying the elements to toggle 120 // start searching for all hitareas 121 toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() { 122 // for plain toggle, no filter is provided, otherwise we need to check the parent element 123 return filter ? $(this).parent("." + filter).length : true; 124 }) ); 125 return false;
126 }; 127 } 128 // click on first element to collapse tree 129 $("a:eq(0)", control).click( handler(CLASSES.collapsable) ); 130 // click on second to expand tree 131 $("a:eq(1)", control).click( handler(CLASSES.expandable) ); 132 // click on third to toggle tree 133 $("a:eq(2)", control).click( handler() ); 134 } 135 136 // handle toggle event 137 function toggler() { 138 $(this) 139 .parent() 140 // swap classes for hitarea 141 .find(">.hitarea") 142 .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea ) 143 .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea ) 144 .end() 145 // swap classes for parent li 146 .swapClass( CLASSES.collapsable, CLASSES.expandable ) 147 .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable ) 148 // find child lists 149 .find( ">ul" ) 150 // toggle them 151 .heightToggle( settings.animated, settings.toggle ); 152 if ( settings.unique ) { 153 $(this).parent() 154 .siblings() 155 // swap classes for hitarea 156 .find(">.hitarea") 157 .replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea ) 158 .replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea ) 159 .end() 160 .replaceClass( CLASSES.collapsable, CLASSES.expandable ) 161 .replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable ) 162 .find( ">ul" ) 163 .heightHide( settings.animated, settings.toggle ); 164 } 165 } 166 this.data("toggler", toggler); 167 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(""), settings.cookieOptions ); 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() { 208 return this.href.toLowerCase() == location.href.toLowerCase(); 209 }); 210 if ( current.length ) { 211 // TODO update the open/closed classes 212 var items = current.addClass("selected").parents("ul, li").add( current.next() ).show(); 213 if (settings.prerendered) { 214 // if prerendered is on, replicate the basic class swapping 215 items.filter("li") 216 .swapClass( CLASSES.collapsable, CLASSES.expandable ) 217 .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable ) 218 .find(">.hitarea") 219 .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea ) 220 .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea ); 221 } 222 } 223 break; 224 } 225 226 branches.applyClasses(settings, toggler); 227 228 // if control option is set, create the treecontroller and show it 229 if ( settings.control ) { 230 treeController(this, settings.control); 231 $(settings.control).show(); 232 } 233 234 return this; 235 } 236 }); 237 238 // classes used by the plugin 239 // need to be styled via external stylesheet, see first example 240 $.treeview = {}; 241 var CLASSES = ($.treeview.classes = { 242 open: "open", 243 closed: "closed", 244 expandable: "expandable", 245 expandableHitarea: "expandable-hitarea", 246 lastExpandableHitarea: "lastExpandable-hitarea", 247 collapsable: "collapsable", 248 collapsableHitarea: "collapsable-hitarea", 249 lastCollapsableHitarea: "lastCollapsable-hitarea", 250 lastCollapsable: "lastCollapsable", 251 lastExpandable: "lastExpandable", 252 last: "last", 253 hitarea: "hitarea" 254 }); 255 256})(jQuery); 257 258 259 260 261 262 263 264/** 265 * Cookie plugin 266 * 267 * Copyright (c) 2006 Klaus Hartl (stilbuero.de) 268 * Dual licensed under the MIT and GPL licenses: 269 * http://www.opensource.org/licenses/mit-license.php 270 * http://www.gnu.org/licenses/gpl.html 271 * 272 */ 273 274/** 275 * Create a cookie with the given name and value and other optional parameters. 276 * 277 * @example $.cookie('the_cookie', 'the_value'); 278 * @desc Set the value of a cookie. 279 * @example $.cookie('the_cookie', 'the_value', {expires: 7, path: '/', domain: 'jquery.com', secure: true}); 280 * @desc Create a cookie with all available options. 281 * @example $.cookie('the_cookie', 'the_value'); 282 * @desc Create a session cookie. 283 * @example $.cookie('the_cookie', null); 284 * @desc Delete a cookie by passing null as value. 285 * 286 * @param String name The name of the cookie. 287 * @param String value The value of the cookie. 288 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. 289 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. 290 * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. 291 * If set to null or omitted, the cookie will be a session cookie and will not be retained 292 * when the the browser exits. 293 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). 294 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). 295 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will 296 * require a secure protocol (like HTTPS). 297 * @type undefined 298 * 299 * @name $.cookie 300 * @cat Plugins/Cookie 301 * @author Klaus Hartl/[email protected] 302 */ 303 304/** 305 * Get the value of a cookie with the given name. 306 * 307 * @example $.cookie('the_cookie'); 308 * @desc Get the value of a cookie. 309 * 310 * @param String name The name of the cookie. 311 * @return The value of the cookie.
312 * @type String 313 * 314 * @name $.cookie 315 * @cat Plugins/Cookie 316 * @author Klaus Hartl/[email protected] 317 */ 318jQuery.cookie = function(name, value, options) { 319 if (typeof value != 'undefined') { // name and value given, set cookie 320 options = options || {}; 321 if (value === null) { 322 value = ''; 323 options.expires = -1; 324 } 325 var expires = ''; 326 if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { 327 var date; 328 if (typeof options.expires == 'number') { 329 date = new Date(); 330 date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); 331 } else { 332 date = options.expires; 333 } 334 expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE 335 } 336 var path = options.path ? '; path=' + options.path : ''; 337 var domain = options.domain ? '; domain=' + options.domain : ''; 338 var secure = options.secure ? '; secure' : ''; 339 document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); 340 } else { // only name given, get cookie 341 var cookieValue = null; 342 if (document.cookie && document.cookie != '') { 343 var cookies = document.cookie.split(';'); 344 for (var i = 0; i < cookies.length; i++) { 345 var cookie = jQuery.trim(cookies[i]); 346 // Does this cookie string begin with the name we want? 347 if (cookie.substring(0, name.length + 1) == (name + '=')) { 348 cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 349 break; 350 } 351 } 352 } 353 return cookieValue; 354 } 355}; 356 357 358 359 360 361 362 363 364 365 366$(document).ready(function(){ 367 368 // first example 369 $("#browser").treeview(); 370 371 // second example 372 $("#navigation").treeview({ 373 persist: "location", 374 collapsed: true, 375 unique: true 376 }); 377 378 // third example 379 $("#red").treeview({ 380 animated: "fast", 381 collapsed: true, 382 unique: true, 383 persist: "cookie", 384 toggle: function() { 385 window.console && console.log("%o was toggled", this); 386 } 387 }); 388 389 // fourth example 390 $("#black, #gray").treeview({ 391 control: "#treecontrol", 392 persist: "cookie", 393 cookieId: "treeview-black" 394 }); 395 396});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.