source: trunk/prototype/app/plugins/treeview/jquery.treeview.js @ 5136

Revision 5136, 8.1 KB checked in by wmerlotto, 12 years ago (diff)

Ticket #2305 - Enviando alteracoes, desenvolvidas internamente na Prognus, do modulo prototype.

Line 
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);
Note: See TracBrowser for help on using the repository browser.