1 /* A few useful utility functions. */
3 // Capture a method on an object.
4 function method(obj, name) {
5 return function() {obj[name].apply(obj, arguments);};
8 // The value used to signal the end of a sequence in iterators.
9 var StopIteration = {toString: function() {return "StopIteration"}};
11 // Apply a function to each element in a sequence.
12 function forEach(iter, f) {
14 try {while (true) f(iter.next());}
15 catch (e) {if (e != StopIteration) throw e;}
18 for (var i = 0; i < iter.length; i++)
23 // Map a function over a sequence, producing an array of results.
24 function map(iter, f) {
26 forEach(iter, function(val) {accum.push(f(val));});
30 // Create a predicate function that tests a string againsts a given
31 // regular expression. No longer used but might be used by 3rd party
33 function matcher(regexp){
34 return function(value){return regexp.test(value);};
37 // Test whether a DOM node has a certain CSS class. Much faster than
38 // the MochiKit equivalent, for some reason.
39 function hasClass(element, className){
40 var classes = element.className;
41 return classes && new RegExp("(^| )" + className + "($| )").test(classes);
44 // Insert a DOM node after another node.
45 function insertAfter(newNode, oldNode) {
46 var parent = oldNode.parentNode;
47 parent.insertBefore(newNode, oldNode.nextSibling);
51 function removeElement(node) {
53 node.parentNode.removeChild(node);
56 function clearElement(node) {
57 while (node.firstChild)
58 node.removeChild(node.firstChild);
61 // Check whether a node is contained in another one.
62 function isAncestor(node, child) {
63 while (child = child.parentNode) {
70 // The non-breaking space character.
72 var matching = {"{": "}", "[": "]", "(": ")",
73 "}": "{", "]": "[", ")": "("};
75 // Standardize a few unportable event properties.
76 function normalizeEvent(event) {
77 if (!event.stopPropagation) {
78 event.stopPropagation = function() {this.cancelBubble = true;};
79 event.preventDefault = function() {this.returnValue = false;};
82 event.stop = function() {
83 this.stopPropagation();
84 this.preventDefault();
88 if (event.type == "keypress") {
89 event.code = (event.charCode == null) ? event.keyCode : event.charCode;
90 event.character = String.fromCharCode(event.code);
95 // Portably register event handlers.
96 function addEventHandler(node, type, handler, removeFunc) {
97 function wrapHandler(event) {
98 handler(normalizeEvent(event || window.event));
100 if (typeof node.addEventListener == "function") {
101 node.addEventListener(type, wrapHandler, false);
102 if (removeFunc) return function() {node.removeEventListener(type, wrapHandler, false);};
105 node.attachEvent("on" + type, wrapHandler);
106 if (removeFunc) return function() {node.detachEvent("on" + type, wrapHandler);};
110 function nodeText(node) {
111 return node.textContent || node.innerText || node.nodeValue || "";
114 function nodeTop(node) {
116 while (node.offsetParent) {
117 top += node.offsetTop;
118 node = node.offsetParent;
123 function isBR(node) {
124 var nn = node.nodeName;
125 return nn == "BR" || nn == "br";
127 function isSpan(node) {
128 var nn = node.nodeName;
129 return nn == "SPAN" || nn == "span";