-
Notifications
You must be signed in to change notification settings - Fork 0
/
dom.js
212 lines (194 loc) · 6.21 KB
/
dom.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
define(["./sniff", "./_base/window", "./_base/kernel"],
function(has, win, kernel){
// module:
// dojo/dom
// FIXME: need to add unit tests for all the semi-public methods
if(has("ie") <= 7){
try{
document.execCommand("BackgroundImageCache", false, true);
}catch(e){
// sane browsers don't have cache "issues"
}
}
// =============================
// DOM Functions
// =============================
// the result object
var dom = {
// summary:
// This module defines the core dojo DOM API.
};
if(has("ie")){
dom.byId = function(id, doc){
if(typeof id != "string"){
return id;
}
var _d = doc || win.doc, te = id && _d.getElementById(id);
// attributes.id.value is better than just id in case the
// user has a name=id inside a form
if(te && (te.attributes.id.value == id || te.id == id)){
return te;
}else{
var eles = _d.all[id];
if(!eles || eles.nodeName){
eles = [eles];
}
// if more than 1, choose first with the correct id
var i = 0;
while((te = eles[i++])){
if((te.attributes && te.attributes.id && te.attributes.id.value == id) || te.id == id){
return te;
}
}
}
};
}else{
dom.byId = function(id, doc){
// inline'd type check.
// be sure to return null per documentation, to match IE branch.
return ((typeof id == "string") ? (doc || win.doc).getElementById(id) : id) || null; // DOMNode
};
}
/*=====
dom.byId = function(id, doc){
// summary:
// Returns DOM node with matching `id` attribute or falsy value (ex: null or undefined)
// if not found. If `id` is a DomNode, this function is a no-op.
//
// id: String|DOMNode
// A string to match an HTML id attribute or a reference to a DOM Node
//
// doc: Document?
// Document to work in. Defaults to the current value of
// dojo/_base/window.doc. Can be used to retrieve
// node references from other documents.
//
// example:
// Look up a node by ID:
// | require(["dojo/dom"], function(dom){
// | var n = dom.byId("foo");
// | });
//
// example:
// Check if a node exists, and use it.
// | require(["dojo/dom"], function(dom){
// | var n = dom.byId("bar");
// | if(n){ doStuff() ... }
// | });
//
// example:
// Allow string or DomNode references to be passed to a custom function:
// | require(["dojo/dom"], function(dom){
// | var foo = function(nodeOrId){
// | nodeOrId = dom.byId(nodeOrId);
// | // ... more stuff
// | }
// | });
};
=====*/
// Test for DOMNode.contains() method, available everywhere except FF8-
// and IE8-, where it's available in general, but not on document itself,
// and also problems when either ancestor or node are text nodes.
var doc = kernel.global["document"] || null;
has.add("dom-contains", !!(doc && doc.contains));
dom.isDescendant = has("dom-contains") ?
// FF9+, IE9+, webkit, opera, iOS, Android, Edge, etc.
function(/*DOMNode|String*/ node, /*DOMNode|String*/ ancestor){
return !!( (ancestor = dom.byId(ancestor)) && ancestor.contains(dom.byId(node)) );
} :
function(/*DOMNode|String*/ node, /*DOMNode|String*/ ancestor){
// summary:
// Returns true if node is a descendant of ancestor
// node: DOMNode|String
// string id or node reference to test
// ancestor: DOMNode|String
// string id or node reference of potential parent to test against
//
// example:
// Test is node id="bar" is a descendant of node id="foo"
// | require(["dojo/dom"], function(dom){
// | if(dom.isDescendant("bar", "foo")){ ... }
// | });
try{
node = dom.byId(node);
ancestor = dom.byId(ancestor);
while(node){
if(node == ancestor){
return true; // Boolean
}
node = node.parentNode;
}
}catch(e){ /* squelch, return false */ }
return false; // Boolean
};
// TODO: do we need setSelectable in the base?
// Add feature test for user-select CSS property
// (currently known to work in all but IE < 10 and Opera)
// TODO: The user-select CSS property as of May 2014 is no longer part of
// any CSS specification. In IE, -ms-user-select does not do the same thing
// as the unselectable attribute on elements; namely, dijit Editor buttons
// do not properly prevent the content of the editable content frame from
// unblurring. As a result, the -ms- prefixed version is omitted here.
has.add("css-user-select", function(global, doc, element){
// Avoid exception when dom.js is loaded in non-browser environments
if(!element){ return false; }
var style = element.style;
var prefixes = ["Khtml", "O", "Moz", "Webkit"],
i = prefixes.length,
name = "userSelect",
prefix;
// Iterate prefixes from most to least likely
do{
if(typeof style[name] !== "undefined"){
// Supported; return property name
return name;
}
}while(i-- && (name = prefixes[i] + "UserSelect"));
// Not supported if we didn't return before now
return false;
});
/*=====
dom.setSelectable = function(node, selectable){
// summary:
// Enable or disable selection on a node
// node: DOMNode|String
// id or reference to node
// selectable: Boolean
// state to put the node in. false indicates unselectable, true
// allows selection.
// example:
// Make the node id="bar" unselectable
// | require(["dojo/dom"], function(dom){
// | dom.setSelectable("bar");
// | });
// example:
// Make the node id="bar" selectable
// | require(["dojo/dom"], function(dom){
// | dom.setSelectable("bar", true);
// | });
};
=====*/
var cssUserSelect = has("css-user-select");
dom.setSelectable = cssUserSelect ? function(node, selectable){
// css-user-select returns a (possibly vendor-prefixed) CSS property name
dom.byId(node).style[cssUserSelect] = selectable ? "" : "none";
} : function(node, selectable){
node = dom.byId(node);
// (IE < 10 / Opera) Fall back to setting/removing the
// unselectable attribute on the element and all its children
var nodes = node.getElementsByTagName("*"),
i = nodes.length;
if(selectable){
node.removeAttribute("unselectable");
while(i--){
nodes[i].removeAttribute("unselectable");
}
}else{
node.setAttribute("unselectable", "on");
while(i--){
nodes[i].setAttribute("unselectable", "on");
}
}
};
return dom;
});