2  * Treeview 1.4 - jQuery plugin to hide and show branches of a tree
 
   4  * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
 
   5  * http://docs.jquery.com/Plugins/Treeview
 
   7  * Copyright (c) 2007 Jörn Zaefferer
 
   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
 
  13  * Revision: $Id: jquery.treeview.js 4684 2008-02-07 19:08:06Z joern.zaefferer $
 
  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);
 
  26                 replaceClass: function(c1, c2) {
 
  27                         return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
 
  29                 hoverClass: function(className) {
 
  30                         className = className || "hover";
 
  31                         return this.hover(function() {
 
  32                                 $(this).addClass(className);
 
  34                                 $(this).removeClass(className);
 
  37                 heightToggle: function(animated, callback) {
 
  39                                 this.animate({ height: "toggle" }, animated, callback) :
 
  41                                         jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
 
  43                                                 callback.apply(this, arguments);
 
  46                 heightHide: function(animated, callback) {
 
  48                                 this.animate({ height: "hide" }, animated, callback);
 
  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();
 
  62                         // return all items with sublists
 
  63                         return this.filter(":has(>ul)");
 
  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();
 
  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);
 
  77                                 this.not(":has(>ul:hidden)")
 
  78                                                 .addClass(CLASSES.collapsable)
 
  79                                                 .replaceClass(CLASSES.last, CLASSES.lastCollapsable);
 
  82                                 this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea).each(function() {
 
  84                                         $.each($(this).parent().attr("class").split(" "), function() {
 
  85                                                 classes += this + "-hitarea ";
 
  87                                         $(this).addClass( classes );
 
  91                         // apply event to hitarea
 
  92                         this.find("div." + CLASSES.hitarea).click( toggler );
 
  94                 treeview: function(settings) {
 
  96             if(typeof(window.treeCookieId) !== 'undefined' || window.treeCookieId === ""){
 
  97                 treeCookieId = "treeview";
 
 100                         settings = $.extend({
 
 101                                 cookieId: treeCookieId
 
 105                                 return this.trigger("add", [settings.add]);
 
 108                         if ( settings.toggle ) {
 
 109                                 var callback = settings.toggle;
 
 110                                 settings.toggle = function() {
 
 111                                         return callback.apply($(this).parent()[0], arguments);
 
 115                         // factory for treecontroller
 
 116                         function treeController(tree, control) {
 
 117                                 // factory for click handlers
 
 118                                 function handler(filter) {
 
 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;
 
 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() ); 
 
 137                         // handle toggle event
 
 141                                         // swap classes for hitarea
 
 143                                                 .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
 
 144                                                 .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
 
 146                                         // swap classes for parent li
 
 147                                         .swapClass( CLASSES.collapsable, CLASSES.expandable )
 
 148                                         .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
 
 152                                         .heightToggle( settings.animated, settings.toggle );
 
 153                                 if ( settings.unique ) {
 
 156                                                 // swap classes for hitarea
 
 158                                                         .replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
 
 159                                                         .replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
 
 161                                                 .replaceClass( CLASSES.collapsable, CLASSES.expandable )
 
 162                                                 .replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
 
 164                                                 .heightHide( settings.animated, settings.toggle );
 
 168                         function serialize() {
 
 169                                 function binary(arg) {
 
 173                                 branches.each(function(i, e) {
 
 174                                         data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
 
 176                                 $.cookie(settings.cookieId, data.join("") );
 
 179                         function deserialize() {
 
 180                                 var stored = $.cookie(settings.cookieId);
 
 182                                         var data = stored.split("");
 
 183                                         branches.each(function(i, e) {
 
 184                                                 $(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
 
 189                         // add treeview class to activate styles
 
 190                         this.addClass("treeview");
 
 192                         // prepare branches and find all tree items with child lists
 
 193                         var branches = this.find("li").prepareBranches(settings);
 
 195                         switch(settings.persist) {
 
 197                                 var toggleCallback = settings.toggle;
 
 198                                 settings.toggle = function() {
 
 200                                         if (toggleCallback) {
 
 201                                                 toggleCallback.apply(this, arguments);
 
 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();
 
 214                         branches.applyClasses(settings, toggler);
 
 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();
 
 222                         return this.bind("add", function(event, branches) {
 
 224                                         .removeClass(CLASSES.last)
 
 225                                         .removeClass(CLASSES.lastCollapsable)
 
 226                                         .removeClass(CLASSES.lastExpandable)
 
 228                                         .removeClass(CLASSES.lastCollapsableHitarea)
 
 229                                         .removeClass(CLASSES.lastExpandableHitarea);
 
 230                                 $(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, toggler);
 
 235         // classes used by the plugin
 
 236         // need to be styled via external stylesheet, see first example
 
 237         var CLASSES = $.fn.treeview.classes = {
 
 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",
 
 252         // provide backwards compability
 
 253         $.fn.Treeview = $.fn.treeview;