Don't loose attributes of unknown tags
[redakcja.git] / redakcja / static / js / lib / codemirror-0.8 / util.js
1 /* A few useful utility functions. */
2
3 // Capture a method on an object.
4 function method(obj, name) {
5   return function() {obj[name].apply(obj, arguments);};
6 }
7
8 // The value used to signal the end of a sequence in iterators.
9 var StopIteration = {toString: function() {return "StopIteration"}};
10
11 // Apply a function to each element in a sequence.
12 function forEach(iter, f) {
13   if (iter.next) {
14     try {while (true) f(iter.next());}
15     catch (e) {if (e != StopIteration) throw e;}
16   }
17   else {
18     for (var i = 0; i < iter.length; i++)
19       f(iter[i]);
20   }
21 }
22
23 // Map a function over a sequence, producing an array of results.
24 function map(iter, f) {
25   var accum = [];
26   forEach(iter, function(val) {accum.push(f(val));});
27   return accum;
28 }
29
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
32 // parsers.
33 function matcher(regexp){
34   return function(value){return regexp.test(value);};
35 }
36
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);
42 }
43
44 // Insert a DOM node after another node.
45 function insertAfter(newNode, oldNode) {
46   var parent = oldNode.parentNode;
47   parent.insertBefore(newNode, oldNode.nextSibling);
48   return newNode;
49 }
50
51 function removeElement(node) {
52   if (node.parentNode)
53     node.parentNode.removeChild(node);
54 }
55
56 function clearElement(node) {
57   while (node.firstChild)
58     node.removeChild(node.firstChild);
59 }
60
61 // Check whether a node is contained in another one.
62 function isAncestor(node, child) {
63   while (child = child.parentNode) {
64     if (node == child)
65       return true;
66   }
67   return false;
68 }
69
70 // The non-breaking space character.
71 var nbsp = "\u00a0";
72 var matching = {"{": "}", "[": "]", "(": ")",
73                 "}": "{", "]": "[", ")": "("};
74
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;};
80   }
81   if (!event.stop) {
82     event.stop = function() {
83       this.stopPropagation();
84       this.preventDefault();
85     };
86   }
87
88   if (event.type == "keypress") {
89     event.code = (event.charCode == null) ? event.keyCode : event.charCode;
90     event.character = String.fromCharCode(event.code);
91   }
92   return event;
93 }
94
95 // Portably register event handlers.
96 function addEventHandler(node, type, handler, removeFunc) {
97   function wrapHandler(event) {
98     handler(normalizeEvent(event || window.event));
99   }
100   if (typeof node.addEventListener == "function") {
101     node.addEventListener(type, wrapHandler, false);
102     if (removeFunc) return function() {node.removeEventListener(type, wrapHandler, false);};
103   }
104   else {
105     node.attachEvent("on" + type, wrapHandler);
106     if (removeFunc) return function() {node.detachEvent("on" + type, wrapHandler);};
107   }
108 }
109
110 function nodeText(node) {
111   return node.textContent || node.innerText || node.nodeValue || "";
112 }
113
114 function nodeTop(node) {
115   var top = 0;
116   while (node.offsetParent) {
117     top += node.offsetTop;
118     node = node.offsetParent;
119   }
120   return top;
121 }
122
123 function isBR(node) {
124   var nn = node.nodeName;
125   return nn == "BR" || nn == "br";
126 }
127 function isSpan(node) {
128   var nn = node.nodeName;
129   return nn == "SPAN" || nn == "span";
130 }