source: gs3-extensions/seaweed-debug/trunk/src/Util.js@ 25160

Last change on this file since 25160 was 25160, checked in by sjm84, 12 years ago

Initial cut at a version of seaweed for debugging purposes. Check it out live into the web/ext folder

File size: 32.4 KB
Line 
1/*
2 * file: Util.js
3 *
4 * @BEGINLICENSE
5 * Copyright 2010 Brook Novak (email : [email protected])
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 * @ENDLICENSE
18 */
19bootstrap.provides("Util");
20
21/**
22 * @function
23 * Gets a text node or element in the document at a given pixel position.
24 *
25 * @param Number x The X pixel relative to the window.
26 * @param Number y The Y pixel relative to the window.
27 * @return {Node} An Element or Text node which i at the given coordinates.
28 */
29var _getRenderedNodeAtXY = document.elementFromPoint ?
30 /* Use native version if available */
31 function(x, y) {
32 //return document.elementFromPoint(x, y);
33 switch(_engine) {
34 case _Platform.GECKO:
35 case _Platform.TRIDENT:
36 return document.elementFromPoint(x, y);
37
38 default:
39 // Webkit / presto requires page coordinates instead of client/window coordinates
40 var scrollPos = _getDocumentScrollPos();
41 return document.elementFromPoint(x + scrollPos.left, y + scrollPos.top); // Opera can return text nodes
42 }
43
44
45 } : function(x, y) {
46
47 var element = null;
48
49 searchElement(docBody);
50
51 return element;
52
53 function searchElement(parent){
54
55 // First search deeper nodes
56 if (parent.childNodes.length > 0) {
57 var child = parent.firstChild;
58 while (child) {
59 if (searchElement(child))
60 return true;
61 child = child.nextSibling;
62 }
63
64 }
65
66 // Test this node... if it is an element
67 if (parent.nodeType == Node.ELEMENT_NODE && (parent.offsetLeft || parent.offsetLeft == 0)) {
68
69 // Get the elements position in the window
70 var pos = _getPositionInWindow(parent);
71
72 // Then check to see if x/y is inside bounds
73 if (y >= pos.y && y <= (pos.y + parent.offsetHeight) &&
74 x >= pos.x &&
75 x <= (pos.x + parent.offsetWidth)) {
76 // Search has finished
77 element = parent;
78 return true;
79 }
80
81 }
82
83 return false;
84
85 }
86
87 };
88
89
90/**
91 * Gets that position of an element in the window.
92 * Supports internal scroll panes - price being slower operation.
93 *
94 * @param {Object} ele The element to get the position for.
95 *
96 * @return {Object} The position of the given element {x,y}
97 */
98/*function _getPosInWndIntScrollSupport(ele){
99 var left = 0, top = 0, parent = ele;
100
101 do {
102 if (parent.offsetLeft || parent.offsetTop) {
103 left += parent.offsetLeft;
104 top += parent.offsetTop;
105 }
106 } while (parent = parent.offsetParent);
107
108 parent = ele;
109 do {
110 if (parent == docBody) break; // already handled in a cross-browser fashion
111 if (parent.scrollLeft || parent.scrollTop) {
112 left -= parent.scrollLeft;
113 top -= parent.scrollTop;
114 }
115 } while (parent = parent.parentNode); // Notice here: going up parent nodes, not offsets
116 // Get the document scroll
117 var scrollPos = _getDocumentScrollPos();
118
119 // Return coordinates relative to window (using scroll information)
120 return {
121 x: left - scrollPos.left,
122 y: top - scrollPos.top
123 };
124}*/
125
126/**
127 * Gets the position of an element in the window.
128 * Does not garuantee to support internal scrolls. However does support
129 * main document scrolling.
130 *
131 * @param {Node} ele The element to get the position for.
132 *
133 * @return {Object} The position of the given element {x,y}
134 */
135function _getPosInWndFast (ele){
136
137 var left = 0,
138 top = 0,
139 isFixed = 0; // True if encountered fixed element
140
141 do {
142
143 // Add pixel offset to parent
144 if (ele.offsetLeft || ele.offsetTop) {
145
146 if (ele == docBody) {
147 if (!isFixed) {
148 // Gecko browsers can have negitive offsets for the document body
149 // if there is a border present.
150 left += Math.abs(ele.offsetLeft);
151 top += Math.abs(ele.offsetTop);
152 }
153 } else {
154 left += ele.offsetLeft;
155 top += ele.offsetTop;
156 }
157
158 }
159
160 // TODO: NEED TO COMPUTE IF FIXED VIA CLASS.. expensive to do every element...
161 isFixed |= (ele.style && ele.style.position == "fixed");
162
163 } while (ele = ele.offsetParent);
164
165 if (!isFixed) {
166
167 // Subtract the document scroll for non-fixed elements
168 var scrollPos = _getDocumentScrollPos();
169
170 left -= scrollPos.left;
171 top -= scrollPos.top;
172
173
174 // Observations:
175 // IE Versions which already includes body border widths
176 // IE8 Standards/Quirks
177 // IE7 Quirks
178
179 // IE Versions which do not include body border widths
180 // IE7 Standards
181 // IE 6 Standards
182 if (_engine == _Platform.TRIDENT && _engineVersion < 8) {
183
184 // Some IE verions do not add the body border in any of the offsets (body/immediate children).
185 // To get the border thicknesses in IE you can query the client top/left which will not
186 // be effected by scrollbars or margins.
187
188 left += docBody.clientLeft;
189 top += docBody.clientTop;
190 }
191
192 }
193
194 // Return coordinates relative to window
195 return {
196 x: left,
197 y: top
198 };
199}
200
201/**
202 * @type Function
203 *
204 * Gets the position of an element in the window.
205 *
206 * @param {Node} ele The element to get the position for.
207 *
208 * @return {Object} The position of the given element {x,y}
209 */
210var _getPositionInWindow = _getPosInWndFast;
211
212/**
213 * Inserts a specified DOM node after a reference element as a child of the
214 * reference element's parent node.
215 *
216 * @param {Node} newNode The dom node being inserted
217 *
218 * @param {Node} refNode The node after which newNode is inserted.
219 *
220 * @return {Node} newNode passed in
221 */
222function _insertAfter(newNode, refNode){
223 var sib = refNode.nextSibling;
224 if (!sib)
225 refNode.parentNode.appendChild(newNode);
226 else
227 refNode.parentNode.insertBefore(newNode, sib);
228 return newNode;
229}
230
231/**
232 * Inserts a dom node at a given index.
233 *
234 * @param {Node} parentNode The parent of the newly inserted node
235 * @param {Node} newNode The dom node being inserted
236 * @param {Number} index The zero-based index of where in the parents child list the new node should be added.
237 */
238function _insertAt(parentNode, newNode, index) {
239
240 var i = -1;
241 var node = parentNode.firstChild;
242
243 while (++i != index && node) {
244 node = node.nextSibling;
245 }
246
247 if (i == index) {
248 if (i == parentNode.childNodes.length) parentNode.appendChild(newNode);
249 else parentNode.insertBefore(newNode, node);
250
251 return newNode;
252 }
253
254 return null;
255}
256
257/**
258 * Returns the combined length of all the descendant text nodes of a given element
259 *
260 * @param {Node} ele A element to get the text length for
261 * @return {Number} The text length for the given element
262 */
263function _getDeepTextLength(ele){
264 var len = 0;
265 _visitTextNodes(ele, true, function(textNode){
266 len += _nodeLength(textNode);
267 });
268 return len;
269}
270
271/**
272 * Clones all object members.
273 *
274 * @param {Object} obj An object to clone
275 *
276 * @return {Object} The cloned object.
277 */
278function _clone(obj) {
279 var clone = {};
280 for (var i in obj) clone[i] = obj[i];
281 return clone;
282}
283
284
285/**
286 * Traverses through DOM nodes and applies/maps a function to all nodes
287 *
288 * @param {Node} root The parent to search from. Inclusive in search. Null to find the root automatically,
289 * up to and excluding the document node (if any).
290 *
291 * @param {Node} start The node at which the traversal should start from. This must be a child of parent, or the same as parent.
292 *
293 * @param {Boolean} searchRight True to traverse tree preorder from left to right, e.g. current, child1, child2, ...
294 * False to traverse tree postorder from right to left, e.g. ... child2, child1, current
295 *
296 * @param {RegExp} filter A regular expression - the function is only
297 * applied to nodes whos names match the regular expression. If null is
298 * supplied then all nodes are visited.
299 *
300 * @param {Function} func The function to apply. One argument is given: the visting nodes.
301 * Returning false aborts traversal. Returning 1 in right searches
302 * skips traversing into the current node's children. Anything else returned
303 * will be ignored and the traversal will continue.
304 */
305function _visitNodes(root, start, searchRight, filter, func) {
306
307 // Ensure that root is set.
308 if (!root)
309 root = _getRoot(start, [Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE]);
310
311 var startStack = _getAncestors(start, root, true, true);
312 var stackIndex = startStack.length - 1;
313
314 (function trav(parent) {
315
316 var child, res, skipChildren = false;
317
318 // Are we recursing to the starting node (building stack frame)?
319 if (stackIndex > 0) { // before start point
320
321 stackIndex--;
322 child = searchRight ? startStack[stackIndex].nextSibling : startStack[stackIndex].previousSibling;
323 if (!trav(startStack[stackIndex]))
324 return false;
325
326 } else if (stackIndex == 0) { // start point onwards
327
328 // Map the function to the parent node if its node name isn't filtered out
329 if (searchRight && (!filter || filter.test(_nodeName(parent)))) {
330 res = func(parent);
331 if (res === false)
332 return res;
333 skipChildren = (res === 1); // Skip children?
334 }
335
336 // If we are traverse backwards (postorder + reverse sequence), then
337 // dont traverse deeper from the start node... begin moving left/upward
338 if (!searchRight && parent == start) child = null;
339 else child = searchRight ? parent.firstChild : parent.lastChild;
340 }
341
342 // Search children
343 if (!skipChildren) {
344 while (child) {
345 if (!trav(child))
346 return false;
347 child = (searchRight) ? child.nextSibling : child.previousSibling;
348 }
349 }
350
351 // Map the function to the parent node if its node name isn't filtered out
352 if (!searchRight && (!filter || filter.test(_nodeName(parent))))
353 if (func(parent) === false)
354 return false;
355
356 return true;
357
358 })(root);
359
360}
361
362/**
363 * Traverses through DOM nodes and applies/maps a function to text nodes.
364 *
365 * The tree traversal is preorder.
366 *
367 * @param {Node} root The parent to search from. Inclusive in search. Null to find the root automatically.
368 *
369 * @param {Node} start The node at which the traversal should start from.
370 *
371 * @param {Boolean} searchRight True to traverse tree preorder from left to right, false to traverse from right to left.
372 *
373 * @param {Function} func The function to apply. One argument is given: the child text nodes.
374 * Returning false aborts traversal.
375 *
376 *
377 */
378function _visitTextNodes(root, start, searchRight, func) {
379 _visitNodes(root, start, searchRight, /^#text$/, func);
380}
381
382/**
383 * Traverses through DOM nodes and applies/maps a function to all nodes.
384 *
385 * The tree traversal is preorder.
386 *
387 * @param {Node} root The parent to search from. Inclusive in search. Null to find the root automatically.
388 *
389 * @param {Node} start The node at which the traversal should start from.
390 *
391 * @param {Boolean} searchRight True to traverse tree preorder from left to right, false to traverse from right to left.
392 *
393 * @param {Function} func The function to apply. One argument is given: the child nodes.
394 * Returning false aborts traversal.
395 */
396function _visitAllNodes(root, start, searchRight, func) {
397 _visitNodes(root, start, searchRight, null, func);
398}
399
400/**
401 * Determines whether a node is an ansetor of another.
402 *
403 * @param {Node} ancestor A dom node
404 *
405 * @param {Node} descendant A dom node
406 *
407 * @return {Boolean} True if ancestor is an ancestor of descendant
408 */
409function _isAncestor(ancestor, descendant) {
410 descendant = descendant.parentNode;
411 while (descendant) {
412 if (descendant == ancestor)
413 return true;
414 descendant = descendant.parentNode;
415 }
416
417 return false;
418}
419
420/**
421 * Gets ancestors of a dom node.
422 *
423 * @param {Node} child The node to get ancestors for.
424 *
425 * @param {Node} endAncestor The last ancestor of the search. This can be null to get all ancestors
426 *
427 * @param {Boolean} includeChild True to include the child in with the ancestors.
428 *
429 * @param {Boolean} includeEndAncestor True to include the endAncestor in with the ancestors.
430 *
431 * @return {Array} An array of dom Node's containinhg the ancestors. Ordered from child to ancestor
432 */
433function _getAncestors(child, endAncestor, includeChild, includeEndAncestor) {
434
435 if (child == endAncestor)
436 return (includeChild || includeEndAncestor) ? [child] : [];
437
438 var ancestors = includeChild ? [child] : [];
439
440 var nd = child.parentNode;
441
442 while (nd && nd != endAncestor) {
443 ancestors.push(nd);
444 nd = nd.parentNode;
445 }
446
447 if (includeEndAncestor && endAncestor && nd == endAncestor)
448 ancestors.push(endAncestor);
449
450 return ancestors;
451}
452
453/**
454 * Finds an ancestor for a child up to a given point with a specific condition.
455 *
456 * @example
457 *
458 * var firstOccuringBlock = _findAncestor(child, docBody, de.html.isBlockLevel, true);
459 *
460 * @param {Node} child The child node to begin search from (Inclusive)
461 *
462 * @param {Node} endAncestorEx (Optional) The ancestor of the child node to stop at,
463 * Null will search up to the dom tree root
464 *
465 * @param {Function} markFunc (Optional) A function which tests a given dom node. Return true to
466 * mark the node for being the node to retrieve (depending on stopOnFirst argument).
467 * False/null/undefined to continue the search.
468 *
469 * @param {Boolean} stopOnFirst (Optional) True to stop the search on the first encountered marked node,
470 * False/null/undefined to continue search to find last occuring marked node in ancestor path.
471 *
472 * @return {Node} The querried result - null if could not find
473 */
474function _findAncestor(child, endAncestorEx, markFunc, stopOnFirst) {
475
476 var lastMarkedNode = null;
477
478 while (child) {
479 if (markFunc && markFunc(child)) {
480 if (stopOnFirst)
481 return child;
482 lastMarkedNode = child;
483 }
484 if (child.parentNode == endAncestorEx)
485 break;
486 child = child.parentNode;
487 }
488
489 return markFunc ? lastMarkedNode : child;
490}
491
492/**
493 * Gets the first common ancestor between two nodes.
494 *
495 * @param {Node} node1 A dom node
496 *
497 * @param {Node} node2 A dom node
498 *
499 * @param {Boolean} inclusive True to count node1 and node2 as being a possible common ancestor.
500 *
501 * @return {Node} the first common ancestor between two nodes. Null if they share no ancestor.
502 */
503function _getCommonAncestor(node1, node2, inclusive){
504
505 var ancestors1 = _getAncestors(node1, null, inclusive, 1),
506 ancestors2 = _getAncestors(node2, null, inclusive, 1),
507 commonParent = null;
508
509 for (var i in ancestors1) {
510 for (var j in ancestors2) {
511 if (ancestors1[i] == ancestors2[j]) {
512 return ancestors1[i];
513 }
514 }
515 }
516
517 return null;
518}
519
520/**
521 * Gets the next node in the preorder/postorder traversal.
522 *
523 * @param {Node} node The reference point.
524 *
525 * @param {Boolean} searchRight True to traverse tree preorder from left to right, false to traverse postorder from right to left.
526 *
527 * @return {Node} The next node. Null if none exists.
528 *
529 */
530function _nextNode(node, searchRight) {
531 var next = null;
532
533 _visitNodes(null, node, searchRight, null, function(nd) {
534 if (nd == node) return true; // Skip starting node
535 next = nd;
536 return false;
537 });
538
539 return next;
540}
541
542/**
543 * @param {Node} node The node to get the root for. Must not be null.
544 *
545 * @param {[Number]} untilNodeTypes Optional, an aray of DOM Node constants. If given, the search for the
546 * root node will stop just before the first encountered given node type.
547 * For example. [Node.DOCUMENT_NODE] will retreive up to the body element if
548 * it has a document node ancestor.
549 *
550 * @return {Node} the root of the given node
551 */
552function _getRoot(node, untilNodeTypes) {
553
554 while (node.parentNode){
555 if (untilNodeTypes) {
556 for (var i in untilNodeTypes) {
557 if (node.parentNode.nodeType == untilNodeTypes[i])
558 return node;
559 }
560 }
561 node = node.parentNode;
562 }
563 return node;
564}
565
566/**
567 * Gets a dom nodes child index in its parents childrens node list
568 *
569 * @param {Node} node A dom node
570 *
571 * @return {Number} The zero-based index of where the node occurs in its parent chilren.
572 * -1 if has no parent
573 */
574function _indexInParent(node) {
575 var index = -1;
576 while (node) {
577 index++;
578 node = node.previousSibling;
579 }
580 return index;
581}
582
583
584
585/**
586 * Returns a string so that special reserved entities and white spaces are escaped.
587 * Note that only whitespaces are escaped if they need to be....
588 *
589 * @param {String} text The text to escape.
590 *
591 * @param {Boolean} breakNewLines True to replace newline charactors with line breaks. False to treat as whitespace
592 *
593 * @return {String} The escaped version of text.
594 */
595function _escapeTextToHTML(text, breakNewLines) {
596
597 var escapedText = "";
598 var start = 0;
599 var c, i;
600
601 for (i = 0; i < text.length; i++) {
602 c = text.charAt(i);
603
604 var escapedStr = null;
605
606 switch(c) {
607 case "\"":
608 escapedStr = "&quot;";
609 break;
610 case "'":
611 escapedStr = "&#39;"; // &apos; does not work in IE
612 break;
613 case "&":
614 escapedStr = "&amp;";
615 break;
616 case "<":
617 escapedStr = "&lt;";
618 break;
619 case ">":
620 escapedStr = "&gt;";
621 break;
622 default:
623 if (breakNewLines && c == "\n") {
624 escapedStr = "<br>";
625
626 } else if (_isAllWhiteSpace(c) &&
627 (i == 0 ||
628 i == (text.length - 1) ||
629 text.charAt(i-1) == " " ||
630 text.charAt(i+1) == " ")) {
631 escapedStr = "&nbsp;";
632 }
633 }
634
635 // Does this charactor need escaping?
636 if (escapedStr) {
637 // First append charactors that are previously ok
638 if ((i - start) > 0) {
639 escapedText += (text.substring(start, i));
640 }
641
642 // Add the escaped version
643 escapedText += escapedStr;
644
645 // reset the start
646 start = i + 1;
647 }
648 }
649
650 // Add remaining text
651 if ((i - start) > 0) {
652 escapedText += (text.substring(start, i));
653 }
654
655 return escapedText;
656
657}
658
659
660/**
661 *
662 * @param {String} htmlText The html string to parse
663 *
664 * @return {String} The escaped version of text.
665 */
666function _parseHTMLString(htmlText) {
667
668 var tmp = $createElement("span");
669 tmp.innerHTML = htmlText;
670 return tmp.firstChild.nodeValue;
671
672}
673
674/**
675 * Determines whether a node is displayed or not depending on its immediate or inherited
676 * CSS display style. Note, that if a node's visibility is hidden, is does not mean
677 * it is not displayed.
678 *
679 * @param {Node} node A dom node to test
680 *
681 * @return {Boolean} True if the dom node is displayed, false if it is not.
682 */
683function _isNodeDisplayed(node){
684 while(node) {
685 if (node.nodeType == Node.ELEMENT_NODE) {
686 if (node.style.display == "none")
687 return false;
688 }
689 node = node.parentNode;
690 }
691 return true;
692}
693
694/**
695 * Retreives a CSS style directly set for or inherited by a given dom node.
696 *
697 * @see www.quirksmode.org/dom/getstyles.html
698 *
699 * @param {Node} node A dom node.
700 * @param {String} styleProp A CSS style property, formatted in CSS notation.
701 * @return {String} The inherited style of the given node. Undefined if the node does not have the style.
702 * If the node is not an element, then the first ancestor element is selected.
703 *
704 */
705function _getComputedStyle(node, styleProp) {
706
707 while (node && node.nodeType != Node.ELEMENT_NODE) {
708 node = node.parentNode;
709 }
710 if (!node) return;
711
712 if (window.getComputedStyle) // DOM Spec
713 return document.defaultView.getComputedStyle(node,"").getPropertyValue(styleProp)
714
715 else if (node.currentStyle) // MS HTML
716 return node.currentStyle[_styleCSSToJSNotation(styleProp)];
717
718 debug.println("Warning - could not get style \"" + styleProp + "\" for a \"" + node.nodeName + "\" element");
719 // Otherwise undefined...
720}
721
722/**
723 * Sets an element's CSS string
724 * @param {Node} ele An element node
725 * @param {String} css A css style string formatted in CSS notation.
726 *
727 * @example
728 * _setFullStyle(myElement, "color:red; padding:4px; font-size:12px");
729 */
730function _setFullStyle(ele, css){
731 if (_engine == _Platform.TRIDENT)
732 ele.style.setAttribute("cssText", css);
733 else
734 ele.setAttribute("style", css);
735}
736
737/**
738 * Sets a CSS style value for a given element
739 *
740 * @param {Node} ele An element node
741 *
742 * @param {String} css The CSS style to set in JS Notation
743 *
744 * @param {String} val The value of the new style
745 */
746function _setStyle(ele, css, val) {
747 if (_engine == _Platform.TRIDENT)
748 ele.style.setAttribute(css, val);
749 else
750 ele.style[css] = val;
751}
752
753/**
754 * Retrieves the full CSS markup for an elements style. Note that this is not the
755 * computed markup - it is the explicitely assigned CSS for the particular node.
756 *
757 * @param {Node} ele The element to get the style from
758 * @return {String} The CSS for the given element. Never null, empty if no explicit styles set
759 */
760function _getFullStyle(ele) {
761 return (_engine == _Platform.TRIDENT ? ele.style.getAttribute("cssText") : ele.getAttribute("style")) || "";
762}
763
764/**
765 * @param {Element} ele The element to check
766 * @return {Boolean} Evaluates to true iff the element has an element-level style
767 * (i.e not computed).
768 */
769function _doesHaveElementStyle(ele) {
770
771 var fs = _getFullStyle(ele);
772
773 // Check if the CSS text contains non-empty style-values
774 if (fs) {
775 fs = fs.split(";");
776 for (var s in fs) {
777 var idx = fs[s].indexOf(':');
778 if (idx > 0 &&
779 idx < (fs[s].length - 1) &&
780 /\s*\S+\s*/.test(fs[s].substr(idx)))
781 return 1;
782 }
783 }
784}
785
786/**
787 * @param {String} styleProp A CSS style in JS notation.
788 * @return {String} The given CSS style in CSS notation.
789 */
790function _styleJSToCSSNotation(styleProp) {
791 do {
792 var match = /([A-Z])/.exec(styleProp);
793 if (match)
794 styleProp = styleProp.substr(0, match.index) + "-" + match[1].toLowerCase() + styleProp.substr(match.index+1);
795 } while(match);
796
797 return styleProp;
798};
799
800/**
801 * @param {String} color A CSS Style color. Can be in hex, rgb, percentages or actual names.
802 * NOTE: Only supports converting the 16 standardized HTML color names -
803 * unstandard color names will return white.
804 *
805 * @return {[Number]} An array with elements R,G and B respectively. They range from 0-255.
806 *
807 * DEPRECIATED
808 */
809var _getColorRGB = function() {
810
811 var colorRegExp = /^\s*rgb\s*\(\s*(\d+)\%?\s*\,\s*(\d+)\%?\s*\,\s*(\d+)\%?\s*\)\s*$/i,
812
813 /* Only going to support the 16 standardized colors. All major browsers support a lot more but will seriously bloat the api size. */
814 colorWMap = {
815 maroon: [128,0,0],
816 red: [255,0,0],
817 orange: [255,165,0],
818 yellow: [255,255,0],
819 olive: [128,128,0],
820 purple: [128,0,128],
821 fuchsia: [255,0,255],
822 white: [255,255,255],
823 lime: [0,255,0],
824 green: [0,128,0],
825 navy: [0,0,128],
826 blue: [0,0,255],
827 aqua: [0,255,255],
828 teal: [0,128,128],
829 black: [0,0,0],
830 silver: [12,12,12],
831 gray: [128,128,128]
832 };
833
834 return function(val){
835
836 if (val.charAt(0) == "#") {
837 if (val.length < 7)
838 val += "000000";
839 // Convert to RGB
840 return [parseInt(val.substr(1,2),16), parseInt(val.substr(3,2),16), parseInt(val.substr(5,2),16)];
841 }
842
843 // Is the color in the notation "rbg(r,b,g)" ?
844 var match = colorRegExp.exec(val);
845 if (match) {
846
847 var r = parseInt(match[1]), g = parseInt(match[2]), b = parseInt(match[3]);
848
849 if (val.indexOf("%") > -1) { // convert percentages to 255 range
850 if (r > 100) r = 100; // clamp;
851 r = (255 * r) / 100;
852 if (g > 100) g = 100; // clamp;
853 g = (255 * g) / 100;
854 if (b > 100) b = 100; // clamp;
855 b = (255 * b) / 100;
856 } else { // Clamp 255 range
857 if (r > 255) r = 255;
858 if (g > 255) g = 255;
859 if (b > 255) b = 255;
860 }
861
862 return [r,g,b];
863 }
864
865 return colorWMap[val.toLowerCase()] || [255,255,255];
866 }
867
868}();
869
870/**
871 * @param {String} cssStyle A CSS Style to check
872 * @param {String} val1 The value of a CSS style to compare (with val2)
873 * @param {String} val2 The value of a CSS style to compare (with val1)
874 * @return {Boolean} True if val1 is equivalent to val2 CSS
875 *
876 * DEPRECIATED
877 *
878 */
879var _isCSSValueSame = function(){
880
881 var fontWeightMap = {
882 bold: "700",
883 normal: "400"
884 };
885
886 function normalizeFontWeight(val){
887 return fontWeightMap[val.toLowerCase()] || val;
888 }
889
890
891 return function(cssStyle, val1, val2){
892
893 switch (cssStyle) {
894 case "backgroundColor":
895 case "borderColor":
896 case "outlineColor":
897 case "color":
898 val1 = _getColorRGB(val1);
899 val2 = _getColorRGB(val2);
900 return val1[0] == val2[0] && val1[1] == val2[1] && val1[2] == val2[2];
901
902 case "fontWeight":
903 val1 = normalizeFontWeight(val1);
904 val2 = normalizeFontWeight(val2);
905 break;
906 }
907
908 return val1 == val2;
909
910 };
911
912}();
913
914/**
915 * @param {String} styleProp A CSS style in CSS notation.
916 * @return {String} The given CSS style in JS notation.
917 */
918function _styleCSSToJSNotation(styleProp) {
919 do {
920 var index = styleProp.indexOf("-");
921 if (index > -1)
922 styleProp = (index == (styleProp.length-1)) ?
923 styleProp.substr(0, index) :
924 styleProp.substr(0, index) + styleProp.charAt(index+1).toUpperCase() + styleProp.substr(index + 2);
925 } while(index > -1);
926 return styleProp;
927};
928
929
930
931/**
932 * Gets the outer HTML content of a given element.
933 * NOTE: Can be expensive for large DOM Trees in firefox/konqueror.
934 * @param {Node} node An Element to get it's outer HTML for.
935 * @return {String} The outer html of the given node.
936 */
937function _getOuterHTML(node) {
938 if (node.outerHTML) return node.outerHTML;
939 else { // Firefox / konqueror
940 var tmp = $createElement("span");
941 tmp.appendChild(node.cloneNode(true));
942 return tmp.innerHTML;
943 }
944}
945
946/**
947 * @return {Boolean} True if this browser allows you to safely extend the DOM.
948 */
949function _isDOMExtendable() {
950 /* IE Versions 7 down are not core javascript. */
951 return !(_browser == _Platform.IE && _browserVersion < 8);
952}
953
954/**
955 * @param {Node} node The node to extract the class name from
956 * @param {RegExp} A regular expression.
957 * @return {String} the first occurring classname of the node which matches regexp.
958 * Null if did not find a match
959 */
960function _findClassName(node, regexp){
961 if (node.nodeType == Node.ELEMENT_NODE || node == docBody) {
962 var clsName = _getClassName(node);
963 if (clsName) {
964 var classNames = clsName.split(' ');
965 for (var i in classNames) {
966 if (regexp.test(classNames[i]))
967 return classNames[i];
968 }
969 }
970 }
971 return null;
972}
973
974/**
975 * @param {Node} element A Dom element
976 * @return {String} The class name for the given element
977 */
978function _getClassName(element) {
979 return element.className;
980}
981
982/**
983 * @param {Node} element A Dom element
984 * @param {String} name The class to set - overrides all classes.
985 */
986function _setClassName(element, name) {
987 return _browser == _Platform.IE ? element.setAttribute("className", name) :
988 element.className = name;
989}
990
991/**
992 * Not all browsers support Array.indexOf .. this is a manual impl.
993 *
994 * @param {Object} obj An object
995 * @param {Array} arr An array
996 * @return {Number} The index of obj in arr. -1 if obj is not in arr.
997 */
998function _indexOf(obj, arr) {
999 for (var i in arr) {
1000 if (arr[i] == obj)
1001 return parseInt(i);
1002 }
1003 return -1;
1004}
1005
1006/**
1007 * @param {Node} node a dom node
1008 * @return {String} The dom node's name in lower case
1009 */
1010function _nodeName(node) {
1011 return node.nodeName.toLowerCase();
1012}
1013
1014/**
1015 * Determines whether a node is a text node and returns the text length if it is.
1016 *
1017 * @param {Node} node The dom node to test
1018 *
1019 * @param {Object} defaultValue (optional) If the node to test is not a text node then this value will be returned instead.
1020 * Defaults to NULL.
1021 *
1022 * @return {Object} If the node is a text node, then the text length of the node will be returned.
1023 * Otherwise defaultValue will be returned.
1024 */
1025function _nodeLength(node, defaultValue) {
1026 if (typeof defaultValue == "undefined")
1027 defaultValue = null;
1028 return node.nodeType == Node.TEXT_NODE ? node.nodeValue.length : defaultValue;
1029}
1030
1031/**
1032 * Determines if an object is a DOM Node or not.
1033 * @param {Object} obj The object to test
1034 */
1035function _isDOMNode(obj){
1036
1037 // @DEBUG ON
1038 // In debug mode, the Node object will be created if it is not available - in order to provide
1039 // node type constants. To distinuish from a real node object and the fabricaed one, test if the
1040 // _DE_DEBUG_CREATED if there
1041 if (Node._DE_DEBUG_CREATED)
1042 return typeof obj == "object" && typeof obj.nodeType == "number" && typeof obj.nodeName == "string";
1043 // @DEBUG OFF
1044
1045 return typeof Node == "object" ? obj instanceof Node : (typeof obj == "object" && typeof obj.nodeType == "number" && typeof obj.nodeName == "string");
1046};
1047
1048/*
1049 * Expose internals to public
1050 */
1051$extend(de, {
1052
1053 /**
1054 * Exposure of _visitAllNodes internal
1055 * @see _visitAllNodes
1056 */
1057 visitAllNodes : _visitAllNodes,
1058
1059 getCommonAncestor : _getCommonAncestor,
1060
1061 /**
1062 * @param {Node} node a dom node
1063 * @return {String} The inner text of the given node, never null, but can be empty.
1064 */
1065 getInnerText : function(node) {
1066 if (node.nodeType == Node.TEXT_NODE)
1067 return node.nodeValue;
1068 return node.innerText || node.textContent || "";
1069 },
1070
1071 /**
1072 * Exposure of _parseHTMLString internal
1073 * @see _parseHTMLString
1074 */
1075 parseHTMLString : _parseHTMLString,
1076
1077 /**
1078 * Exposure of _insertAfter internal
1079 * @see _insertAfter
1080 */
1081 insertAfter : _insertAfter,
1082
1083 /**
1084 * Exposure of _insertAt internal
1085 * @see _insertAt
1086 */
1087 insertAt : _insertAt,
1088
1089 /**
1090 * Exposure of _findClassName internal
1091 * @see _findClassName
1092 */
1093 findClassName : _findClassName,
1094
1095 /**
1096 * Exposure of _getPositionInWindow internal
1097 * @see _getPositionInWindow
1098 */
1099 getPositionInWindow : _getPositionInWindow,
1100
1101 getOuterHTML : _getOuterHTML,
1102
1103 getComputedStyle : _getComputedStyle
1104
1105});
Note: See TracBrowser for help on using the repository browser.