// turn this into a nice module-like namespace to avoid messing up the global // (window) namespace this.kuputoolcollapser = new function() { var ToolCollapser = function(toolboxesparentid) { this.parent = document.getElementById(toolboxesparentid); }; // make the collapser available in the namespace this.Collapser = ToolCollapser; ToolCollapser.prototype.initialize = function() { var initial_state = {}; if (navigator.cookieEnabled) { var cookie = document.cookie; var reg = /initial_state=([^;]+);?/; var match = cookie.match(reg); if (match) { eval(unescape(match[0])); }; }; for (var i=0; i < this.parent.childNodes.length; i++) { var child = this.parent.childNodes[i]; if (child.className == 'kupu-toolbox') { var heading = child.getElementsByTagName('h1')[0]; if (!heading) { throw('heading not found by collapser for toolbox ' + child.id); }; heading.setAttribute('title', _('click to unfold')); // find the toolbox's body var body = this.getToolBody(child); // now set a handler that makes the body display and hide // on click, and register it to the heading // WAAAAAHHHH!!! since there's some weird shit happening when // I just use closures to refer to the body (somehow only the // *last* value body is set to in this loop is used?!?) I // used a reference to the body as 'this' in the handler var handler = function(heading) { if (this.style.display == 'none') { // assume we have a block-level element here... this.style.display = 'block'; heading.className = 'kupu-toolbox-heading-opened'; heading.setAttribute('title', _('click to fold')); } else { this.style.display = 'none'; heading.className = 'kupu-toolbox-heading-closed'; heading.setAttribute('title', _('click to unfold')); }; }; var wrap_openhandler = function(body, heading) { return function() { body.style.display = 'block'; heading.className = 'kupu-toolbox-heading-opened'; }; }; addEventHandler(heading, 'click', handler, body, heading); if (initial_state[child.id] === undefined || initial_state[child.id] == '0') { body.style.display = 'none'; }; // add a reference to the openhandler on the toolbox div // so any toolbox code can use that to open the toolbox if // it so desires child.open_handler = wrap_openhandler(body, heading); }; }; addEventHandler(window, 'beforeunload', this.saveState, this); }; ToolCollapser.prototype.getToolBody = function(tool) { var heading = tool.getElementsByTagName('h1')[0]; var currchild = heading.nextSibling; while (currchild.nodeType != 1) { currchild = currchild.nextSibling; if (!currchild) { throw('body not found by collapser for toolbox ' + child.id); }; }; return currchild; }; ToolCollapser.prototype.saveState = function() { /* save collapse state of the toolboxes in a cookie */ if (!navigator.cookieEnabled) { return; }; var current_state = {}; for (var i=0; i < this.parent.childNodes.length; i++) { var child = this.parent.childNodes[i]; if (child.nodeType != 1) { continue; }; var body = this.getToolBody(child); current_state[child.id] = body.style.display == 'none' ? '0' : '1'; }; var exp = new Date(); // 100 years before state is lost... should be enough ;) exp.setTime(exp.getTime() + (100 * 365 * 24 * 60 * 60 * 1000)); var cookie = 'initial_state=' + escape(this.serializeMapping(current_state)) + ';' + 'expires=' + exp.toGMTString() + ';' + 'path=/'; document.cookie = cookie; }; ToolCollapser.prototype.serializeMapping = function(mapping) { /* serializes the config dict into a string that can be evalled works only for dicts with string values */ if (typeof(mapping) == 'string') { return "'" + mapping + "'"; }; var ret = '{'; var first = true; for (var key in mapping) { if (!first) { ret += ', '; }; ret += "'" + key + "': " + this.serializeMapping(mapping[key]); first = false; }; return ret + '}'; }; }();