|
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