diff options
Diffstat (limited to 'upstream/clipper-6.4.2/Documentation/Scripts/expandable.js')
-rw-r--r-- | upstream/clipper-6.4.2/Documentation/Scripts/expandable.js | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/upstream/clipper-6.4.2/Documentation/Scripts/expandable.js b/upstream/clipper-6.4.2/Documentation/Scripts/expandable.js new file mode 100644 index 0000000..548fb57 --- /dev/null +++ b/upstream/clipper-6.4.2/Documentation/Scripts/expandable.js @@ -0,0 +1,190 @@ +/* + * Expandable list implementation. + * by David Lindquist <first name><at><last name><dot><net> + * See: + * http://www.gazingus.org/html/DOM-Scripted_Lists_Revisited.html + * Modifies lists so that sublists can be hidden and shown by means of + * a switch. The switch is a node inserted into the DOM tree as the + * first child of the list item containing the sublist. + */ + +// The script will only be applied to lists containing this class name, +// e.g.: <ul class="foo expandable">...</ul>. +var CLASS_NAME = "expandable"; + +// This value is the assumed initial display style for a sublist when it cannot +// be determined by other means. See below. +var DEFAULT_DISPLAY = "none"; + +// The namespace to use when using this script in an XML context. +var XMLNS = "http://www.w3.org/1999/xhtml"; + +// The beginning of the title text for the switch when the sublist is collapsed. +var CLOSED_PREFIX = "Expand list: "; + +// The beginning of the title text for the switch when the sublist is expanded. +var OPENED_PREFIX = "Collapse list: "; + +/******************************************************************************/ + +// Returns a copy of a string with leading and trailing whitespace removed. +String.prototype.trim = function() { + return this.replace(/^\s+/, "").replace(/\s+$/, ""); +} + +// Walks the DOM tree starting at a given root element. Returns an +// array of nodes of the specified type and conforming to the criteria +// of the given filter function. The filter should return a boolean. +function getNodesByType(root, type, filter) { + var node = root; + var nodes = []; + var next; + + while (node != null) { + if (node.hasChildNodes()) + node = node.firstChild; + else if (node != root && null != (next = node.nextSibling)) + node = next; + else { + next = null; + for ( ; node != root; node = node.parentNode) { + next = node.nextSibling; + if (next != null) break; + } + node = next; + } + if (node != null && node.nodeType == type && filter(node)) + nodes.push(node); + } + return nodes; +} + +// Simulates the innerText property of IE and other browsers. +// Mozilla/Firefox need this. +function getInnerText(node) { + if (node == null || node.nodeType != 1) + return; + var text = ""; + var textnodes = getNodesByType(node, 3, function() { return true; }); + for (var i = 0; i < textnodes.length; i++) + text += textnodes[i].data; + return text; +} + +function initExpandableLists() { + if (!document.getElementsByTagName) return; + + // Top-level function to accommodate browsers that do not register + // a click event when a link is activated by the keyboard. + switchNode = function(id) { + var node = document.getElementById(id); + if (node && /^switch /.test(node.className)) node.onclick(); + } + + // Top-level function to be assigned as the event handler for the + // switch. This could have been bound to the handler as a closure, + // but closures are associated with memory leak problems in IE. + actuate = function() { + var sublist = this.parentNode.getElementsByTagName("ul")[0] || + this.parentNode.getElementsByTagName("ol")[0]; + if (sublist.style.display == "block") { + sublist.style.display = "none"; + this.firstChild.data = "+"; + this.className = "switch off"; + this.title = this.title.replace(OPENED_PREFIX, CLOSED_PREFIX); + } else { + sublist.style.display = "block"; + this.firstChild.data = "-"; + this.className = "switch on"; + this.title = this.title.replace(CLOSED_PREFIX, OPENED_PREFIX); + } + return false; + } + + // Create switch node from which the others will be cloned. + if (typeof document.createElementNS == "function") + var template = document.createElementNS(XMLNS, "a"); + else + var template = document.createElement("a"); + template.appendChild(document.createTextNode(" ")); + + var list, i = 0, j = 0; + var pattern = new RegExp("(^| )" + CLASS_NAME + "( |$)"); + + while ((list = document.getElementsByTagName("ul")[i++]) || + (list = document.getElementsByTagName("ol")[j++])) + { + // Only lists with the given class name are processed. + if (pattern.test(list.className) == false) continue; + + var item, k = 0; + while ((item = list.getElementsByTagName("li")[k++])) { + var sublist = item.getElementsByTagName("ul")[0] || + item.getElementsByTagName("ol")[0]; + // No sublist under this list item. Skip it. + if (sublist == null) continue; + + // Attempt to determine initial display style of the + // sublist so the proper symbol is used. + var symbol; + switch (sublist.style.display) { + case "none" : symbol = "+"; break; + case "block": symbol = "-"; break; + default: + var display = DEFAULT_DISPLAY; + if (sublist.currentStyle) { + display = sublist.currentStyle.display; + } else if (document.defaultView && + document.defaultView.getComputedStyle && + document.defaultView.getComputedStyle(sublist, "")) + { + var view = document.defaultView; + var computed = view.getComputedStyle(sublist, ""); + display = computed.getPropertyValue("display"); + } + symbol = (display == "none") ? "+" : "-"; + // Explicitly set the display style to make sure it is + // set for the next read. If it is somehow the empty + // string, use the default value from the (X)HTML DTD. + sublist.style.display = display || "block"; + break; + } + + // This bit attempts to extract some text from the first + // child node of the list item to append to the title + // attribute of the switch. + var child = item.firstChild; + var text = ""; + while (child) { + if (child.nodeType == 3 && "" != child.data.trim()) { + text = child.data; + break; + } else if (child.nodeType == 1 && + !/^[ou]l$/i.test(child.tagName)) + { + text = child.innerText || getInnerText(child); + break; + } + child = child.nextSibling; + } + + var actuator = template.cloneNode(true); + // a reasonably unique ID + var uid = "switch" + i + "-" + j + "-" + k; + actuator.id = uid; + actuator.href = "javascript:switchNode('" + uid + "')"; + actuator.className = "switch " + ((symbol == "+") ? "off" : "on"); + actuator.title = ((symbol == "+") + ? CLOSED_PREFIX : OPENED_PREFIX) + text.trim(); + actuator.firstChild.data = symbol; + actuator.onclick = actuate; + item.insertBefore(actuator, item.firstChild); + } + } +} + +// Props to Simon Willison: +// http://simon.incutio.com/archive/2004/05/26/addLoadEvent +var oldhandler = window.onload; +window.onload = (typeof oldhandler == "function") + ? function() { oldhandler(); initExpandableLists(); } : initExpandableLists; |