-
Notifications
You must be signed in to change notification settings - Fork 13
/
DOMAdapter.js
136 lines (120 loc) · 5.43 KB
/
DOMAdapter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
var cMath = global.Math;
function cDOMAdapter() {
};
// Custom members
cDOMAdapter.prototype.isNode = function(oNode) {
return oNode &&!!oNode.nodeType;
};
cDOMAdapter.prototype.getProperty = function(oNode, sName) {
return oNode[sName];
};
// Standard members
cDOMAdapter.prototype.isSameNode = function(oNode, oNode2) {
return oNode == oNode2;
};
cDOMAdapter.prototype.compareDocumentPosition = function(oNode, oChild) {
// Run native if there is one
if ("compareDocumentPosition" in oNode)
return oNode.compareDocumentPosition(oChild);
// Otherwise run JS fallback
if (oChild == oNode)
return 0;
//
var oAttr1 = null,
oAttr2 = null,
aAttributes,
oAttr, oElement, nIndex, nLength;
if (this.getProperty(oNode, "nodeType") == 2 /* cNode.ATTRIBUTE_NODE */) {
oAttr1 = oNode;
oNode = this.getProperty(oAttr1, "ownerElement");
}
if (this.getProperty(oChild, "nodeType") == 2 /* cNode.ATTRIBUTE_NODE */) {
oAttr2 = oChild;
oChild = this.getProperty(oAttr2, "ownerElement");
}
// Compare attributes from same element
if (oAttr1 && oAttr2 && oNode && oNode == oChild) {
for (nIndex = 0, aAttributes = this.getProperty(oNode, "attributes"), nLength = aAttributes.length; nIndex < nLength; nIndex++) {
oAttr = aAttributes[nIndex];
if (oAttr == oAttr1)
return 32 /* cNode.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC */ | 4 /* cNode.DOCUMENT_POSITION_FOLLOWING */;
if (oAttr == oAttr2)
return 32 /* cNode.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC */ | 2 /* cNode.DOCUMENT_POSITION_PRECEDING */;
}
}
//
var aChain1 = [], nLength1, oNode1,
aChain2 = [], nLength2, oNode2;
//
if (oAttr1)
aChain1.push(oAttr1);
for (oElement = oNode; oElement; oElement = this.getProperty(oElement, "parentNode"))
aChain1.push(oElement);
if (oAttr2)
aChain2.push(oAttr2);
for (oElement = oChild; oElement; oElement = this.getProperty(oElement, "parentNode"))
aChain2.push(oElement);
// If nodes are from different documents or if they do not have common top, they are disconnected
if (((this.getProperty(oNode, "ownerDocument") || oNode) != (this.getProperty(oChild, "ownerDocument") || oChild)) || (aChain1[aChain1.length - 1] != aChain2[aChain2.length - 1]))
return 32 /* cNode.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC */ | 1 /* cNode.DOCUMENT_POSITION_DISCONNECTED */;
//
for (nIndex = cMath.min(nLength1 = aChain1.length, nLength2 = aChain2.length); nIndex; --nIndex)
if ((oNode1 = aChain1[--nLength1]) != (oNode2 = aChain2[--nLength2])) {
//
if (this.getProperty(oNode1, "nodeType") == 2 /* cNode.ATTRIBUTE_NODE */)
return 4 /* cNode.DOCUMENT_POSITION_FOLLOWING */;
if (this.getProperty(oNode2, "nodeType") == 2 /* cNode.ATTRIBUTE_NODE */)
return 2 /* cNode.DOCUMENT_POSITION_PRECEDING */;
//
if (!this.getProperty(oNode2, "nextSibling"))
return 4 /* cNode.DOCUMENT_POSITION_FOLLOWING */;
if (!this.getProperty(oNode1, "nextSibling"))
return 2 /* cNode.DOCUMENT_POSITION_PRECEDING */;
for (oElement = this.getProperty(oNode2, "previousSibling"); oElement; oElement = this.getProperty(oElement, "previousSibling"))
if (oElement == oNode1)
return 4 /* cNode.DOCUMENT_POSITION_FOLLOWING */;
return 2 /* cNode.DOCUMENT_POSITION_PRECEDING */;
}
//
return nLength1 < nLength2 ? 4 /* cNode.DOCUMENT_POSITION_FOLLOWING */ | 16 /* cNode.DOCUMENT_POSITION_CONTAINED_BY */ : 2 /* cNode.DOCUMENT_POSITION_PRECEDING */ | 8 /* cNode.DOCUMENT_POSITION_CONTAINS */;
};
cDOMAdapter.prototype.lookupNamespaceURI = function(oNode, sPrefix) {
// Run native if there is one
if ("lookupNamespaceURI" in oNode)
return oNode.lookupNamespaceURI(sPrefix);
// Otherwise run JS fallback
for (; oNode && this.getProperty(oNode, "nodeType") != 9 /* cNode.DOCUMENT_NODE */ ; oNode = this.getProperty(oNode, "parentNode"))
if (sPrefix == this.getProperty(oNode, "prefix"))
return this.getProperty(oNode, "namespaceURI");
else
if (this.getProperty(oNode, "nodeType") == 1) // cNode.ELEMENT_NODE
for (var oAttributes = this.getProperty(oNode, "attributes"), nIndex = 0, nLength = oAttributes.length, sName = "xmlns" + ':' + sPrefix; nIndex < nLength; nIndex++)
if (this.getProperty(oAttributes[nIndex], "nodeName") == sName)
return this.getProperty(oAttributes[nIndex], "value");
return null;
};
// Document object members
cDOMAdapter.prototype.getElementById = function(oNode, sId) {
if ("getElementById" in oNode)
return oNode.getElementById(sId);
return fTraverse(this, this.getProperty(oNode, "documentElement"), function(oDOMAdapter, oNode) {
for (var oAttributes = oDOMAdapter.getProperty(oNode, "attributes"), nIndex = 0, nLength = oAttributes.length; nIndex < nLength; nIndex++) {
if (oDOMAdapter.getProperty(oAttributes[nIndex], "nodeName") == "id")
return oDOMAdapter.getProperty(oAttributes[nIndex], "value") == sId;
}
return false;
});
};
function fTraverse(oDOMAdapter, oParent, fTest) {
for (var oNode = oParent, oChild; oNode; oNode = oDOMAdapter.getProperty(oNode, "nextSibling")) {
if (oDOMAdapter.getProperty(oNode, "nodeType") == 1) {
if (fTest(oDOMAdapter, oNode))
return oNode;
if (oChild = fTraverse(oDOMAdapter, oDOMAdapter.getProperty(oNode, "firstChild"), fTest))
return oChild;
}
}
return null;
};
//
module.exports = cDOMAdapter;