Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(626)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/platform/DOMExtension.js

Issue 2611843010: DevTools: move DOMExtension.js into ui module. (Closed)
Patch Set: Introduce progress monitor Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Google Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contains diff method based on Javascript Diff Algorithm By John Resig
30 * http://ejohn.org/files/jsdiff.js (released under the MIT license).
31 */
32 /**
33 * @param {number} offset
34 * @param {string} stopCharacters
35 * @param {!Node} stayWithinNode
36 * @param {string=} direction
37 * @return {!Range}
38 */
39 Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, di rection) {
40 var startNode;
41 var startOffset = 0;
42 var endNode;
43 var endOffset = 0;
44
45 if (!stayWithinNode)
46 stayWithinNode = this;
47
48 if (!direction || direction === 'backward' || direction === 'both') {
49 var node = this;
50 while (node) {
51 if (node === stayWithinNode) {
52 if (!startNode)
53 startNode = stayWithinNode;
54 break;
55 }
56
57 if (node.nodeType === Node.TEXT_NODE) {
58 var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1)) ;
59 for (var i = start; i >= 0; --i) {
60 if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
61 startNode = node;
62 startOffset = i + 1;
63 break;
64 }
65 }
66 }
67
68 if (startNode)
69 break;
70
71 node = node.traversePreviousNode(stayWithinNode);
72 }
73
74 if (!startNode) {
75 startNode = stayWithinNode;
76 startOffset = 0;
77 }
78 } else {
79 startNode = this;
80 startOffset = offset;
81 }
82
83 if (!direction || direction === 'forward' || direction === 'both') {
84 node = this;
85 while (node) {
86 if (node === stayWithinNode) {
87 if (!endNode)
88 endNode = stayWithinNode;
89 break;
90 }
91
92 if (node.nodeType === Node.TEXT_NODE) {
93 var start = (node === this ? offset : 0);
94 for (var i = start; i < node.nodeValue.length; ++i) {
95 if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
96 endNode = node;
97 endOffset = i;
98 break;
99 }
100 }
101 }
102
103 if (endNode)
104 break;
105
106 node = node.traverseNextNode(stayWithinNode);
107 }
108
109 if (!endNode) {
110 endNode = stayWithinNode;
111 endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.no deValue.length :
112 stayWithinNode.ch ildNodes.length;
113 }
114 } else {
115 endNode = this;
116 endOffset = offset;
117 }
118
119 var result = this.ownerDocument.createRange();
120 result.setStart(startNode, startOffset);
121 result.setEnd(endNode, endOffset);
122
123 return result;
124 };
125
126 /**
127 * @param {!Node=} stayWithin
128 * @return {?Node}
129 */
130 Node.prototype.traverseNextTextNode = function(stayWithin) {
131 var node = this.traverseNextNode(stayWithin);
132 if (!node)
133 return null;
134 var nonTextTags = {'STYLE': 1, 'SCRIPT': 1};
135 while (node && (node.nodeType !== Node.TEXT_NODE || nonTextTags[node.parentEle ment.nodeName]))
136 node = node.traverseNextNode(stayWithin);
137
138 return node;
139 };
140
141 /**
142 * @param {number|undefined} x
143 * @param {number|undefined} y
144 * @param {!Element=} relativeTo
145 */
146 Element.prototype.positionAt = function(x, y, relativeTo) {
147 var shift = {x: 0, y: 0};
148 if (relativeTo)
149 shift = relativeTo.boxInWindow(this.ownerDocument.defaultView);
150
151 if (typeof x === 'number')
152 this.style.setProperty('left', (shift.x + x) + 'px');
153 else
154 this.style.removeProperty('left');
155
156 if (typeof y === 'number')
157 this.style.setProperty('top', (shift.y + y) + 'px');
158 else
159 this.style.removeProperty('top');
160
161 if (typeof x === 'number' || typeof y === 'number')
162 this.style.setProperty('position', 'absolute');
163 else
164 this.style.removeProperty('position');
165 };
166
167 /**
168 * @return {boolean}
169 */
170 Element.prototype.isScrolledToBottom = function() {
171 // This code works only for 0-width border.
172 // The scrollTop, clientHeight and scrollHeight are computed in double values internally.
173 // However, they are exposed to javascript differently, each being either roun ded (via
174 // round, ceil or floor functions) or left intouch.
175 // This adds up a total error up to 2.
176 return Math.abs(this.scrollTop + this.clientHeight - this.scrollHeight) <= 2;
177 };
178
179 /**
180 * @param {!Array.<string>} nameArray
181 * @return {?Node}
182 */
183 Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) {
184 for (var node = this; node && node !== this.ownerDocument; node = node.parentN odeOrShadowHost()) {
185 for (var i = 0; i < nameArray.length; ++i) {
186 if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
187 return node;
188 }
189 }
190 return null;
191 };
192
193 /**
194 * @param {string} nodeName
195 * @return {?Node}
196 */
197 Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName) {
198 return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]);
199 };
200
201 /**
202 * @param {string} className
203 * @param {!Element=} stayWithin
204 * @return {?Element}
205 */
206 Node.prototype.enclosingNodeOrSelfWithClass = function(className, stayWithin) {
207 return this.enclosingNodeOrSelfWithClassList([className], stayWithin);
208 };
209
210 /**
211 * @param {!Array.<string>} classNames
212 * @param {!Element=} stayWithin
213 * @return {?Element}
214 */
215 Node.prototype.enclosingNodeOrSelfWithClassList = function(classNames, stayWithi n) {
216 for (var node = this; node && node !== stayWithin && node !== this.ownerDocume nt;
217 node = node.parentNodeOrShadowHost()) {
218 if (node.nodeType === Node.ELEMENT_NODE) {
219 var containsAll = true;
220 for (var i = 0; i < classNames.length && containsAll; ++i) {
221 if (!node.classList.contains(classNames[i]))
222 containsAll = false;
223 }
224 if (containsAll)
225 return /** @type {!Element} */ (node);
226 }
227 }
228 return null;
229 };
230
231 /**
232 * @return {?Element}
233 */
234 Node.prototype.parentElementOrShadowHost = function() {
235 var node = this.parentNode;
236 if (!node)
237 return null;
238 if (node.nodeType === Node.ELEMENT_NODE)
239 return /** @type {!Element} */ (node);
240 if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE)
241 return /** @type {!Element} */ (node.host);
242 return null;
243 };
244
245 /**
246 * @return {?Node}
247 */
248 Node.prototype.parentNodeOrShadowHost = function() {
249 if (this.parentNode)
250 return this.parentNode;
251 if (this.nodeType === Node.DOCUMENT_FRAGMENT_NODE && this.host)
252 return this.host;
253 return null;
254 };
255
256 /**
257 * @return {?Selection}
258 */
259 Node.prototype.getComponentSelection = function() {
260 var parent = this.parentNode;
261 while (parent && parent.nodeType !== Node.DOCUMENT_FRAGMENT_NODE)
262 parent = parent.parentNode;
263 return parent instanceof ShadowRoot ? parent.getSelection() : this.window().ge tSelection();
264 };
265
266 /**
267 * @return {boolean}
268 */
269 Node.prototype.isComponentSelectionCollapsed = function() {
270 // FIXME: crbug.com/447523, use selection.isCollapsed when it is fixed for sha dow dom.
271 var selection = this.getComponentSelection();
272 var range = selection && selection.rangeCount ? selection.getRangeAt(0) : null ;
273 return range ? range.collapsed : true;
274 };
275
276 /**
277 * @return {boolean}
278 */
279 Node.prototype.hasSelection = function() {
280 // TODO(luoe): use contains(node, {includeShadow: true}) when it is fixed for shadow dom.
281 var contents = this.querySelectorAll('content');
282 for (var content of contents) {
283 if (Array.prototype.some.call(content.getDistributedNodes(), node => node.ha sSelection()))
284 return true;
285 }
286 if (this.isComponentSelectionCollapsed())
287 return false;
288 return this.getComponentSelection().containsNode(this, true);
289 };
290
291 /**
292 * @return {!Selection}
293 */
294 Node.prototype.getDeepSelection = function() {
295 var activeElement = this.ownerDocument.activeElement;
296 var shadowRoot = null;
297 while (activeElement && activeElement.shadowRoot) {
298 shadowRoot = activeElement.shadowRoot;
299 activeElement = shadowRoot.activeElement;
300 }
301
302 return shadowRoot ? shadowRoot.getSelection() : this.window().getSelection();
303 };
304
305 /**
306 * @return {!Window}
307 */
308 Node.prototype.window = function() {
309 return this.ownerDocument.defaultView;
310 };
311
312 Element.prototype.removeChildren = function() {
313 if (this.firstChild)
314 this.textContent = '';
315 };
316
317 /**
318 * @param {string} tagName
319 * @param {string=} customElementType
320 * @return {!Element}
321 * @suppressGlobalPropertiesCheck
322 */
323 function createElement(tagName, customElementType) {
324 return document.createElement(tagName, customElementType || '');
325 }
326
327 /**
328 * @param {number|string} data
329 * @return {!Text}
330 * @suppressGlobalPropertiesCheck
331 */
332 function createTextNode(data) {
333 return document.createTextNode(data);
334 }
335
336 /**
337 * @param {string} elementName
338 * @param {string=} className
339 * @param {string=} customElementType
340 * @return {!Element}
341 */
342 Document.prototype.createElementWithClass = function(elementName, className, cus tomElementType) {
343 var element = this.createElement(elementName, customElementType || '');
344 if (className)
345 element.className = className;
346 return element;
347 };
348
349 /**
350 * @param {string} elementName
351 * @param {string=} className
352 * @param {string=} customElementType
353 * @return {!Element}
354 * @suppressGlobalPropertiesCheck
355 */
356 function createElementWithClass(elementName, className, customElementType) {
357 return document.createElementWithClass(elementName, className, customElementTy pe);
358 }
359
360 /**
361 * @param {string} childType
362 * @param {string=} className
363 * @return {!Element}
364 */
365 Document.prototype.createSVGElement = function(childType, className) {
366 var element = this.createElementNS('http://www.w3.org/2000/svg', childType);
367 if (className)
368 element.setAttribute('class', className);
369 return element;
370 };
371
372 /**
373 * @param {string} childType
374 * @param {string=} className
375 * @return {!Element}
376 * @suppressGlobalPropertiesCheck
377 */
378 function createSVGElement(childType, className) {
379 return document.createSVGElement(childType, className);
380 }
381
382 /**
383 * @return {!DocumentFragment}
384 * @suppressGlobalPropertiesCheck
385 */
386 function createDocumentFragment() {
387 return document.createDocumentFragment();
388 }
389
390 /**
391 * @param {string} elementName
392 * @param {string=} className
393 * @param {string=} customElementType
394 * @return {!Element}
395 */
396 Element.prototype.createChild = function(elementName, className, customElementTy pe) {
397 var element = this.ownerDocument.createElementWithClass(elementName, className , customElementType);
398 this.appendChild(element);
399 return element;
400 };
401
402 DocumentFragment.prototype.createChild = Element.prototype.createChild;
403
404 /**
405 * @param {string} text
406 * @return {!Text}
407 */
408 Element.prototype.createTextChild = function(text) {
409 var element = this.ownerDocument.createTextNode(text);
410 this.appendChild(element);
411 return element;
412 };
413
414 DocumentFragment.prototype.createTextChild = Element.prototype.createTextChild;
415
416 /**
417 * @param {...string} var_args
418 */
419 Element.prototype.createTextChildren = function(var_args) {
420 for (var i = 0, n = arguments.length; i < n; ++i)
421 this.createTextChild(arguments[i]);
422 };
423
424 DocumentFragment.prototype.createTextChildren = Element.prototype.createTextChil dren;
425
426 /**
427 * @return {number}
428 */
429 Element.prototype.totalOffsetLeft = function() {
430 return this.totalOffset().left;
431 };
432
433 /**
434 * @return {number}
435 */
436 Element.prototype.totalOffsetTop = function() {
437 return this.totalOffset().top;
438 };
439
440 /**
441 * @return {!{left: number, top: number}}
442 */
443 Element.prototype.totalOffset = function() {
444 var rect = this.getBoundingClientRect();
445 return {left: rect.left, top: rect.top};
446 };
447
448 /**
449 * @param {string} childType
450 * @param {string=} className
451 * @return {!Element}
452 */
453 Element.prototype.createSVGChild = function(childType, className) {
454 var child = this.ownerDocument.createSVGElement(childType, className);
455 this.appendChild(child);
456 return child;
457 };
458
459 /**
460 * @unrestricted
461 */
462 var AnchorBox = class {
463 /**
464 * @param {number=} x
465 * @param {number=} y
466 * @param {number=} width
467 * @param {number=} height
468 */
469 constructor(x, y, width, height) {
470 this.x = x || 0;
471 this.y = y || 0;
472 this.width = width || 0;
473 this.height = height || 0;
474 }
475 };
476
477 /**
478 * @param {!AnchorBox} box
479 * @return {!AnchorBox}
480 */
481 AnchorBox.prototype.relativeTo = function(box) {
482 return new AnchorBox(this.x - box.x, this.y - box.y, this.width, this.height);
483 };
484
485 /**
486 * @param {!Element} element
487 * @return {!AnchorBox}
488 */
489 AnchorBox.prototype.relativeToElement = function(element) {
490 return this.relativeTo(element.boxInWindow(element.ownerDocument.defaultView)) ;
491 };
492
493 /**
494 * @param {?AnchorBox} anchorBox
495 * @return {boolean}
496 */
497 AnchorBox.prototype.equals = function(anchorBox) {
498 return !!anchorBox && this.x === anchorBox.x && this.y === anchorBox.y && this .width === anchorBox.width &&
499 this.height === anchorBox.height;
500 };
501
502 /**
503 * @param {!Window=} targetWindow
504 * @return {!AnchorBox}
505 */
506 Element.prototype.boxInWindow = function(targetWindow) {
507 targetWindow = targetWindow || this.ownerDocument.defaultView;
508
509 var anchorBox = new AnchorBox();
510 var curElement = this;
511 var curWindow = this.ownerDocument.defaultView;
512 while (curWindow && curElement) {
513 anchorBox.x += curElement.totalOffsetLeft();
514 anchorBox.y += curElement.totalOffsetTop();
515 if (curWindow === targetWindow)
516 break;
517 curElement = curWindow.frameElement;
518 curWindow = curWindow.parent;
519 }
520
521 anchorBox.width = Math.min(this.offsetWidth, targetWindow.innerWidth - anchorB ox.x);
522 anchorBox.height = Math.min(this.offsetHeight, targetWindow.innerHeight - anch orBox.y);
523 return anchorBox;
524 };
525
526 /**
527 * @param {boolean=} preventDefault
528 */
529 Event.prototype.consume = function(preventDefault) {
530 this.stopImmediatePropagation();
531 if (preventDefault)
532 this.preventDefault();
533 this.handled = true;
534 };
535
536 /**
537 * @param {number=} start
538 * @param {number=} end
539 * @return {!Text}
540 */
541 Text.prototype.select = function(start, end) {
542 start = start || 0;
543 end = end || this.textContent.length;
544
545 if (start < 0)
546 start = end + start;
547
548 var selection = this.getComponentSelection();
549 selection.removeAllRanges();
550 var range = this.ownerDocument.createRange();
551 range.setStart(this, start);
552 range.setEnd(this, end);
553 selection.addRange(range);
554 return this;
555 };
556
557 /**
558 * @return {?number}
559 */
560 Element.prototype.selectionLeftOffset = function() {
561 // Calculate selection offset relative to the current element.
562
563 var selection = this.getComponentSelection();
564 if (!selection.containsNode(this, true))
565 return null;
566
567 var leftOffset = selection.anchorOffset;
568 var node = selection.anchorNode;
569
570 while (node !== this) {
571 while (node.previousSibling) {
572 node = node.previousSibling;
573 leftOffset += node.textContent.length;
574 }
575 node = node.parentNodeOrShadowHost();
576 }
577
578 return leftOffset;
579 };
580
581 /**
582 * @param {...!Node} var_args
583 */
584 Node.prototype.appendChildren = function(var_args) {
585 for (var i = 0, n = arguments.length; i < n; ++i)
586 this.appendChild(arguments[i]);
587 };
588
589 /**
590 * @return {string}
591 */
592 Node.prototype.deepTextContent = function() {
593 return this.childTextNodes()
594 .map(function(node) {
595 return node.textContent;
596 })
597 .join('');
598 };
599
600 /**
601 * @return {!Array.<!Node>}
602 */
603 Node.prototype.childTextNodes = function() {
604 var node = this.traverseNextTextNode(this);
605 var result = [];
606 var nonTextTags = {'STYLE': 1, 'SCRIPT': 1};
607 while (node) {
608 if (!nonTextTags[node.parentElement.nodeName])
609 result.push(node);
610 node = node.traverseNextTextNode(this);
611 }
612 return result;
613 };
614
615 /**
616 * @param {?Node} node
617 * @return {boolean}
618 */
619 Node.prototype.isAncestor = function(node) {
620 if (!node)
621 return false;
622
623 var currentNode = node.parentNodeOrShadowHost();
624 while (currentNode) {
625 if (this === currentNode)
626 return true;
627 currentNode = currentNode.parentNodeOrShadowHost();
628 }
629 return false;
630 };
631
632 /**
633 * @param {?Node} descendant
634 * @return {boolean}
635 */
636 Node.prototype.isDescendant = function(descendant) {
637 return !!descendant && descendant.isAncestor(this);
638 };
639
640 /**
641 * @param {?Node} node
642 * @return {boolean}
643 */
644 Node.prototype.isSelfOrAncestor = function(node) {
645 return !!node && (node === this || this.isAncestor(node));
646 };
647
648 /**
649 * @param {?Node} node
650 * @return {boolean}
651 */
652 Node.prototype.isSelfOrDescendant = function(node) {
653 return !!node && (node === this || this.isDescendant(node));
654 };
655
656 /**
657 * @param {!Node=} stayWithin
658 * @return {?Node}
659 */
660 Node.prototype.traverseNextNode = function(stayWithin) {
661 if (this.shadowRoot)
662 return this.shadowRoot;
663
664 var distributedNodes = this.getDistributedNodes ? this.getDistributedNodes() : [];
665
666 if (distributedNodes.length)
667 return distributedNodes[0];
668
669 if (this.firstChild)
670 return this.firstChild;
671
672 var node = this;
673 while (node) {
674 if (stayWithin && node === stayWithin)
675 return null;
676
677 var sibling = nextSibling(node);
678 if (sibling)
679 return sibling;
680
681 node = insertionPoint(node) || node.parentNodeOrShadowHost();
682 }
683
684 /**
685 * @param {!Node} node
686 * @return {?Node}
687 */
688 function nextSibling(node) {
689 var parent = insertionPoint(node);
690 if (!parent)
691 return node.nextSibling;
692 var distributedNodes = parent.getDistributedNodes ? parent.getDistributedNod es() : [];
693
694 var position = Array.prototype.indexOf.call(distributedNodes, node);
695 if (position + 1 < distributedNodes.length)
696 return distributedNodes[position + 1];
697 return null;
698 }
699
700 /**
701 * @param {!Node} node
702 * @return {?Node}
703 */
704 function insertionPoint(node) {
705 var insertionPoints = node.getDestinationInsertionPoints ? node.getDestinati onInsertionPoints() : [];
706 return insertionPoints.length > 0 ? insertionPoints[insertionPoints.length - 1] : null;
707 }
708
709 return null;
710 };
711
712 /**
713 * @param {!Node=} stayWithin
714 * @return {?Node}
715 */
716 Node.prototype.traversePreviousNode = function(stayWithin) {
717 if (stayWithin && this === stayWithin)
718 return null;
719 var node = this.previousSibling;
720 while (node && node.lastChild)
721 node = node.lastChild;
722 if (node)
723 return node;
724 return this.parentNodeOrShadowHost();
725 };
726
727 /**
728 * @param {*} text
729 * @param {string=} placeholder
730 * @return {boolean} true if was truncated
731 */
732 Node.prototype.setTextContentTruncatedIfNeeded = function(text, placeholder) {
733 // Huge texts in the UI reduce rendering performance drastically.
734 // Moreover, Blink/WebKit uses <unsigned short> internally for storing text co ntent
735 // length, so texts longer than 65535 are inherently displayed incorrectly.
736 const maxTextContentLength = 10000;
737
738 if (typeof text === 'string' && text.length > maxTextContentLength) {
739 this.textContent = typeof placeholder === 'string' ? placeholder : text.trim Middle(maxTextContentLength);
740 return true;
741 }
742
743 this.textContent = text;
744 return false;
745 };
746
747 /**
748 * @return {?Node}
749 */
750 Event.prototype.deepElementFromPoint = function() {
751 var root = this.target && this.target.getComponentRoot();
752 return root ? root.deepElementFromPoint(this.pageX, this.pageY) : null;
753 };
754
755 /**
756 * @param {number} x
757 * @param {number} y
758 * @return {?Node}
759 */
760 Document.prototype.deepElementFromPoint = function(x, y) {
761 var node = this.elementFromPoint(x, y);
762 while (node && node.shadowRoot)
763 node = node.shadowRoot.elementFromPoint(x, y);
764 return node;
765 };
766
767 DocumentFragment.prototype.deepElementFromPoint = Document.prototype.deepElement FromPoint;
768
769 /**
770 * @return {?Element}
771 */
772 Document.prototype.deepActiveElement = function() {
773 var activeElement = this.activeElement;
774 while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.a ctiveElement)
775 activeElement = activeElement.shadowRoot.activeElement;
776 return activeElement;
777 };
778
779 DocumentFragment.prototype.deepActiveElement = Document.prototype.deepActiveElem ent;
780
781 /**
782 * @return {boolean}
783 */
784 Element.prototype.hasFocus = function() {
785 var root = this.getComponentRoot();
786 return !!root && this.isSelfOrAncestor(root.activeElement);
787 };
788
789 /**
790 * @return {?Document|?DocumentFragment}
791 */
792 Node.prototype.getComponentRoot = function() {
793 var node = this;
794 while (node && node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE && node.nodeType !== Node.DOCUMENT_NODE)
795 node = node.parentNode;
796 return /** @type {?Document|?DocumentFragment} */ (node);
797 };
798
799 /**
800 * @param {!Event} event
801 * @return {boolean}
802 */
803 function isEnterKey(event) {
804 // Check if in IME.
805 return event.keyCode !== 229 && event.key === 'Enter';
806 }
807
808 /**
809 * @param {!Event} event
810 * @return {boolean}
811 */
812 function isEscKey(event) {
813 return event.keyCode === 27;
814 }
815
816 /**
817 * @param {function()} callback
818 * @suppressGlobalPropertiesCheck
819 */
820 function runOnWindowLoad(callback) {
821 /**
822 * @suppressGlobalPropertiesCheck
823 */
824 function windowLoaded() {
825 window.removeEventListener('DOMContentLoaded', windowLoaded, false);
826 callback();
827 }
828
829 if (document.readyState === 'complete' || document.readyState === 'interactive ')
830 callback();
831 else
832 window.addEventListener('DOMContentLoaded', windowLoaded, false);
833 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698