danielebarchiesi@0
|
1 /**
|
danielebarchiesi@0
|
2 * @file
|
danielebarchiesi@0
|
3 * Javascript required for a simple collapsible div.
|
danielebarchiesi@0
|
4 *
|
danielebarchiesi@0
|
5 * Creating a collapsible div with this doesn't take too much. There are
|
danielebarchiesi@0
|
6 * three classes necessary:
|
danielebarchiesi@0
|
7 *
|
danielebarchiesi@0
|
8 * - ctools-collapsible-container: This is the overall container that will be
|
danielebarchiesi@0
|
9 * collapsible. This must be a div.
|
danielebarchiesi@0
|
10 * - ctools-collapsible-handle: This is the title area, and is what will be
|
danielebarchiesi@0
|
11 * visible when it is collapsed. This can be any block element, such as div
|
danielebarchiesi@0
|
12 * or h2.
|
danielebarchiesi@0
|
13 * - ctools-collapsible-content: This is the ocntent area and will only be
|
danielebarchiesi@0
|
14 * visible when expanded. This must be a div.
|
danielebarchiesi@0
|
15 *
|
danielebarchiesi@0
|
16 * Adding 'ctools-collapsible-remember' to the container class will cause the
|
danielebarchiesi@0
|
17 * state of the container to be stored in a cookie, and remembered from page
|
danielebarchiesi@0
|
18 * load to page load. This will only work if the container has a unique ID, so
|
danielebarchiesi@0
|
19 * very carefully add IDs to your containers.
|
danielebarchiesi@0
|
20 *
|
danielebarchiesi@0
|
21 * If the class 'ctools-no-container' is placed on the container, the container
|
danielebarchiesi@0
|
22 * will be the handle. The content will be found by appending '-content' to the
|
danielebarchiesi@0
|
23 * id of the handle. The ctools-collapsible-handle and
|
danielebarchiesi@0
|
24 * ctools-collapsible-content classes will not be required in that case, and no
|
danielebarchiesi@0
|
25 * restrictions on what of data the container is are placed. Like
|
danielebarchiesi@0
|
26 * ctools-collapsible-remember this requires an id to eist.
|
danielebarchiesi@0
|
27 *
|
danielebarchiesi@0
|
28 * The content will be 'open' unless the container class has 'ctools-collapsed'
|
danielebarchiesi@0
|
29 * as a class, which will cause the container to draw collapsed.
|
danielebarchiesi@0
|
30 */
|
danielebarchiesi@0
|
31
|
danielebarchiesi@0
|
32 (function ($) {
|
danielebarchiesi@0
|
33 // All CTools tools begin with this if they need to use the CTools namespace.
|
danielebarchiesi@0
|
34 if (!Drupal.CTools) {
|
danielebarchiesi@0
|
35 Drupal.CTools = {};
|
danielebarchiesi@0
|
36 }
|
danielebarchiesi@0
|
37
|
danielebarchiesi@0
|
38 /**
|
danielebarchiesi@0
|
39 * Object to store state.
|
danielebarchiesi@0
|
40 *
|
danielebarchiesi@0
|
41 * This object will remember the state of collapsible containers. The first
|
danielebarchiesi@0
|
42 * time a state is requested, it will check the cookie and set up the variable.
|
danielebarchiesi@0
|
43 * If a state has been changed, when the window is unloaded the state will be
|
danielebarchiesi@0
|
44 * saved.
|
danielebarchiesi@0
|
45 */
|
danielebarchiesi@0
|
46 Drupal.CTools.Collapsible = {
|
danielebarchiesi@0
|
47 state: {},
|
danielebarchiesi@0
|
48 stateLoaded: false,
|
danielebarchiesi@0
|
49 stateChanged: false,
|
danielebarchiesi@0
|
50 cookieString: 'ctools-collapsible-state=',
|
danielebarchiesi@0
|
51
|
danielebarchiesi@0
|
52 /**
|
danielebarchiesi@0
|
53 * Get the current collapsed state of a container.
|
danielebarchiesi@0
|
54 *
|
danielebarchiesi@0
|
55 * If set to 1, the container is open. If set to -1, the container is
|
danielebarchiesi@0
|
56 * collapsed. If unset the state is unknown, and the default state should
|
danielebarchiesi@0
|
57 * be used.
|
danielebarchiesi@0
|
58 */
|
danielebarchiesi@0
|
59 getState: function (id) {
|
danielebarchiesi@0
|
60 if (!this.stateLoaded) {
|
danielebarchiesi@0
|
61 this.loadCookie();
|
danielebarchiesi@0
|
62 }
|
danielebarchiesi@0
|
63
|
danielebarchiesi@0
|
64 return this.state[id];
|
danielebarchiesi@0
|
65 },
|
danielebarchiesi@0
|
66
|
danielebarchiesi@0
|
67 /**
|
danielebarchiesi@0
|
68 * Set the collapsed state of a container for subsequent page loads.
|
danielebarchiesi@0
|
69 *
|
danielebarchiesi@0
|
70 * Set the state to 1 for open, -1 for collapsed.
|
danielebarchiesi@0
|
71 */
|
danielebarchiesi@0
|
72 setState: function (id, state) {
|
danielebarchiesi@0
|
73 if (!this.stateLoaded) {
|
danielebarchiesi@0
|
74 this.loadCookie();
|
danielebarchiesi@0
|
75 }
|
danielebarchiesi@0
|
76
|
danielebarchiesi@0
|
77 this.state[id] = state;
|
danielebarchiesi@0
|
78
|
danielebarchiesi@0
|
79 if (!this.stateChanged) {
|
danielebarchiesi@0
|
80 this.stateChanged = true;
|
danielebarchiesi@0
|
81 $(window).unload(this.unload);
|
danielebarchiesi@0
|
82 }
|
danielebarchiesi@0
|
83 },
|
danielebarchiesi@0
|
84
|
danielebarchiesi@0
|
85 /**
|
danielebarchiesi@0
|
86 * Check the cookie and load the state variable.
|
danielebarchiesi@0
|
87 */
|
danielebarchiesi@0
|
88 loadCookie: function () {
|
danielebarchiesi@0
|
89 // If there is a previous instance of this cookie
|
danielebarchiesi@0
|
90 if (document.cookie.length > 0) {
|
danielebarchiesi@0
|
91 // Get the number of characters that have the list of values
|
danielebarchiesi@0
|
92 // from our string index.
|
danielebarchiesi@0
|
93 offset = document.cookie.indexOf(this.cookieString);
|
danielebarchiesi@0
|
94
|
danielebarchiesi@0
|
95 // If its positive, there is a list!
|
danielebarchiesi@0
|
96 if (offset != -1) {
|
danielebarchiesi@0
|
97 offset += this.cookieString.length;
|
danielebarchiesi@0
|
98 var end = document.cookie.indexOf(';', offset);
|
danielebarchiesi@0
|
99 if (end == -1) {
|
danielebarchiesi@0
|
100 end = document.cookie.length;
|
danielebarchiesi@0
|
101 }
|
danielebarchiesi@0
|
102
|
danielebarchiesi@0
|
103 // Get a list of all values that are saved on our string
|
danielebarchiesi@0
|
104 var cookie = unescape(document.cookie.substring(offset, end));
|
danielebarchiesi@0
|
105
|
danielebarchiesi@0
|
106 if (cookie != '') {
|
danielebarchiesi@0
|
107 var cookieList = cookie.split(',');
|
danielebarchiesi@0
|
108 for (var i = 0; i < cookieList.length; i++) {
|
danielebarchiesi@0
|
109 var info = cookieList[i].split(':');
|
danielebarchiesi@0
|
110 this.state[info[0]] = info[1];
|
danielebarchiesi@0
|
111 }
|
danielebarchiesi@0
|
112 }
|
danielebarchiesi@0
|
113 }
|
danielebarchiesi@0
|
114 }
|
danielebarchiesi@0
|
115
|
danielebarchiesi@0
|
116 this.stateLoaded = true;
|
danielebarchiesi@0
|
117 },
|
danielebarchiesi@0
|
118
|
danielebarchiesi@0
|
119 /**
|
danielebarchiesi@0
|
120 * Turn the state variable into a string and store it in the cookie.
|
danielebarchiesi@0
|
121 */
|
danielebarchiesi@0
|
122 storeCookie: function () {
|
danielebarchiesi@0
|
123 var cookie = '';
|
danielebarchiesi@0
|
124
|
danielebarchiesi@0
|
125 // Get a list of IDs, saparated by comma
|
danielebarchiesi@0
|
126 for (i in this.state) {
|
danielebarchiesi@0
|
127 if (cookie != '') {
|
danielebarchiesi@0
|
128 cookie += ',';
|
danielebarchiesi@0
|
129 }
|
danielebarchiesi@0
|
130 cookie += i + ':' + this.state[i];
|
danielebarchiesi@0
|
131 }
|
danielebarchiesi@0
|
132
|
danielebarchiesi@0
|
133 // Save this values on the cookie
|
danielebarchiesi@0
|
134 document.cookie = this.cookieString + escape(cookie) + ';path=/';
|
danielebarchiesi@0
|
135 },
|
danielebarchiesi@0
|
136
|
danielebarchiesi@0
|
137 /**
|
danielebarchiesi@0
|
138 * Respond to the unload event by storing the current state.
|
danielebarchiesi@0
|
139 */
|
danielebarchiesi@0
|
140 unload: function() {
|
danielebarchiesi@0
|
141 Drupal.CTools.Collapsible.storeCookie();
|
danielebarchiesi@0
|
142 }
|
danielebarchiesi@0
|
143 };
|
danielebarchiesi@0
|
144
|
danielebarchiesi@0
|
145 // Set up an array for callbacks.
|
danielebarchiesi@0
|
146 Drupal.CTools.CollapsibleCallbacks = [];
|
danielebarchiesi@0
|
147 Drupal.CTools.CollapsibleCallbacksAfterToggle = [];
|
danielebarchiesi@0
|
148
|
danielebarchiesi@0
|
149 /**
|
danielebarchiesi@0
|
150 * Bind collapsible behavior to a given container.
|
danielebarchiesi@0
|
151 */
|
danielebarchiesi@0
|
152 Drupal.CTools.bindCollapsible = function () {
|
danielebarchiesi@0
|
153 var $container = $(this);
|
danielebarchiesi@0
|
154
|
danielebarchiesi@0
|
155 // Allow the specification of the 'no container' class, which means the
|
danielebarchiesi@0
|
156 // handle and the container can be completely independent.
|
danielebarchiesi@0
|
157 if ($container.hasClass('ctools-no-container') && $container.attr('id')) {
|
danielebarchiesi@0
|
158 // In this case, the container *is* the handle and the content is found
|
danielebarchiesi@0
|
159 // by adding '-content' to the id. Obviously, an id is required.
|
danielebarchiesi@0
|
160 var handle = $container;
|
danielebarchiesi@0
|
161 var content = $('#' + $container.attr('id') + '-content');
|
danielebarchiesi@0
|
162 }
|
danielebarchiesi@0
|
163 else {
|
danielebarchiesi@0
|
164 var handle = $container.children('.ctools-collapsible-handle');
|
danielebarchiesi@0
|
165 var content = $container.children('div.ctools-collapsible-content');
|
danielebarchiesi@0
|
166 }
|
danielebarchiesi@0
|
167
|
danielebarchiesi@0
|
168 if (content.length) {
|
danielebarchiesi@0
|
169 // Create the toggle item and place it in front of the toggle.
|
danielebarchiesi@0
|
170 var toggle = $('<span class="ctools-toggle"></span>');
|
danielebarchiesi@0
|
171 handle.before(toggle);
|
danielebarchiesi@0
|
172
|
danielebarchiesi@0
|
173 // If the remember class is set, check to see if we have a remembered
|
danielebarchiesi@0
|
174 // state stored.
|
danielebarchiesi@0
|
175 if ($container.hasClass('ctools-collapsible-remember') && $container.attr('id')) {
|
danielebarchiesi@0
|
176 var state = Drupal.CTools.Collapsible.getState($container.attr('id'));
|
danielebarchiesi@0
|
177 if (state == 1) {
|
danielebarchiesi@0
|
178 $container.removeClass('ctools-collapsed');
|
danielebarchiesi@0
|
179 }
|
danielebarchiesi@0
|
180 else if (state == -1) {
|
danielebarchiesi@0
|
181 $container.addClass('ctools-collapsed');
|
danielebarchiesi@0
|
182 }
|
danielebarchiesi@0
|
183 }
|
danielebarchiesi@0
|
184
|
danielebarchiesi@0
|
185 // If we should start collapsed, do so:
|
danielebarchiesi@0
|
186 if ($container.hasClass('ctools-collapsed')) {
|
danielebarchiesi@0
|
187 toggle.toggleClass('ctools-toggle-collapsed');
|
danielebarchiesi@0
|
188 content.hide();
|
danielebarchiesi@0
|
189 }
|
danielebarchiesi@0
|
190
|
danielebarchiesi@0
|
191 var afterToggle = function () {
|
danielebarchiesi@0
|
192 if (Drupal.CTools.CollapsibleCallbacksAfterToggle) {
|
danielebarchiesi@0
|
193 for (i in Drupal.CTools.CollapsibleCallbacksAfterToggle) {
|
danielebarchiesi@0
|
194 Drupal.CTools.CollapsibleCallbacksAfterToggle[i]($container, handle, content, toggle);
|
danielebarchiesi@0
|
195 }
|
danielebarchiesi@0
|
196 }
|
danielebarchiesi@0
|
197 }
|
danielebarchiesi@0
|
198
|
danielebarchiesi@0
|
199 var clickMe = function () {
|
danielebarchiesi@0
|
200 if (Drupal.CTools.CollapsibleCallbacks) {
|
danielebarchiesi@0
|
201 for (i in Drupal.CTools.CollapsibleCallbacks) {
|
danielebarchiesi@0
|
202 Drupal.CTools.CollapsibleCallbacks[i]($container, handle, content, toggle);
|
danielebarchiesi@0
|
203 }
|
danielebarchiesi@0
|
204 }
|
danielebarchiesi@0
|
205
|
danielebarchiesi@0
|
206 // If the container is a table element slideToggle does not do what
|
danielebarchiesi@0
|
207 // we want, so use toggle() instead.
|
danielebarchiesi@0
|
208 if ($container.is('table')) {
|
danielebarchiesi@0
|
209 content.toggle(0, afterToggle);
|
danielebarchiesi@0
|
210 }
|
danielebarchiesi@0
|
211 else {
|
danielebarchiesi@0
|
212 content.slideToggle(100, afterToggle);
|
danielebarchiesi@0
|
213 }
|
danielebarchiesi@0
|
214
|
danielebarchiesi@0
|
215 toggle.toggleClass('ctools-toggle-collapsed');
|
danielebarchiesi@0
|
216
|
danielebarchiesi@0
|
217 // If we're supposed to remember the state of this class, do so.
|
danielebarchiesi@0
|
218 if ($container.hasClass('ctools-collapsible-remember') && $container.attr('id')) {
|
danielebarchiesi@0
|
219 var state = toggle.hasClass('ctools-toggle-collapsed') ? -1 : 1;
|
danielebarchiesi@0
|
220 Drupal.CTools.Collapsible.setState($container.attr('id'), state);
|
danielebarchiesi@0
|
221 }
|
danielebarchiesi@0
|
222
|
danielebarchiesi@0
|
223 return false;
|
danielebarchiesi@0
|
224 }
|
danielebarchiesi@0
|
225
|
danielebarchiesi@0
|
226 // Let both the toggle and the handle be clickable.
|
danielebarchiesi@0
|
227 toggle.click(clickMe);
|
danielebarchiesi@0
|
228 handle.click(clickMe);
|
danielebarchiesi@0
|
229 }
|
danielebarchiesi@0
|
230 };
|
danielebarchiesi@0
|
231
|
danielebarchiesi@0
|
232 /**
|
danielebarchiesi@0
|
233 * Support Drupal's 'behaviors' system for binding.
|
danielebarchiesi@0
|
234 */
|
danielebarchiesi@0
|
235 Drupal.behaviors.CToolsCollapsible = {
|
danielebarchiesi@0
|
236 attach: function(context) {
|
danielebarchiesi@0
|
237 $('.ctools-collapsible-container', context).once('ctools-collapsible', Drupal.CTools.bindCollapsible);
|
danielebarchiesi@0
|
238 }
|
danielebarchiesi@0
|
239 }
|
danielebarchiesi@0
|
240 })(jQuery);
|