1 //Add ECMA262-5 method binding if not supported natively 2 // 3 if (!('bind' in Function.prototype)) { 4 Function.prototype.bind= function(owner) { 5 var that= this; 6 if (arguments.length<=1) { 7 return function() { 8 return that.apply(owner, arguments); 9 }; 10 } else { 11 var args= Array.prototype.slice.call(arguments, 1); 12 return function() { 13 return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments))); 14 }; 15 } 16 }; 17 } 18 19 // Add ECMA262-5 string trim if not supported natively 20 // 21 if (!('trim' in String.prototype)) { 22 String.prototype.trim= function() { 23 return this.replace(/^\s+/, '').replace(/\s+$/, ''); 24 }; 25 } 26 27 // Add ECMA262-5 Array methods if not supported natively 28 // 29 if (!('indexOf' in Array.prototype)) { 30 Array.prototype.indexOf= function(find, i /*opt*/) { 31 if (i===undefined) i= 0; 32 if (i<0) i+= this.length; 33 if (i<0) i= 0; 34 for (var n= this.length; i<n; i++) 35 if (i in this && this[i]===find) 36 return i; 37 return -1; 38 }; 39 } 40 if (!('lastIndexOf' in Array.prototype)) { 41 Array.prototype.lastIndexOf= function(find, i /*opt*/) { 42 if (i===undefined) i= this.length-1; 43 if (i<0) i+= this.length; 44 if (i>this.length-1) i= this.length-1; 45 for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */ 46 if (i in this && this[i]===find) 47 return i; 48 return -1; 49 }; 50 } 51 if (!('forEach' in Array.prototype)) { 52 Array.prototype.forEach= function(action, that /*opt*/) { 53 for (var i= 0, n= this.length; i<n; i++) 54 if (i in this) 55 action.call(that, this[i], i, this); 56 }; 57 } 58 if (!('map' in Array.prototype)) { 59 Array.prototype.map= function(mapper, that /*opt*/) { 60 var other= new Array(this.length); 61 for (var i= 0, n= this.length; i<n; i++) 62 if (i in this) 63 other[i]= mapper.call(that, this[i], i, this); 64 return other; 65 }; 66 } 67 if (!('filter' in Array.prototype)) { 68 Array.prototype.filter= function(filter, that /*opt*/) { 69 var other= [], v; 70 for (var i=0, n= this.length; i<n; i++) 71 if (i in this && filter.call(that, v= this[i], i, this)) 72 other.push(v); 73 return other; 74 }; 75 } 76 if (!('every' in Array.prototype)) { 77 Array.prototype.every= function(tester, that /*opt*/) { 78 for (var i= 0, n= this.length; i<n; i++) 79 if (i in this && !tester.call(that, this[i], i, this)) 80 return false; 81 return true; 82 }; 83 } 84 if (!('some' in Array.prototype)) { 85 Array.prototype.some= function(tester, that /*opt*/) { 86 for (var i= 0, n= this.length; i<n; i++) 87 if (i in this && tester.call(that, this[i], i, this)) 88 return true; 89 return false; 90 }; 91 } 92 if (!Node) { 93 // http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1841493061 94 var Node = { 95 'ELEMENT_NODE' : 1, 96 'ATTRIBUTE_NODE': 2, 97 'TEXT_NODE': 3, 98 'CDATA_SECTION_NODE': 4, 99 'ENTITY_REFERENCE_NODE': 5, 100 'ENTITY_NODE': 6, 101 'PROCESSING_INSTRUCTION_NODE': 7, 102 'COMMENT_NODE': 8, 103 'DOCUMENT_NODE': 9, 104 'DOCUMENT_TYPE_NODE': 10, 105 'DOCUMENT_FRAGMENT_NODE': 11, 106 'NOTATION_NODE': 12, 107 //The two nodes are disconnected. Order between disconnected nodes is always implementation-specific. 108 'DOCUMENT_POSITION_DISCONNECTED': 0x01, 109 //The second node precedes the reference node. 110 'DOCUMENT_POSITION_PRECEDING': 0x02, 111 //The node follows the reference node. 112 'DOCUMENT_POSITION_FOLLOWING': 0x04, 113 //The node contains the reference node. A node which contains is always preceding, too. 114 'DOCUMENT_POSITION_CONTAINS': 0x08, 115 //The node is contained by the reference node. A node which is contained is always following, too. 116 'DOCUMENT_POSITION_CONTAINED_BY': 0x10, 117 //The determination of preceding versus following is implementation-specific. 118 'DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC': 0x20 119 }; 120 } 121 122 // http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition 123 // FIXME: Check if the DOMNode prototype can be set. 124 window.compareDocumentPosition = function(node1, node2) { 125 126 if ('compareDocumentPosition' in document.documentElement ) { 127 return node1.compareDocumentPosition(node2); 128 } 129 130 if (!("contains" in document.documentElement)) { 131 throw 'compareDocumentPosition nor contains is not supported by this browser.'; 132 } 133 134 if (node1 == node2) return 0; 135 136 //if they don't have the same parent, there's a disconnect 137 if (getRootParent(node1) != getRootParent(node2)) return 1; 138 139 //use this if both nodes have a sourceIndex (text nodes don't) 140 if ("sourceIndex" in node1 && "sourceIndex" in node2) { 141 return comparePosition(node1, node2); 142 } 143 144 //document will definitely contain the other node 145 if (node1 == document) return 20; 146 else if (node2 == document) return 10; 147 148 //get sourceIndexes to use for both nodes 149 var useNode1 = getUseNode(node1), useNode2 = getUseNode(node2); 150 151 //call this function again to get the result 152 var result = comparePosition(useNode1, useNode2); 153 154 //clean up if needed 155 if (node1 != useNode1) useNode1.parentNode.removeChild(useNode1); 156 if (node2 != useNode2) useNode2.parentNode.removeChild(useNode2); 157 return result; 158 159 160 //node.ownerDocument gives the document object, which isn't the right info for a disconnect 161 function getRootParent(node) { 162 do { var parent = node; } 163 while (node = node.parentNode); 164 return parent; 165 } 166 167 //Compare Position - MIT Licensed, John Resig; http://ejohn.org/blog/comparing-document-position/ 168 //Already checked for equality and disconnect 169 function comparePosition(node1, node2) { 170 return (node1.contains(node2) && 16) + 171 (node2.contains(node1) && 8) + 172 (node1.sourceIndex >= 0 && node2.sourceIndex >= 0 ? 173 174 (node1.sourceIndex < node2.sourceIndex && 4) + 175 (node1.sourceIndex > node2.sourceIndex && 2) : 176 1); 177 } 178 179 //get a node with a sourceIndex to use 180 function getUseNode(node) { 181 //if the node already has a sourceIndex, use that node 182 if ("sourceIndex" in node) return node; 183 //otherwise, insert a comment (which has a sourceIndex but minimal DOM impact) before the node and use that 184 return node.parentNode.insertBefore(document.createComment(""), node); 185 } 186 }; 187 188 if (!('getComputedStyle' in window)) { 189 window.getComputedStyle = function (node, style) { 190 if( node.currentStyle ) { 191 return node.currentStyle; 192 } 193 return null; 194 } 195 } 196