|
199 | 199 | {% endif %}
|
200 | 200 |
|
201 | 201 | <script>
|
202 |
| - function Toggler(togglerStorage) { |
| 202 | + function Toggler(storage) { |
203 | 203 | "use strict";
|
204 | 204 |
|
205 |
| - var expand = function (button) { |
| 205 | + var STORAGE_KEY = 'sf_toggle_data', |
| 206 | +
|
| 207 | + states = {}, |
| 208 | +
|
| 209 | + isCollapsed = function (button) { |
| 210 | + return Sfjs.hasClass(button, 'closed'); |
| 211 | + }, |
| 212 | +
|
| 213 | + isExpanded = function (button) { |
| 214 | + return !isCollapsed(button); |
| 215 | + }, |
| 216 | +
|
| 217 | + expand = function (button) { |
206 | 218 | var targetId = button.dataset.toggleTargetId,
|
207 | 219 | target = document.getElementById(targetId);
|
208 | 220 |
|
209 | 221 | if (!target) {
|
210 | 222 | throw "Toggle target " + targetId + " does not exist";
|
211 | 223 | }
|
212 | 224 |
|
213 |
| - togglerStorage.store(targetId, 'visible'); |
| 225 | + if (isCollapsed(button)) { |
| 226 | + Sfjs.removeClass(button, 'closed'); |
| 227 | + Sfjs.removeClass(target, 'hidden'); |
214 | 228 |
|
215 |
| - Sfjs.removeClass(button, 'closed'); |
216 |
| - Sfjs.removeClass(target, 'hidden'); |
| 229 | + states[targetId] = 1; |
| 230 | + storage.setItem(STORAGE_KEY, states); |
| 231 | + } |
217 | 232 | },
|
218 | 233 |
|
219 | 234 | collapse = function (button) {
|
|
224 | 239 | throw "Toggle target " + targetId + " does not exist";
|
225 | 240 | }
|
226 | 241 |
|
227 |
| - togglerStorage.store(targetId, 'hidden'); |
| 242 | + if (isExpanded(button)) { |
| 243 | + Sfjs.addClass(button, 'closed'); |
| 244 | + Sfjs.addClass(target, 'hidden'); |
228 | 245 |
|
229 |
| - Sfjs.addClass(button, 'closed'); |
230 |
| - Sfjs.addClass(target, 'hidden'); |
| 246 | + states[targetId] = 0; |
| 247 | + storage.setItem(STORAGE_KEY, states); |
| 248 | + } |
231 | 249 | },
|
232 | 250 |
|
233 | 251 | toggle = function (button) {
|
|
239 | 257 | },
|
240 | 258 |
|
241 | 259 | initButtons = function (buttons) {
|
| 260 | + states = storage.getItem(STORAGE_KEY, {}); |
| 261 | +
|
| 262 | + // must be an object, not an array or anything else |
| 263 | + // `typeof` returns "object" also for arrays, so the following |
| 264 | + // check must be done |
| 265 | + // see http://stackoverflow.com/questions/4775722/check-if-object-is-array |
| 266 | + if ('[object Object]' !== Object.prototype.toString.call(states)) { |
| 267 | + states = {}; |
| 268 | + } |
| 269 | +
|
242 | 270 | for (var i = 0, l = buttons.length; i < l; ++i) {
|
243 |
| - var toggleTargetId = buttons[i].dataset.toggleTargetId, |
244 |
| - toggleTarget = document.getElementById(toggleTargetId); |
| 271 | + var targetId = buttons[i].dataset.toggleTargetId, |
| 272 | + target = document.getElementById(targetId); |
245 | 273 |
|
246 |
| - if (!toggleTarget) { |
247 |
| - throw "Toggle target " + toggleTargetId + " does not exist"; |
| 274 | + if (!target) { |
| 275 | + throw "Toggle target " + targetId + " does not exist"; |
248 | 276 | }
|
249 | 277 |
|
250 | 278 | // correct the initial state of the button
|
251 |
| - if (Sfjs.hasClass(toggleTarget, 'hidden')) { |
| 279 | + if (Sfjs.hasClass(target, 'hidden')) { |
252 | 280 | Sfjs.addClass(buttons[i], 'closed');
|
253 | 281 | }
|
254 | 282 |
|
|
261 | 289 |
|
262 | 290 | return false;
|
263 | 291 | });
|
| 292 | +
|
| 293 | + if (states.hasOwnProperty(targetId)) { |
| 294 | + // open or collapse based on stored data |
| 295 | + if (0 === states[targetId]) { |
| 296 | + collapse(buttons[i]); |
| 297 | + } else { |
| 298 | + expand(buttons[i]); |
| 299 | + } |
| 300 | + } |
264 | 301 | }
|
265 | 302 | };
|
266 | 303 |
|
|
269 | 306 |
|
270 | 307 | toggle: toggle,
|
271 | 308 |
|
| 309 | + isExpanded: isExpanded, |
| 310 | +
|
| 311 | + isCollapsed: isCollapsed, |
| 312 | +
|
272 | 313 | expand: expand,
|
273 | 314 |
|
274 | 315 | collapse: collapse
|
275 | 316 | };
|
276 | 317 | }
|
277 | 318 |
|
278 |
| - function TogglerStorage(key) { |
279 |
| - var key = 'sf_' + (key || 'toggle_data'), |
280 |
| - store = function (id, state) { |
281 |
| - var toggleData = sessionStorage.getItem(key); |
282 |
| - if (!toggleData) { |
283 |
| - toggleData = []; |
284 |
| - } else { |
285 |
| - toggleData = toggleData.split('|'); |
286 |
| - } |
287 |
| -
|
288 |
| - if ('visible' == state) { |
289 |
| - toggleData.push(id); |
290 |
| - } else { |
291 |
| - var index = toggleData.indexOf(id); |
292 |
| - if (-1 < index) { |
293 |
| - toggleData.splice(index, 1); |
294 |
| - } |
295 |
| - } |
296 |
| -
|
297 |
| - sessionStorage.setItem(key, toggleData.join('|')); |
| 319 | + function JsonStorage(storage) { |
| 320 | + var setItem = function (key, data) { |
| 321 | + storage.setItem(key, JSON.stringify(data)); |
298 | 322 | },
|
299 | 323 |
|
300 |
| - initStorage = function (buttonsSelector) { |
301 |
| - var toggleData = sessionStorage.getItem(key); |
302 |
| -
|
303 |
| - if (!toggleData) { |
304 |
| - return; |
305 |
| - } |
306 |
| - toggleData = toggleData.split('|'); |
307 |
| -
|
308 |
| - var buttons = document.getElementsByClassName(buttonsSelector || 'toggle-button'); |
309 |
| - for (i in toggleData) { |
310 |
| - var element = document.getElementById(toggleData[i]); |
311 |
| - if (!element) { |
312 |
| - continue; |
313 |
| - } |
314 |
| -
|
315 |
| - if (Sfjs.hasClass(element, 'hidden')) { |
316 |
| - for (var i = -1; button = buttons[++i]; ) { |
317 |
| - if (button.dataset.toggleTargetId && button.dataset.toggleTargetId == element.getAttribute('id')) { |
318 |
| - break; |
319 |
| - } |
320 |
| - } |
| 324 | + getItem = function (key, defaultValue) { |
| 325 | + var data = storage.getItem(key); |
321 | 326 |
|
322 |
| - Sfjs.removeClass(element, 'hidden'); |
323 |
| - Sfjs.removeClass(button, 'closed'); |
| 327 | + if (null !== data) { |
| 328 | + try { |
| 329 | + return JSON.parse(data); |
| 330 | + } catch(e) { |
324 | 331 | }
|
325 | 332 | }
|
| 333 | +
|
| 334 | + return defaultValue; |
326 | 335 | };
|
327 | 336 |
|
328 | 337 | return {
|
329 |
| - store: store, |
| 338 | + setItem: setItem, |
330 | 339 |
|
331 |
| - initStorage: initStorage |
| 340 | + getItem: getItem |
332 | 341 | };
|
333 | 342 | }
|
334 | 343 |
|
|
396 | 405 | }
|
397 | 406 |
|
398 | 407 | var tabTarget = new TabView(),
|
399 |
| - storage = new TogglerStorage(), |
400 |
| - toggler = new Toggler(storage); |
| 408 | + toggler = new Toggler(new JsonStorage(sessionStorage)); |
401 | 409 |
|
402 | 410 | tabTarget.initTabs(document.querySelectorAll('.tree .tree-inner'));
|
403 | 411 | toggler.initButtons(document.querySelectorAll('a.toggle-button'));
|
404 |
| - storage.initStorage(); |
405 | 412 | </script>
|
406 | 413 | {% endblock %}
|
407 | 414 |
|
|
0 commit comments