796025eeeeeef03b5af199e4321e59014c7fd834
[redakcja.git] / redakcja / static / js / lib / codemirror / util.js
1 /* A few useful utility functions. */
2
3 var internetExplorer = document.selection && window.ActiveXObject && /MSIE/.test(navigator.userAgent);
4 var webkit = /AppleWebKit/.test(navigator.userAgent);
5 var safari = /Apple Computers, Inc/.test(navigator.vendor);
6
7 // Capture a method on an object.
8 function method(obj, name) {
9   return function() {obj[name].apply(obj, arguments);};
10 }
11
12 // The value used to signal the end of a sequence in iterators.
13 var StopIteration = {toString: function() {return "StopIteration"}};
14
15 // Apply a function to each element in a sequence.
16 function forEach(iter, f) {
17   if (iter.next) {
18     try {while (true) f(iter.next());}
19     catch (e) {if (e != StopIteration) throw e;}
20   }
21   else {
22     for (var i = 0; i < iter.length; i++)
23       f(iter[i]);
24   }
25 }
26
27 // Map a function over a sequence, producing an array of results.
28 function map(iter, f) {
29   var accum = [];
30   forEach(iter, function(val) {accum.push(f(val));});
31   return accum;
32 }
33
34 // Create a predicate function that tests a string againsts a given
35 // regular expression. No longer used but might be used by 3rd party
36 // parsers.
37 function matcher(regexp){
38   return function(value){return regexp.test(value);};
39 }
40
41 // Test whether a DOM node has a certain CSS class. Much faster than
42 // the MochiKit equivalent, for some reason.
43 function hasClass(element, className){
44   var classes = element.className;
45   return classes && new RegExp("(^| )" + className + "($| )").test(classes);
46 }
47
48 // Insert a DOM node after another node.
49 function insertAfter(newNode, oldNode) {
50   var parent = oldNode.parentNode;
51   parent.insertBefore(newNode, oldNode.nextSibling);
52   return newNode;
53 }
54
55 function removeElement(node) {
56   if (node.parentNode)
57     node.parentNode.removeChild(node);
58 }
59
60 function clearElement(node) {
61   while (node.firstChild)
62     node.removeChild(node.firstChild);
63 }
64
65 // Check whether a node is contained in another one.
66 function isAncestor(node, child) {
67   while (child = child.parentNode) {
68     if (node == child)
69       return true;
70   }
71   return false;
72 }
73
74 // The non-breaking space character.
75 var nbsp = "\u00a0";
76 var matching = {"{": "}", "[": "]", "(": ")",
77                 "}": "{", "]": "[", ")": "("};
78
79 // Standardize a few unportable event properties.
80 function normalizeEvent(event) {
81   if (!event.stopPropagation) {
82     event.stopPropagation = function() {this.cancelBubble = true;};
83     event.preventDefault = function() {this.returnValue = false;};
84   }
85   if (!event.stop) {
86     event.stop = function() {
87       this.stopPropagation();
88       this.preventDefault();
89     };
90   }
91
92   if (event.type == "keypress") {
93     event.code = (event.charCode == null) ? event.keyCode : event.charCode;
94     event.character = String.fromCharCode(event.code);
95   }
96   return event;
97 }
98
99 // Portably register event handlers.
100 function addEventHandler(node, type, handler, removeFunc) {
101   function wrapHandler(event) {
102     handler(normalizeEvent(event || window.event));
103   }
104   if (typeof node.addEventListener == "function") {
105     node.addEventListener(type, wrapHandler, false);
106     if (removeFunc) return function() {node.removeEventListener(type, wrapHandler, false);};
107   }
108   else {
109     node.attachEvent("on" + type, wrapHandler);
110     if (removeFunc) return function() {node.detachEvent("on" + type, wrapHandler);};
111   }
112 }
113
114 function nodeText(node) {
115   return node.textContent || node.innerText || node.nodeValue || "";
116 }
117
118 function nodeTop(node) {
119   var top = 0;
120   while (node.offsetParent) {
121     top += node.offsetTop;
122     node = node.offsetParent;
123   }
124   return top;
125 }