Mercurial > hg > rr-repo
comparison sites/all/modules/token/jquery.treeTable.js @ 0:ff03f76ab3fe
initial version
author | danieleb <danielebarchiesi@me.com> |
---|---|
date | Wed, 21 Aug 2013 18:51:11 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:ff03f76ab3fe |
---|---|
1 | |
2 /* | |
3 * jQuery treeTable Plugin 2.3.0 | |
4 * http://ludo.cubicphuse.nl/jquery-plugins/treeTable/ | |
5 * | |
6 * Copyright 2010, Ludo van den Boom | |
7 * Dual licensed under the MIT or GPL Version 2 licenses. | |
8 */ | |
9 (function($) { | |
10 // Helps to make options available to all functions | |
11 // TODO: This gives problems when there are both expandable and non-expandable | |
12 // trees on a page. The options shouldn't be global to all these instances! | |
13 var options; | |
14 var defaultPaddingLeft; | |
15 | |
16 $.fn.treeTable = function(opts) { | |
17 options = $.extend({}, $.fn.treeTable.defaults, opts); | |
18 | |
19 return this.each(function() { | |
20 $(this).addClass("treeTable").find("tbody tr").each(function() { | |
21 // Initialize root nodes only if possible | |
22 if(!options.expandable || $(this)[0].className.search(options.childPrefix) == -1) { | |
23 // To optimize performance of indentation, I retrieve the padding-left | |
24 // value of the first root node. This way I only have to call +css+ | |
25 // once. | |
26 if (isNaN(defaultPaddingLeft)) { | |
27 defaultPaddingLeft = parseInt($($(this).children("td")[options.treeColumn]).css('padding-left'), 10); | |
28 } | |
29 | |
30 initialize($(this)); | |
31 } else if(options.initialState == "collapsed") { | |
32 this.style.display = "none"; // Performance! $(this).hide() is slow... | |
33 } | |
34 }); | |
35 }); | |
36 }; | |
37 | |
38 $.fn.treeTable.defaults = { | |
39 childPrefix: "child-of-", | |
40 clickableNodeNames: false, | |
41 expandable: true, | |
42 indent: 19, | |
43 initialState: "collapsed", | |
44 treeColumn: 0 | |
45 }; | |
46 | |
47 // Recursively hide all node's children in a tree | |
48 $.fn.collapse = function() { | |
49 $(this).addClass("collapsed"); | |
50 | |
51 childrenOf($(this)).each(function() { | |
52 if(!$(this).hasClass("collapsed")) { | |
53 $(this).collapse(); | |
54 } | |
55 | |
56 this.style.display = "none"; // Performance! $(this).hide() is slow... | |
57 }); | |
58 | |
59 return this; | |
60 }; | |
61 | |
62 // Recursively show all node's children in a tree | |
63 $.fn.expand = function() { | |
64 $(this).removeClass("collapsed").addClass("expanded"); | |
65 | |
66 childrenOf($(this)).each(function() { | |
67 initialize($(this)); | |
68 | |
69 if($(this).is(".expanded.parent")) { | |
70 $(this).expand(); | |
71 } | |
72 | |
73 // this.style.display = "table-row"; // Unfortunately this is not possible with IE :-( | |
74 $(this).show(); | |
75 }); | |
76 | |
77 return this; | |
78 }; | |
79 | |
80 // Reveal a node by expanding all ancestors | |
81 $.fn.reveal = function() { | |
82 $(ancestorsOf($(this)).reverse()).each(function() { | |
83 initialize($(this)); | |
84 $(this).expand().show(); | |
85 }); | |
86 | |
87 return this; | |
88 }; | |
89 | |
90 // Add an entire branch to +destination+ | |
91 $.fn.appendBranchTo = function(destination) { | |
92 var node = $(this); | |
93 var parent = parentOf(node); | |
94 | |
95 var ancestorNames = $.map(ancestorsOf($(destination)), function(a) { return a.id; }); | |
96 | |
97 // Conditions: | |
98 // 1: +node+ should not be inserted in a location in a branch if this would | |
99 // result in +node+ being an ancestor of itself. | |
100 // 2: +node+ should not have a parent OR the destination should not be the | |
101 // same as +node+'s current parent (this last condition prevents +node+ | |
102 // from being moved to the same location where it already is). | |
103 // 3: +node+ should not be inserted as a child of +node+ itself. | |
104 if($.inArray(node[0].id, ancestorNames) == -1 && (!parent || (destination.id != parent[0].id)) && destination.id != node[0].id) { | |
105 indent(node, ancestorsOf(node).length * options.indent * -1); // Remove indentation | |
106 | |
107 if(parent) { node.removeClass(options.childPrefix + parent[0].id); } | |
108 | |
109 node.addClass(options.childPrefix + destination.id); | |
110 move(node, destination); // Recursively move nodes to new location | |
111 indent(node, ancestorsOf(node).length * options.indent); | |
112 } | |
113 | |
114 return this; | |
115 }; | |
116 | |
117 // Add reverse() function from JS Arrays | |
118 $.fn.reverse = function() { | |
119 return this.pushStack(this.get().reverse(), arguments); | |
120 }; | |
121 | |
122 // Toggle an entire branch | |
123 $.fn.toggleBranch = function() { | |
124 if($(this).hasClass("collapsed")) { | |
125 $(this).expand(); | |
126 } else { | |
127 $(this).removeClass("expanded").collapse(); | |
128 } | |
129 | |
130 return this; | |
131 }; | |
132 | |
133 // === Private functions | |
134 | |
135 function ancestorsOf(node) { | |
136 var ancestors = []; | |
137 while(node = parentOf(node)) { | |
138 ancestors[ancestors.length] = node[0]; | |
139 } | |
140 return ancestors; | |
141 }; | |
142 | |
143 function childrenOf(node) { | |
144 return $(node).siblings("tr." + options.childPrefix + node[0].id); | |
145 }; | |
146 | |
147 function getPaddingLeft(node) { | |
148 var paddingLeft = parseInt(node[0].style.paddingLeft, 10); | |
149 return (isNaN(paddingLeft)) ? defaultPaddingLeft : paddingLeft; | |
150 } | |
151 | |
152 function indent(node, value) { | |
153 var cell = $(node.children("td")[options.treeColumn]); | |
154 cell[0].style.paddingLeft = getPaddingLeft(cell) + value + "px"; | |
155 | |
156 childrenOf(node).each(function() { | |
157 indent($(this), value); | |
158 }); | |
159 }; | |
160 | |
161 function initialize(node) { | |
162 if(!node.hasClass("initialized")) { | |
163 node.addClass("initialized"); | |
164 | |
165 var childNodes = childrenOf(node); | |
166 | |
167 if(!node.hasClass("parent") && childNodes.length > 0) { | |
168 node.addClass("parent"); | |
169 } | |
170 | |
171 if(node.hasClass("parent")) { | |
172 var cell = $(node.children("td")[options.treeColumn]); | |
173 var padding = getPaddingLeft(cell) + options.indent; | |
174 | |
175 childNodes.each(function() { | |
176 $(this).children("td")[options.treeColumn].style.paddingLeft = padding + "px"; | |
177 }); | |
178 | |
179 if(options.expandable) { | |
180 cell.prepend('<span style="margin-left: -' + options.indent + 'px; padding-left: ' + options.indent + 'px" class="expander"></span>'); | |
181 $(cell[0].firstChild).click(function() { node.toggleBranch(); }); | |
182 | |
183 if(options.clickableNodeNames) { | |
184 cell[0].style.cursor = "pointer"; | |
185 $(cell).click(function(e) { | |
186 // Don't double-toggle if the click is on the existing expander icon | |
187 if (e.target.className != 'expander') { | |
188 node.toggleBranch(); | |
189 } | |
190 }); | |
191 } | |
192 | |
193 // Check for a class set explicitly by the user, otherwise set the default class | |
194 if(!(node.hasClass("expanded") || node.hasClass("collapsed"))) { | |
195 node.addClass(options.initialState); | |
196 } | |
197 | |
198 if(node.hasClass("expanded")) { | |
199 node.expand(); | |
200 } | |
201 } | |
202 } | |
203 } | |
204 }; | |
205 | |
206 function move(node, destination) { | |
207 node.insertAfter(destination); | |
208 childrenOf(node).reverse().each(function() { move($(this), node[0]); }); | |
209 }; | |
210 | |
211 function parentOf(node) { | |
212 var classNames = node[0].className.split(' '); | |
213 | |
214 for(key in classNames) { | |
215 if(classNames[key].match(options.childPrefix)) { | |
216 return $(node).siblings("#" + classNames[key].substring(options.childPrefix.length)); | |
217 } | |
218 } | |
219 }; | |
220 })(jQuery); |