OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007 Apple Inc. All rights reserved. |
3 * Copyright (C) 2012 Google Inc. All rights reserved. | 3 * Copyright (C) 2012 Google Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * | 8 * |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 } else { | 115 } else { |
116 endNode = this; | 116 endNode = this; |
117 endOffset = offset; | 117 endOffset = offset; |
118 } | 118 } |
119 | 119 |
120 var result = this.ownerDocument.createRange(); | 120 var result = this.ownerDocument.createRange(); |
121 result.setStart(startNode, startOffset); | 121 result.setStart(startNode, startOffset); |
122 result.setEnd(endNode, endOffset); | 122 result.setEnd(endNode, endOffset); |
123 | 123 |
124 return result; | 124 return result; |
125 } | 125 }; |
126 | 126 |
127 /** | 127 /** |
128 * @param {!Node=} stayWithin | 128 * @param {!Node=} stayWithin |
129 * @return {?Node} | 129 * @return {?Node} |
130 */ | 130 */ |
131 Node.prototype.traverseNextTextNode = function(stayWithin) | 131 Node.prototype.traverseNextTextNode = function(stayWithin) |
132 { | 132 { |
133 var node = this.traverseNextNode(stayWithin); | 133 var node = this.traverseNextNode(stayWithin); |
134 if (!node) | 134 if (!node) |
135 return null; | 135 return null; |
136 var nonTextTags = { "STYLE": 1, "SCRIPT": 1 }; | 136 var nonTextTags = { "STYLE": 1, "SCRIPT": 1 }; |
137 while (node && (node.nodeType !== Node.TEXT_NODE || nonTextTags[node.parentE
lement.nodeName])) | 137 while (node && (node.nodeType !== Node.TEXT_NODE || nonTextTags[node.parentE
lement.nodeName])) |
138 node = node.traverseNextNode(stayWithin); | 138 node = node.traverseNextNode(stayWithin); |
139 | 139 |
140 return node; | 140 return node; |
141 } | 141 }; |
142 | 142 |
143 /** | 143 /** |
144 * @param {number|undefined} x | 144 * @param {number|undefined} x |
145 * @param {number|undefined} y | 145 * @param {number|undefined} y |
146 * @param {!Element=} relativeTo | 146 * @param {!Element=} relativeTo |
147 */ | 147 */ |
148 Element.prototype.positionAt = function(x, y, relativeTo) | 148 Element.prototype.positionAt = function(x, y, relativeTo) |
149 { | 149 { |
150 var shift = {x: 0, y: 0}; | 150 var shift = {x: 0, y: 0}; |
151 if (relativeTo) | 151 if (relativeTo) |
152 shift = relativeTo.boxInWindow(this.ownerDocument.defaultView); | 152 shift = relativeTo.boxInWindow(this.ownerDocument.defaultView); |
153 | 153 |
154 if (typeof x === "number") | 154 if (typeof x === "number") |
155 this.style.setProperty("left", (shift.x + x) + "px"); | 155 this.style.setProperty("left", (shift.x + x) + "px"); |
156 else | 156 else |
157 this.style.removeProperty("left"); | 157 this.style.removeProperty("left"); |
158 | 158 |
159 if (typeof y === "number") | 159 if (typeof y === "number") |
160 this.style.setProperty("top", (shift.y + y) + "px"); | 160 this.style.setProperty("top", (shift.y + y) + "px"); |
161 else | 161 else |
162 this.style.removeProperty("top"); | 162 this.style.removeProperty("top"); |
163 | 163 |
164 if (typeof x === "number" || typeof y === "number") | 164 if (typeof x === "number" || typeof y === "number") |
165 this.style.setProperty("position", "absolute"); | 165 this.style.setProperty("position", "absolute"); |
166 else | 166 else |
167 this.style.removeProperty("position"); | 167 this.style.removeProperty("position"); |
168 } | 168 }; |
169 | 169 |
170 /** | 170 /** |
171 * @return {boolean} | 171 * @return {boolean} |
172 */ | 172 */ |
173 Element.prototype.isScrolledToBottom = function() | 173 Element.prototype.isScrolledToBottom = function() |
174 { | 174 { |
175 // This code works only for 0-width border. | 175 // This code works only for 0-width border. |
176 // The scrollTop, clientHeight and scrollHeight are computed in double value
s internally. | 176 // The scrollTop, clientHeight and scrollHeight are computed in double value
s internally. |
177 // However, they are exposed to javascript differently, each being either ro
unded (via | 177 // However, they are exposed to javascript differently, each being either ro
unded (via |
178 // round, ceil or floor functions) or left intouch. | 178 // round, ceil or floor functions) or left intouch. |
179 // This adds up a total error up to 2. | 179 // This adds up a total error up to 2. |
180 return Math.abs(this.scrollTop + this.clientHeight - this.scrollHeight) <= 2
; | 180 return Math.abs(this.scrollTop + this.clientHeight - this.scrollHeight) <= 2
; |
181 } | 181 }; |
182 | 182 |
183 /** | 183 /** |
184 * @param {!Array.<string>} nameArray | 184 * @param {!Array.<string>} nameArray |
185 * @return {?Node} | 185 * @return {?Node} |
186 */ | 186 */ |
187 Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) | 187 Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) |
188 { | 188 { |
189 for (var node = this; node && node !== this.ownerDocument; node = node.paren
tNodeOrShadowHost()) { | 189 for (var node = this; node && node !== this.ownerDocument; node = node.paren
tNodeOrShadowHost()) { |
190 for (var i = 0; i < nameArray.length; ++i) { | 190 for (var i = 0; i < nameArray.length; ++i) { |
191 if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase()) | 191 if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase()) |
192 return node; | 192 return node; |
193 } | 193 } |
194 } | 194 } |
195 return null; | 195 return null; |
196 } | 196 }; |
197 | 197 |
198 /** | 198 /** |
199 * @param {string} nodeName | 199 * @param {string} nodeName |
200 * @return {?Node} | 200 * @return {?Node} |
201 */ | 201 */ |
202 Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName) | 202 Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName) |
203 { | 203 { |
204 return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]); | 204 return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]); |
205 } | 205 }; |
206 | 206 |
207 /** | 207 /** |
208 * @param {string} className | 208 * @param {string} className |
209 * @param {!Element=} stayWithin | 209 * @param {!Element=} stayWithin |
210 * @return {?Element} | 210 * @return {?Element} |
211 */ | 211 */ |
212 Node.prototype.enclosingNodeOrSelfWithClass = function(className, stayWithin) | 212 Node.prototype.enclosingNodeOrSelfWithClass = function(className, stayWithin) |
213 { | 213 { |
214 return this.enclosingNodeOrSelfWithClassList([className], stayWithin); | 214 return this.enclosingNodeOrSelfWithClassList([className], stayWithin); |
215 } | 215 }; |
216 | 216 |
217 /** | 217 /** |
218 * @param {!Array.<string>} classNames | 218 * @param {!Array.<string>} classNames |
219 * @param {!Element=} stayWithin | 219 * @param {!Element=} stayWithin |
220 * @return {?Element} | 220 * @return {?Element} |
221 */ | 221 */ |
222 Node.prototype.enclosingNodeOrSelfWithClassList = function(classNames, stayWithi
n) | 222 Node.prototype.enclosingNodeOrSelfWithClassList = function(classNames, stayWithi
n) |
223 { | 223 { |
224 for (var node = this; node && node !== stayWithin && node !== this.ownerDocu
ment; node = node.parentNodeOrShadowHost()) { | 224 for (var node = this; node && node !== stayWithin && node !== this.ownerDocu
ment; node = node.parentNodeOrShadowHost()) { |
225 if (node.nodeType === Node.ELEMENT_NODE) { | 225 if (node.nodeType === Node.ELEMENT_NODE) { |
226 var containsAll = true; | 226 var containsAll = true; |
227 for (var i = 0; i < classNames.length && containsAll; ++i) { | 227 for (var i = 0; i < classNames.length && containsAll; ++i) { |
228 if (!node.classList.contains(classNames[i])) | 228 if (!node.classList.contains(classNames[i])) |
229 containsAll = false; | 229 containsAll = false; |
230 } | 230 } |
231 if (containsAll) | 231 if (containsAll) |
232 return /** @type {!Element} */ (node); | 232 return /** @type {!Element} */ (node); |
233 } | 233 } |
234 } | 234 } |
235 return null; | 235 return null; |
236 } | 236 }; |
237 | 237 |
238 /** | 238 /** |
239 * @return {?Element} | 239 * @return {?Element} |
240 */ | 240 */ |
241 Node.prototype.parentElementOrShadowHost = function() | 241 Node.prototype.parentElementOrShadowHost = function() |
242 { | 242 { |
243 var node = this.parentNode; | 243 var node = this.parentNode; |
244 if (!node) | 244 if (!node) |
245 return null; | 245 return null; |
246 if (node.nodeType === Node.ELEMENT_NODE) | 246 if (node.nodeType === Node.ELEMENT_NODE) |
247 return /** @type {!Element} */ (node); | 247 return /** @type {!Element} */ (node); |
248 if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) | 248 if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) |
249 return /** @type {!Element} */ (node.host); | 249 return /** @type {!Element} */ (node.host); |
250 return null; | 250 return null; |
251 } | 251 }; |
252 | 252 |
253 /** | 253 /** |
254 * @return {?Node} | 254 * @return {?Node} |
255 */ | 255 */ |
256 Node.prototype.parentNodeOrShadowHost = function() | 256 Node.prototype.parentNodeOrShadowHost = function() |
257 { | 257 { |
258 return this.parentNode || this.host || null; | 258 return this.parentNode || this.host || null; |
259 } | 259 }; |
260 | 260 |
261 /** | 261 /** |
262 * @return {?Selection} | 262 * @return {?Selection} |
263 */ | 263 */ |
264 Node.prototype.getComponentSelection = function() | 264 Node.prototype.getComponentSelection = function() |
265 { | 265 { |
266 var parent = this.parentNode; | 266 var parent = this.parentNode; |
267 while (parent && parent.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) | 267 while (parent && parent.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) |
268 parent = parent.parentNode; | 268 parent = parent.parentNode; |
269 return parent instanceof ShadowRoot ? parent.getSelection() : this.window().
getSelection(); | 269 return parent instanceof ShadowRoot ? parent.getSelection() : this.window().
getSelection(); |
270 } | 270 }; |
271 | 271 |
272 | 272 |
273 /** | 273 /** |
274 * @return {boolean} | 274 * @return {boolean} |
275 */ | 275 */ |
276 Node.prototype.isComponentSelectionCollapsed = function() | 276 Node.prototype.isComponentSelectionCollapsed = function() |
277 { | 277 { |
278 // FIXME: crbug.com/447523, use selection.isCollapsed when it is fixed for s
hadow dom. | 278 // FIXME: crbug.com/447523, use selection.isCollapsed when it is fixed for s
hadow dom. |
279 var selection = this.getComponentSelection(); | 279 var selection = this.getComponentSelection(); |
280 var range = selection && selection.rangeCount ? selection.getRangeAt(0) : nu
ll; | 280 var range = selection && selection.rangeCount ? selection.getRangeAt(0) : nu
ll; |
281 return range ? range.collapsed : true; | 281 return range ? range.collapsed : true; |
282 } | 282 }; |
283 | 283 |
284 /** | 284 /** |
285 * @return {boolean} | 285 * @return {boolean} |
286 */ | 286 */ |
287 Node.prototype.hasSelection = function() | 287 Node.prototype.hasSelection = function() |
288 { | 288 { |
289 if (this.isComponentSelectionCollapsed()) | 289 if (this.isComponentSelectionCollapsed()) |
290 return false; | 290 return false; |
291 return this.getComponentSelection().containsNode(this, true); | 291 return this.getComponentSelection().containsNode(this, true); |
292 } | 292 }; |
293 | 293 |
294 /** | 294 /** |
295 * @return {!Selection} | 295 * @return {!Selection} |
296 */ | 296 */ |
297 Node.prototype.getDeepSelection = function() | 297 Node.prototype.getDeepSelection = function() |
298 { | 298 { |
299 var activeElement = this.ownerDocument.activeElement; | 299 var activeElement = this.ownerDocument.activeElement; |
300 var shadowRoot = null; | 300 var shadowRoot = null; |
301 while (activeElement && activeElement.shadowRoot) { | 301 while (activeElement && activeElement.shadowRoot) { |
302 shadowRoot = activeElement.shadowRoot; | 302 shadowRoot = activeElement.shadowRoot; |
303 activeElement = shadowRoot.activeElement; | 303 activeElement = shadowRoot.activeElement; |
304 } | 304 } |
305 | 305 |
306 return shadowRoot ? shadowRoot.getSelection() : this.window().getSelection()
; | 306 return shadowRoot ? shadowRoot.getSelection() : this.window().getSelection()
; |
307 } | 307 }; |
308 | 308 |
309 /** | 309 /** |
310 * @return {!Window} | 310 * @return {!Window} |
311 */ | 311 */ |
312 Node.prototype.window = function() | 312 Node.prototype.window = function() |
313 { | 313 { |
314 return this.ownerDocument.defaultView; | 314 return this.ownerDocument.defaultView; |
315 } | 315 }; |
316 | 316 |
317 Element.prototype.removeChildren = function() | 317 Element.prototype.removeChildren = function() |
318 { | 318 { |
319 if (this.firstChild) | 319 if (this.firstChild) |
320 this.textContent = ""; | 320 this.textContent = ""; |
321 } | 321 }; |
322 | 322 |
323 /** | 323 /** |
324 * @param {string} tagName | 324 * @param {string} tagName |
325 * @param {string=} customElementType | 325 * @param {string=} customElementType |
326 * @return {!Element} | 326 * @return {!Element} |
327 * @suppressGlobalPropertiesCheck | 327 * @suppressGlobalPropertiesCheck |
328 */ | 328 */ |
329 function createElement(tagName, customElementType) | 329 function createElement(tagName, customElementType) |
330 { | 330 { |
331 return document.createElement(tagName, customElementType || ""); | 331 return document.createElement(tagName, customElementType || ""); |
(...skipping 14 matching lines...) Expand all Loading... |
346 * @param {string=} className | 346 * @param {string=} className |
347 * @param {string=} customElementType | 347 * @param {string=} customElementType |
348 * @return {!Element} | 348 * @return {!Element} |
349 */ | 349 */ |
350 Document.prototype.createElementWithClass = function(elementName, className, cus
tomElementType) | 350 Document.prototype.createElementWithClass = function(elementName, className, cus
tomElementType) |
351 { | 351 { |
352 var element = this.createElement(elementName, customElementType || ""); | 352 var element = this.createElement(elementName, customElementType || ""); |
353 if (className) | 353 if (className) |
354 element.className = className; | 354 element.className = className; |
355 return element; | 355 return element; |
356 } | 356 }; |
357 | 357 |
358 /** | 358 /** |
359 * @param {string} elementName | 359 * @param {string} elementName |
360 * @param {string=} className | 360 * @param {string=} className |
361 * @param {string=} customElementType | 361 * @param {string=} customElementType |
362 * @return {!Element} | 362 * @return {!Element} |
363 * @suppressGlobalPropertiesCheck | 363 * @suppressGlobalPropertiesCheck |
364 */ | 364 */ |
365 function createElementWithClass(elementName, className, customElementType) | 365 function createElementWithClass(elementName, className, customElementType) |
366 { | 366 { |
367 return document.createElementWithClass(elementName, className, customElement
Type); | 367 return document.createElementWithClass(elementName, className, customElement
Type); |
368 } | 368 } |
369 | 369 |
370 /** | 370 /** |
371 * @param {string} childType | 371 * @param {string} childType |
372 * @param {string=} className | 372 * @param {string=} className |
373 * @return {!Element} | 373 * @return {!Element} |
374 */ | 374 */ |
375 Document.prototype.createSVGElement = function(childType, className) | 375 Document.prototype.createSVGElement = function(childType, className) |
376 { | 376 { |
377 var element = this.createElementNS("http://www.w3.org/2000/svg", childType); | 377 var element = this.createElementNS("http://www.w3.org/2000/svg", childType); |
378 if (className) | 378 if (className) |
379 element.setAttribute("class", className); | 379 element.setAttribute("class", className); |
380 return element; | 380 return element; |
381 } | 381 }; |
382 | 382 |
383 /** | 383 /** |
384 * @param {string} childType | 384 * @param {string} childType |
385 * @param {string=} className | 385 * @param {string=} className |
386 * @return {!Element} | 386 * @return {!Element} |
387 * @suppressGlobalPropertiesCheck | 387 * @suppressGlobalPropertiesCheck |
388 */ | 388 */ |
389 function createSVGElement(childType, className) | 389 function createSVGElement(childType, className) |
390 { | 390 { |
391 return document.createSVGElement(childType, className); | 391 return document.createSVGElement(childType, className); |
(...skipping 12 matching lines...) Expand all Loading... |
404 * @param {string} elementName | 404 * @param {string} elementName |
405 * @param {string=} className | 405 * @param {string=} className |
406 * @param {string=} customElementType | 406 * @param {string=} customElementType |
407 * @return {!Element} | 407 * @return {!Element} |
408 */ | 408 */ |
409 Element.prototype.createChild = function(elementName, className, customElementTy
pe) | 409 Element.prototype.createChild = function(elementName, className, customElementTy
pe) |
410 { | 410 { |
411 var element = this.ownerDocument.createElementWithClass(elementName, classNa
me, customElementType); | 411 var element = this.ownerDocument.createElementWithClass(elementName, classNa
me, customElementType); |
412 this.appendChild(element); | 412 this.appendChild(element); |
413 return element; | 413 return element; |
414 } | 414 }; |
415 | 415 |
416 DocumentFragment.prototype.createChild = Element.prototype.createChild; | 416 DocumentFragment.prototype.createChild = Element.prototype.createChild; |
417 | 417 |
418 /** | 418 /** |
419 * @param {string} text | 419 * @param {string} text |
420 * @return {!Text} | 420 * @return {!Text} |
421 */ | 421 */ |
422 Element.prototype.createTextChild = function(text) | 422 Element.prototype.createTextChild = function(text) |
423 { | 423 { |
424 var element = this.ownerDocument.createTextNode(text); | 424 var element = this.ownerDocument.createTextNode(text); |
425 this.appendChild(element); | 425 this.appendChild(element); |
426 return element; | 426 return element; |
427 } | 427 }; |
428 | 428 |
429 DocumentFragment.prototype.createTextChild = Element.prototype.createTextChild; | 429 DocumentFragment.prototype.createTextChild = Element.prototype.createTextChild; |
430 | 430 |
431 /** | 431 /** |
432 * @param {...string} var_args | 432 * @param {...string} var_args |
433 */ | 433 */ |
434 Element.prototype.createTextChildren = function(var_args) | 434 Element.prototype.createTextChildren = function(var_args) |
435 { | 435 { |
436 for (var i = 0, n = arguments.length; i < n; ++i) | 436 for (var i = 0, n = arguments.length; i < n; ++i) |
437 this.createTextChild(arguments[i]); | 437 this.createTextChild(arguments[i]); |
438 } | 438 }; |
439 | 439 |
440 DocumentFragment.prototype.createTextChildren = Element.prototype.createTextChil
dren; | 440 DocumentFragment.prototype.createTextChildren = Element.prototype.createTextChil
dren; |
441 | 441 |
442 /** | 442 /** |
443 * @return {number} | 443 * @return {number} |
444 */ | 444 */ |
445 Element.prototype.totalOffsetLeft = function() | 445 Element.prototype.totalOffsetLeft = function() |
446 { | 446 { |
447 return this.totalOffset().left; | 447 return this.totalOffset().left; |
448 } | 448 }; |
449 | 449 |
450 /** | 450 /** |
451 * @return {number} | 451 * @return {number} |
452 */ | 452 */ |
453 Element.prototype.totalOffsetTop = function() | 453 Element.prototype.totalOffsetTop = function() |
454 { | 454 { |
455 return this.totalOffset().top; | 455 return this.totalOffset().top; |
456 } | 456 }; |
457 | 457 |
458 /** | 458 /** |
459 * @return {!{left: number, top: number}} | 459 * @return {!{left: number, top: number}} |
460 */ | 460 */ |
461 Element.prototype.totalOffset = function() | 461 Element.prototype.totalOffset = function() |
462 { | 462 { |
463 var rect = this.getBoundingClientRect(); | 463 var rect = this.getBoundingClientRect(); |
464 return { left: rect.left, top: rect.top }; | 464 return { left: rect.left, top: rect.top }; |
465 } | 465 }; |
466 | 466 |
467 /** | 467 /** |
468 * @param {string} childType | 468 * @param {string} childType |
469 * @param {string=} className | 469 * @param {string=} className |
470 * @return {!Element} | 470 * @return {!Element} |
471 */ | 471 */ |
472 Element.prototype.createSVGChild = function(childType, className) | 472 Element.prototype.createSVGChild = function(childType, className) |
473 { | 473 { |
474 var child = this.ownerDocument.createSVGElement(childType, className); | 474 var child = this.ownerDocument.createSVGElement(childType, className); |
475 this.appendChild(child); | 475 this.appendChild(child); |
476 return child; | 476 return child; |
477 } | 477 }; |
478 | 478 |
479 /** | 479 /** |
480 * @constructor | 480 * @constructor |
481 * @param {number=} x | 481 * @param {number=} x |
482 * @param {number=} y | 482 * @param {number=} y |
483 * @param {number=} width | 483 * @param {number=} width |
484 * @param {number=} height | 484 * @param {number=} height |
485 */ | 485 */ |
486 function AnchorBox(x, y, width, height) | 486 function AnchorBox(x, y, width, height) |
487 { | 487 { |
488 this.x = x || 0; | 488 this.x = x || 0; |
489 this.y = y || 0; | 489 this.y = y || 0; |
490 this.width = width || 0; | 490 this.width = width || 0; |
491 this.height = height || 0; | 491 this.height = height || 0; |
492 } | 492 } |
493 | 493 |
494 /** | 494 /** |
495 * @param {!AnchorBox} box | 495 * @param {!AnchorBox} box |
496 * @return {!AnchorBox} | 496 * @return {!AnchorBox} |
497 */ | 497 */ |
498 AnchorBox.prototype.relativeTo = function(box) | 498 AnchorBox.prototype.relativeTo = function(box) |
499 { | 499 { |
500 return new AnchorBox( | 500 return new AnchorBox( |
501 this.x - box.x, this.y - box.y, this.width, this.height); | 501 this.x - box.x, this.y - box.y, this.width, this.height); |
502 } | 502 }; |
503 | 503 |
504 /** | 504 /** |
505 * @param {!Element} element | 505 * @param {!Element} element |
506 * @return {!AnchorBox} | 506 * @return {!AnchorBox} |
507 */ | 507 */ |
508 AnchorBox.prototype.relativeToElement = function(element) | 508 AnchorBox.prototype.relativeToElement = function(element) |
509 { | 509 { |
510 return this.relativeTo(element.boxInWindow(element.ownerDocument.defaultView
)); | 510 return this.relativeTo(element.boxInWindow(element.ownerDocument.defaultView
)); |
511 } | 511 }; |
512 | 512 |
513 /** | 513 /** |
514 * @param {?AnchorBox} anchorBox | 514 * @param {?AnchorBox} anchorBox |
515 * @return {boolean} | 515 * @return {boolean} |
516 */ | 516 */ |
517 AnchorBox.prototype.equals = function(anchorBox) | 517 AnchorBox.prototype.equals = function(anchorBox) |
518 { | 518 { |
519 return !!anchorBox && this.x === anchorBox.x && this.y === anchorBox.y && th
is.width === anchorBox.width && this.height === anchorBox.height; | 519 return !!anchorBox && this.x === anchorBox.x && this.y === anchorBox.y && th
is.width === anchorBox.width && this.height === anchorBox.height; |
520 } | 520 }; |
521 | 521 |
522 /** | 522 /** |
523 * @param {!Window=} targetWindow | 523 * @param {!Window=} targetWindow |
524 * @return {!AnchorBox} | 524 * @return {!AnchorBox} |
525 */ | 525 */ |
526 Element.prototype.boxInWindow = function(targetWindow) | 526 Element.prototype.boxInWindow = function(targetWindow) |
527 { | 527 { |
528 targetWindow = targetWindow || this.ownerDocument.defaultView; | 528 targetWindow = targetWindow || this.ownerDocument.defaultView; |
529 | 529 |
530 var anchorBox = new AnchorBox(); | 530 var anchorBox = new AnchorBox(); |
531 var curElement = this; | 531 var curElement = this; |
532 var curWindow = this.ownerDocument.defaultView; | 532 var curWindow = this.ownerDocument.defaultView; |
533 while (curWindow && curElement) { | 533 while (curWindow && curElement) { |
534 anchorBox.x += curElement.totalOffsetLeft(); | 534 anchorBox.x += curElement.totalOffsetLeft(); |
535 anchorBox.y += curElement.totalOffsetTop(); | 535 anchorBox.y += curElement.totalOffsetTop(); |
536 if (curWindow === targetWindow) | 536 if (curWindow === targetWindow) |
537 break; | 537 break; |
538 curElement = curWindow.frameElement; | 538 curElement = curWindow.frameElement; |
539 curWindow = curWindow.parent; | 539 curWindow = curWindow.parent; |
540 } | 540 } |
541 | 541 |
542 anchorBox.width = Math.min(this.offsetWidth, targetWindow.innerWidth - ancho
rBox.x); | 542 anchorBox.width = Math.min(this.offsetWidth, targetWindow.innerWidth - ancho
rBox.x); |
543 anchorBox.height = Math.min(this.offsetHeight, targetWindow.innerHeight - an
chorBox.y); | 543 anchorBox.height = Math.min(this.offsetHeight, targetWindow.innerHeight - an
chorBox.y); |
544 return anchorBox; | 544 return anchorBox; |
545 } | 545 }; |
546 | 546 |
547 /** | 547 /** |
548 * @param {boolean=} preventDefault | 548 * @param {boolean=} preventDefault |
549 */ | 549 */ |
550 Event.prototype.consume = function(preventDefault) | 550 Event.prototype.consume = function(preventDefault) |
551 { | 551 { |
552 this.stopImmediatePropagation(); | 552 this.stopImmediatePropagation(); |
553 if (preventDefault) | 553 if (preventDefault) |
554 this.preventDefault(); | 554 this.preventDefault(); |
555 this.handled = true; | 555 this.handled = true; |
556 } | 556 }; |
557 | 557 |
558 /** | 558 /** |
559 * @param {number=} start | 559 * @param {number=} start |
560 * @param {number=} end | 560 * @param {number=} end |
561 * @return {!Text} | 561 * @return {!Text} |
562 */ | 562 */ |
563 Text.prototype.select = function(start, end) | 563 Text.prototype.select = function(start, end) |
564 { | 564 { |
565 start = start || 0; | 565 start = start || 0; |
566 end = end || this.textContent.length; | 566 end = end || this.textContent.length; |
567 | 567 |
568 if (start < 0) | 568 if (start < 0) |
569 start = end + start; | 569 start = end + start; |
570 | 570 |
571 var selection = this.getComponentSelection(); | 571 var selection = this.getComponentSelection(); |
572 selection.removeAllRanges(); | 572 selection.removeAllRanges(); |
573 var range = this.ownerDocument.createRange(); | 573 var range = this.ownerDocument.createRange(); |
574 range.setStart(this, start); | 574 range.setStart(this, start); |
575 range.setEnd(this, end); | 575 range.setEnd(this, end); |
576 selection.addRange(range); | 576 selection.addRange(range); |
577 return this; | 577 return this; |
578 } | 578 }; |
579 | 579 |
580 /** | 580 /** |
581 * @return {?number} | 581 * @return {?number} |
582 */ | 582 */ |
583 Element.prototype.selectionLeftOffset = function() | 583 Element.prototype.selectionLeftOffset = function() |
584 { | 584 { |
585 // Calculate selection offset relative to the current element. | 585 // Calculate selection offset relative to the current element. |
586 | 586 |
587 var selection = this.getComponentSelection(); | 587 var selection = this.getComponentSelection(); |
588 if (!selection.containsNode(this, true)) | 588 if (!selection.containsNode(this, true)) |
589 return null; | 589 return null; |
590 | 590 |
591 var leftOffset = selection.anchorOffset; | 591 var leftOffset = selection.anchorOffset; |
592 var node = selection.anchorNode; | 592 var node = selection.anchorNode; |
593 | 593 |
594 while (node !== this) { | 594 while (node !== this) { |
595 while (node.previousSibling) { | 595 while (node.previousSibling) { |
596 node = node.previousSibling; | 596 node = node.previousSibling; |
597 leftOffset += node.textContent.length; | 597 leftOffset += node.textContent.length; |
598 } | 598 } |
599 node = node.parentNodeOrShadowHost(); | 599 node = node.parentNodeOrShadowHost(); |
600 } | 600 } |
601 | 601 |
602 return leftOffset; | 602 return leftOffset; |
603 } | 603 }; |
604 | 604 |
605 /** | 605 /** |
606 * @param {...!Node} var_args | 606 * @param {...!Node} var_args |
607 */ | 607 */ |
608 Node.prototype.appendChildren = function(var_args) | 608 Node.prototype.appendChildren = function(var_args) |
609 { | 609 { |
610 for (var i = 0, n = arguments.length; i < n; ++i) | 610 for (var i = 0, n = arguments.length; i < n; ++i) |
611 this.appendChild(arguments[i]); | 611 this.appendChild(arguments[i]); |
612 } | 612 }; |
613 | 613 |
614 /** | 614 /** |
615 * @return {string} | 615 * @return {string} |
616 */ | 616 */ |
617 Node.prototype.deepTextContent = function() | 617 Node.prototype.deepTextContent = function() |
618 { | 618 { |
619 return this.childTextNodes().map(function(node) { return node.textContent; }
).join(""); | 619 return this.childTextNodes().map(function(node) { return node.textContent; }
).join(""); |
620 } | 620 }; |
621 | 621 |
622 /** | 622 /** |
623 * @return {!Array.<!Node>} | 623 * @return {!Array.<!Node>} |
624 */ | 624 */ |
625 Node.prototype.childTextNodes = function() | 625 Node.prototype.childTextNodes = function() |
626 { | 626 { |
627 var node = this.traverseNextTextNode(this); | 627 var node = this.traverseNextTextNode(this); |
628 var result = []; | 628 var result = []; |
629 var nonTextTags = { "STYLE": 1, "SCRIPT": 1 }; | 629 var nonTextTags = { "STYLE": 1, "SCRIPT": 1 }; |
630 while (node) { | 630 while (node) { |
631 if (!nonTextTags[node.parentElement.nodeName]) | 631 if (!nonTextTags[node.parentElement.nodeName]) |
632 result.push(node); | 632 result.push(node); |
633 node = node.traverseNextTextNode(this); | 633 node = node.traverseNextTextNode(this); |
634 } | 634 } |
635 return result; | 635 return result; |
636 } | 636 }; |
637 | 637 |
638 /** | 638 /** |
639 * @param {?Node} node | 639 * @param {?Node} node |
640 * @return {boolean} | 640 * @return {boolean} |
641 */ | 641 */ |
642 Node.prototype.isAncestor = function(node) | 642 Node.prototype.isAncestor = function(node) |
643 { | 643 { |
644 if (!node) | 644 if (!node) |
645 return false; | 645 return false; |
646 | 646 |
647 var currentNode = node.parentNodeOrShadowHost(); | 647 var currentNode = node.parentNodeOrShadowHost(); |
648 while (currentNode) { | 648 while (currentNode) { |
649 if (this === currentNode) | 649 if (this === currentNode) |
650 return true; | 650 return true; |
651 currentNode = currentNode.parentNodeOrShadowHost(); | 651 currentNode = currentNode.parentNodeOrShadowHost(); |
652 } | 652 } |
653 return false; | 653 return false; |
654 } | 654 }; |
655 | 655 |
656 /** | 656 /** |
657 * @param {?Node} descendant | 657 * @param {?Node} descendant |
658 * @return {boolean} | 658 * @return {boolean} |
659 */ | 659 */ |
660 Node.prototype.isDescendant = function(descendant) | 660 Node.prototype.isDescendant = function(descendant) |
661 { | 661 { |
662 return !!descendant && descendant.isAncestor(this); | 662 return !!descendant && descendant.isAncestor(this); |
663 } | 663 }; |
664 | 664 |
665 /** | 665 /** |
666 * @param {?Node} node | 666 * @param {?Node} node |
667 * @return {boolean} | 667 * @return {boolean} |
668 */ | 668 */ |
669 Node.prototype.isSelfOrAncestor = function(node) | 669 Node.prototype.isSelfOrAncestor = function(node) |
670 { | 670 { |
671 return !!node && (node === this || this.isAncestor(node)); | 671 return !!node && (node === this || this.isAncestor(node)); |
672 } | 672 }; |
673 | 673 |
674 /** | 674 /** |
675 * @param {?Node} node | 675 * @param {?Node} node |
676 * @return {boolean} | 676 * @return {boolean} |
677 */ | 677 */ |
678 Node.prototype.isSelfOrDescendant = function(node) | 678 Node.prototype.isSelfOrDescendant = function(node) |
679 { | 679 { |
680 return !!node && (node === this || this.isDescendant(node)); | 680 return !!node && (node === this || this.isDescendant(node)); |
681 } | 681 }; |
682 | 682 |
683 /** | 683 /** |
684 * @param {!Node=} stayWithin | 684 * @param {!Node=} stayWithin |
685 * @return {?Node} | 685 * @return {?Node} |
686 */ | 686 */ |
687 Node.prototype.traverseNextNode = function(stayWithin) | 687 Node.prototype.traverseNextNode = function(stayWithin) |
688 { | 688 { |
689 if (this.shadowRoot) | 689 if (this.shadowRoot) |
690 return this.shadowRoot; | 690 return this.shadowRoot; |
691 | 691 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 * @param {!Node} node | 730 * @param {!Node} node |
731 * @return {?Node} | 731 * @return {?Node} |
732 */ | 732 */ |
733 function insertionPoint(node) | 733 function insertionPoint(node) |
734 { | 734 { |
735 var insertionPoints = node.getDestinationInsertionPoints ? node.getDes
tinationInsertionPoints() : []; | 735 var insertionPoints = node.getDestinationInsertionPoints ? node.getDes
tinationInsertionPoints() : []; |
736 return insertionPoints.length > 0 ? insertionPoints[insertionPoints.leng
th - 1] : null; | 736 return insertionPoints.length > 0 ? insertionPoints[insertionPoints.leng
th - 1] : null; |
737 } | 737 } |
738 | 738 |
739 return null; | 739 return null; |
740 } | 740 }; |
741 | 741 |
742 /** | 742 /** |
743 * @param {!Node=} stayWithin | 743 * @param {!Node=} stayWithin |
744 * @return {?Node} | 744 * @return {?Node} |
745 */ | 745 */ |
746 Node.prototype.traversePreviousNode = function(stayWithin) | 746 Node.prototype.traversePreviousNode = function(stayWithin) |
747 { | 747 { |
748 if (stayWithin && this === stayWithin) | 748 if (stayWithin && this === stayWithin) |
749 return null; | 749 return null; |
750 var node = this.previousSibling; | 750 var node = this.previousSibling; |
751 while (node && node.lastChild) | 751 while (node && node.lastChild) |
752 node = node.lastChild; | 752 node = node.lastChild; |
753 if (node) | 753 if (node) |
754 return node; | 754 return node; |
755 return this.parentNodeOrShadowHost(); | 755 return this.parentNodeOrShadowHost(); |
756 } | 756 }; |
757 | 757 |
758 /** | 758 /** |
759 * @param {*} text | 759 * @param {*} text |
760 * @param {string=} placeholder | 760 * @param {string=} placeholder |
761 * @return {boolean} true if was truncated | 761 * @return {boolean} true if was truncated |
762 */ | 762 */ |
763 Node.prototype.setTextContentTruncatedIfNeeded = function(text, placeholder) | 763 Node.prototype.setTextContentTruncatedIfNeeded = function(text, placeholder) |
764 { | 764 { |
765 // Huge texts in the UI reduce rendering performance drastically. | 765 // Huge texts in the UI reduce rendering performance drastically. |
766 // Moreover, Blink/WebKit uses <unsigned short> internally for storing text
content | 766 // Moreover, Blink/WebKit uses <unsigned short> internally for storing text
content |
767 // length, so texts longer than 65535 are inherently displayed incorrectly. | 767 // length, so texts longer than 65535 are inherently displayed incorrectly. |
768 const maxTextContentLength = 10000; | 768 const maxTextContentLength = 10000; |
769 | 769 |
770 if (typeof text === "string" && text.length > maxTextContentLength) { | 770 if (typeof text === "string" && text.length > maxTextContentLength) { |
771 this.textContent = typeof placeholder === "string" ? placeholder : text.
trimMiddle(maxTextContentLength); | 771 this.textContent = typeof placeholder === "string" ? placeholder : text.
trimMiddle(maxTextContentLength); |
772 return true; | 772 return true; |
773 } | 773 } |
774 | 774 |
775 this.textContent = text; | 775 this.textContent = text; |
776 return false; | 776 return false; |
777 } | 777 }; |
778 | 778 |
779 /** | 779 /** |
780 * @return {?Node} | 780 * @return {?Node} |
781 */ | 781 */ |
782 Event.prototype.deepElementFromPoint = function() | 782 Event.prototype.deepElementFromPoint = function() |
783 { | 783 { |
784 var root = this.target && this.target.getComponentRoot(); | 784 var root = this.target && this.target.getComponentRoot(); |
785 return root ? root.deepElementFromPoint(this.pageX, this.pageY) : null; | 785 return root ? root.deepElementFromPoint(this.pageX, this.pageY) : null; |
786 } | 786 }; |
787 | 787 |
788 /** | 788 /** |
789 * @param {number} x | 789 * @param {number} x |
790 * @param {number} y | 790 * @param {number} y |
791 * @return {?Node} | 791 * @return {?Node} |
792 */ | 792 */ |
793 Document.prototype.deepElementFromPoint = function(x, y) | 793 Document.prototype.deepElementFromPoint = function(x, y) |
794 { | 794 { |
795 var node = this.elementFromPoint(x, y); | 795 var node = this.elementFromPoint(x, y); |
796 while (node && node.shadowRoot) | 796 while (node && node.shadowRoot) |
797 node = node.shadowRoot.elementFromPoint(x, y); | 797 node = node.shadowRoot.elementFromPoint(x, y); |
798 return node; | 798 return node; |
799 } | 799 }; |
800 | 800 |
801 DocumentFragment.prototype.deepElementFromPoint = Document.prototype.deepElement
FromPoint; | 801 DocumentFragment.prototype.deepElementFromPoint = Document.prototype.deepElement
FromPoint; |
802 | 802 |
803 /** | 803 /** |
804 * @return {?Element} | 804 * @return {?Element} |
805 */ | 805 */ |
806 Document.prototype.deepActiveElement = function() | 806 Document.prototype.deepActiveElement = function() |
807 { | 807 { |
808 var activeElement = this.activeElement; | 808 var activeElement = this.activeElement; |
809 while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot
.activeElement) | 809 while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot
.activeElement) |
810 activeElement = activeElement.shadowRoot.activeElement; | 810 activeElement = activeElement.shadowRoot.activeElement; |
811 return activeElement; | 811 return activeElement; |
812 } | 812 }; |
813 | 813 |
814 DocumentFragment.prototype.deepActiveElement = Document.prototype.deepActiveElem
ent; | 814 DocumentFragment.prototype.deepActiveElement = Document.prototype.deepActiveElem
ent; |
815 | 815 |
816 /** | 816 /** |
817 * @return {boolean} | 817 * @return {boolean} |
818 */ | 818 */ |
819 Element.prototype.hasFocus = function() | 819 Element.prototype.hasFocus = function() |
820 { | 820 { |
821 var root = this.getComponentRoot(); | 821 var root = this.getComponentRoot(); |
822 return !!root && this.isSelfOrAncestor(root.activeElement); | 822 return !!root && this.isSelfOrAncestor(root.activeElement); |
823 } | 823 }; |
824 | 824 |
825 /** | 825 /** |
826 * @return {?Document|?DocumentFragment} | 826 * @return {?Document|?DocumentFragment} |
827 */ | 827 */ |
828 Node.prototype.getComponentRoot = function() | 828 Node.prototype.getComponentRoot = function() |
829 { | 829 { |
830 var node = this; | 830 var node = this; |
831 while (node && node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE && node.nodeTyp
e !== Node.DOCUMENT_NODE) | 831 while (node && node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE && node.nodeTyp
e !== Node.DOCUMENT_NODE) |
832 node = node.parentNode; | 832 node = node.parentNode; |
833 return /** @type {?Document|?DocumentFragment} */ (node); | 833 return /** @type {?Document|?DocumentFragment} */ (node); |
834 } | 834 }; |
835 | 835 |
836 /** | 836 /** |
837 * @param {!Event} event | 837 * @param {!Event} event |
838 * @return {boolean} | 838 * @return {boolean} |
839 */ | 839 */ |
840 function isEnterKey(event) | 840 function isEnterKey(event) |
841 { | 841 { |
842 // Check if in IME. | 842 // Check if in IME. |
843 return event.keyCode !== 229 && event.key === "Enter"; | 843 return event.keyCode !== 229 && event.key === "Enter"; |
844 } | 844 } |
(...skipping 20 matching lines...) Expand all Loading... |
865 { | 865 { |
866 window.removeEventListener("DOMContentLoaded", windowLoaded, false); | 866 window.removeEventListener("DOMContentLoaded", windowLoaded, false); |
867 callback(); | 867 callback(); |
868 } | 868 } |
869 | 869 |
870 if (document.readyState === "complete" || document.readyState === "interacti
ve") | 870 if (document.readyState === "complete" || document.readyState === "interacti
ve") |
871 callback(); | 871 callback(); |
872 else | 872 else |
873 window.addEventListener("DOMContentLoaded", windowLoaded, false); | 873 window.addEventListener("DOMContentLoaded", windowLoaded, false); |
874 } | 874 } |
OLD | NEW |