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

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

Issue 692343002: Revert of [DevTools] Extract platform module. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
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 /**
34 * @param {number} offset
35 * @param {string} stopCharacters
36 * @param {!Node} stayWithinNode
37 * @param {string=} direction
38 * @return {!Range}
39 */
40 Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, di rection)
41 {
42 var startNode;
43 var startOffset = 0;
44 var endNode;
45 var endOffset = 0;
46
47 if (!stayWithinNode)
48 stayWithinNode = this;
49
50 if (!direction || direction === "backward" || direction === "both") {
51 var node = this;
52 while (node) {
53 if (node === stayWithinNode) {
54 if (!startNode)
55 startNode = stayWithinNode;
56 break;
57 }
58
59 if (node.nodeType === Node.TEXT_NODE) {
60 var start = (node === this ? (offset - 1) : (node.nodeValue.leng th - 1));
61 for (var i = start; i >= 0; --i) {
62 if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
63 startNode = node;
64 startOffset = i + 1;
65 break;
66 }
67 }
68 }
69
70 if (startNode)
71 break;
72
73 node = node.traversePreviousNode(stayWithinNode);
74 }
75
76 if (!startNode) {
77 startNode = stayWithinNode;
78 startOffset = 0;
79 }
80 } else {
81 startNode = this;
82 startOffset = offset;
83 }
84
85 if (!direction || direction === "forward" || direction === "both") {
86 node = this;
87 while (node) {
88 if (node === stayWithinNode) {
89 if (!endNode)
90 endNode = stayWithinNode;
91 break;
92 }
93
94 if (node.nodeType === Node.TEXT_NODE) {
95 var start = (node === this ? offset : 0);
96 for (var i = start; i < node.nodeValue.length; ++i) {
97 if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
98 endNode = node;
99 endOffset = i;
100 break;
101 }
102 }
103 }
104
105 if (endNode)
106 break;
107
108 node = node.traverseNextNode(stayWithinNode);
109 }
110
111 if (!endNode) {
112 endNode = stayWithinNode;
113 endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinN ode.nodeValue.length : stayWithinNode.childNodes.length;
114 }
115 } else {
116 endNode = this;
117 endOffset = offset;
118 }
119
120 var result = this.ownerDocument.createRange();
121 result.setStart(startNode, startOffset);
122 result.setEnd(endNode, endOffset);
123
124 return result;
125 }
126
127 /**
128 * @param {!Node=} stayWithin
129 * @return {?Node}
130 */
131 Node.prototype.traverseNextTextNode = function(stayWithin)
132 {
133 var node = this.traverseNextNode(stayWithin);
134 if (!node)
135 return null;
136
137 while (node && node.nodeType !== Node.TEXT_NODE)
138 node = node.traverseNextNode(stayWithin);
139
140 return node;
141 }
142
143 /**
144 * @param {number} offset
145 * @return {!{container: !Node, offset: number}}
146 */
147 Node.prototype.rangeBoundaryForOffset = function(offset)
148 {
149 var node = this.traverseNextTextNode(this);
150 while (node && offset > node.nodeValue.length) {
151 offset -= node.nodeValue.length;
152 node = node.traverseNextTextNode(this);
153 }
154 if (!node)
155 return { container: this, offset: 0 };
156 return { container: node, offset: offset };
157 }
158
159 /**
160 * @param {number|undefined} x
161 * @param {number|undefined} y
162 * @param {!Element=} relativeTo
163 */
164 Element.prototype.positionAt = function(x, y, relativeTo)
165 {
166 var shift = {x: 0, y: 0};
167 if (relativeTo)
168 shift = relativeTo.boxInWindow(this.ownerDocument.defaultView);
169
170 if (typeof x === "number")
171 this.style.setProperty("left", (shift.x + x) + "px");
172 else
173 this.style.removeProperty("left");
174
175 if (typeof y === "number")
176 this.style.setProperty("top", (shift.y + y) + "px");
177 else
178 this.style.removeProperty("top");
179 }
180
181 /**
182 * @return {boolean}
183 */
184 Element.prototype.isScrolledToBottom = function()
185 {
186 // This code works only for 0-width border.
187 // Both clientHeight and scrollHeight are rounded to integer values, so we t olerate
188 // one pixel error.
189 return Math.abs(this.scrollTop + this.clientHeight - this.scrollHeight) <= 1 ;
190 }
191
192 /**
193 * @param {!Node} fromNode
194 * @param {!Node} toNode
195 */
196 function removeSubsequentNodes(fromNode, toNode)
197 {
198 for (var node = fromNode; node && node !== toNode; ) {
199 var nodeToRemove = node;
200 node = node.nextSibling;
201 nodeToRemove.remove();
202 }
203 }
204
205 /**
206 * @param {!Event} event
207 * @return {boolean}
208 */
209 Element.prototype.containsEventPoint = function(event)
210 {
211 var box = this.getBoundingClientRect();
212 return box.left < event.x && event.x < box.right &&
213 box.top < event.y && event.y < box.bottom;
214 }
215
216 /**
217 * @param {!Array.<string>} nameArray
218 * @return {?Node}
219 */
220 Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
221 {
222 for (var node = this; node && node !== this.ownerDocument; node = node.paren tNodeOrShadowHost()) {
223 for (var i = 0; i < nameArray.length; ++i) {
224 if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
225 return node;
226 }
227 }
228 return null;
229 }
230
231 /**
232 * @param {string} nodeName
233 * @return {?Node}
234 */
235 Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName)
236 {
237 return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]);
238 }
239
240 /**
241 * @param {string} className
242 * @param {!Element=} stayWithin
243 * @return {?Element}
244 */
245 Node.prototype.enclosingNodeOrSelfWithClass = function(className, stayWithin)
246 {
247 for (var node = this; node && node !== stayWithin && node !== this.ownerDocu ment; node = node.parentNodeOrShadowHost()) {
248 if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains(class Name))
249 return /** @type {!Element} */ (node);
250 }
251 return null;
252 }
253
254 /**
255 * @return {?Element}
256 */
257 Node.prototype.parentElementOrShadowHost = function()
258 {
259 var node = this.parentNode;
260 if (!node)
261 return null;
262 if (node.nodeType === Node.ELEMENT_NODE)
263 return /** @type {!Element} */ (node);
264 if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE)
265 return /** @type {!Element} */ (node.host);
266 return null;
267 }
268
269 /**
270 * @return {?Node}
271 */
272 Node.prototype.parentNodeOrShadowHost = function()
273 {
274 return this.parentNode || this.host || null;
275 }
276
277 /**
278 * @param {string} query
279 * @return {?Node}
280 */
281 Element.prototype.query = function(query)
282 {
283 return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDE RED_NODE_TYPE, null).singleNodeValue;
284 }
285
286 Element.prototype.removeChildren = function()
287 {
288 if (this.firstChild)
289 this.textContent = "";
290 }
291
292 /**
293 * @return {boolean}
294 */
295 Element.prototype.isInsertionCaretInside = function()
296 {
297 var selection = window.getSelection();
298 if (!selection.rangeCount || !selection.isCollapsed)
299 return false;
300 var selectionRange = selection.getRangeAt(0);
301 return selectionRange.startContainer.isSelfOrDescendant(this);
302 }
303
304 /**
305 * @param {string} tagName
306 * @return {!Element}
307 * @suppressGlobalPropertiesCheck
308 */
309 function createElement(tagName)
310 {
311 return document.createElement(tagName);
312 }
313
314 /**
315 * @param {number|string} data
316 * @return {!Text}
317 * @suppressGlobalPropertiesCheck
318 */
319 function createTextNode(data)
320 {
321 return document.createTextNode(data);
322 }
323
324 /**
325 * @param {string} elementName
326 * @param {string=} className
327 * @return {!Element}
328 */
329 Document.prototype.createElementWithClass = function(elementName, className)
330 {
331 var element = this.createElement(elementName);
332 if (className)
333 element.className = className;
334 return element;
335 }
336
337 /**
338 * @param {string} elementName
339 * @param {string=} className
340 * @return {!Element}
341 * @suppressGlobalPropertiesCheck
342 */
343 function createElementWithClass(elementName, className)
344 {
345 return document.createElementWithClass(elementName, className);
346 }
347
348 /**
349 * @return {!DocumentFragment}
350 * @suppressGlobalPropertiesCheck
351 */
352 function createDocumentFragment()
353 {
354 return document.createDocumentFragment();
355 }
356
357 /**
358 * @param {string} elementName
359 * @param {string=} className
360 * @return {!Element}
361 */
362 Element.prototype.createChild = function(elementName, className)
363 {
364 var element = this.ownerDocument.createElementWithClass(elementName, classNa me);
365 this.appendChild(element);
366 return element;
367 }
368
369 DocumentFragment.prototype.createChild = Element.prototype.createChild;
370
371 /**
372 * @param {string} text
373 * @return {!Text}
374 */
375 Element.prototype.createTextChild = function(text)
376 {
377 var element = this.ownerDocument.createTextNode(text);
378 this.appendChild(element);
379 return element;
380 }
381
382 DocumentFragment.prototype.createTextChild = Element.prototype.createTextChild;
383
384 /**
385 * @param {...string} var_args
386 */
387 Element.prototype.createTextChildren = function(var_args)
388 {
389 for (var i = 0, n = arguments.length; i < n; ++i)
390 this.createTextChild(arguments[i]);
391 }
392
393 DocumentFragment.prototype.createTextChildren = Element.prototype.createTextChil dren;
394
395 /**
396 * @param {...!Element} var_args
397 */
398 Element.prototype.appendChildren = function(var_args)
399 {
400 for (var i = 0, n = arguments.length; i < n; ++i)
401 this.appendChild(arguments[i]);
402 }
403
404 /**
405 * @return {number}
406 */
407 Element.prototype.totalOffsetLeft = function()
408 {
409 return this.totalOffset().left;
410 }
411
412 /**
413 * @return {number}
414 */
415 Element.prototype.totalOffsetTop = function()
416 {
417 return this.totalOffset().top;
418 }
419
420 /**
421 * @return {!{left: number, top: number}}
422 */
423 Element.prototype.totalOffset = function()
424 {
425 var rect = this.getBoundingClientRect();
426 return { left: rect.left, top: rect.top };
427 }
428
429 /**
430 * @return {!{left: number, top: number}}
431 */
432 Element.prototype.scrollOffset = function()
433 {
434 var curLeft = 0;
435 var curTop = 0;
436 for (var element = this; element; element = element.scrollParent) {
437 curLeft += element.scrollLeft;
438 curTop += element.scrollTop;
439 }
440 return { left: curLeft, top: curTop };
441 }
442
443 /**
444 * @constructor
445 * @param {number=} x
446 * @param {number=} y
447 * @param {number=} width
448 * @param {number=} height
449 */
450 function AnchorBox(x, y, width, height)
451 {
452 this.x = x || 0;
453 this.y = y || 0;
454 this.width = width || 0;
455 this.height = height || 0;
456 }
457
458 /**
459 * @param {!AnchorBox} box
460 * @return {!AnchorBox}
461 */
462 AnchorBox.prototype.relativeTo = function(box)
463 {
464 return new AnchorBox(
465 this.x - box.x, this.y - box.y, this.width, this.height);
466 }
467
468 /**
469 * @param {!Element} element
470 * @return {!AnchorBox}
471 */
472 AnchorBox.prototype.relativeToElement = function(element)
473 {
474 return this.relativeTo(element.boxInWindow(element.ownerDocument.defaultView ));
475 }
476
477 /**
478 * @param {?AnchorBox} anchorBox
479 * @return {boolean}
480 */
481 AnchorBox.prototype.equals = function(anchorBox)
482 {
483 return !!anchorBox && this.x === anchorBox.x && this.y === anchorBox.y && th is.width === anchorBox.width && this.height === anchorBox.height;
484 }
485
486 /**
487 * @param {!Window} targetWindow
488 * @return {!AnchorBox}
489 */
490 Element.prototype.offsetRelativeToWindow = function(targetWindow)
491 {
492 var elementOffset = new AnchorBox();
493 var curElement = this;
494 var curWindow = this.ownerDocument.defaultView;
495 while (curWindow && curElement) {
496 elementOffset.x += curElement.totalOffsetLeft();
497 elementOffset.y += curElement.totalOffsetTop();
498 if (curWindow === targetWindow)
499 break;
500
501 curElement = curWindow.frameElement;
502 curWindow = curWindow.parent;
503 }
504
505 return elementOffset;
506 }
507
508 /**
509 * @param {!Window=} targetWindow
510 * @return {!AnchorBox}
511 */
512 Element.prototype.boxInWindow = function(targetWindow)
513 {
514 targetWindow = targetWindow || this.ownerDocument.defaultView;
515
516 var anchorBox = this.offsetRelativeToWindow(window);
517 anchorBox.width = Math.min(this.offsetWidth, window.innerWidth - anchorBox.x );
518 anchorBox.height = Math.min(this.offsetHeight, window.innerHeight - anchorBo x.y);
519
520 return anchorBox;
521 }
522
523 /**
524 * @param {string} text
525 */
526 Element.prototype.setTextAndTitle = function(text)
527 {
528 this.textContent = text;
529 this.title = text;
530 }
531
532 KeyboardEvent.prototype.__defineGetter__("data", function()
533 {
534 // Emulate "data" attribute from DOM 3 TextInput event.
535 // See http://www.w3.org/TR/DOM-Level-3-Events/#events-Events-TextEvent-data
536 switch (this.type) {
537 case "keypress":
538 if (!this.ctrlKey && !this.metaKey)
539 return String.fromCharCode(this.charCode);
540 else
541 return "";
542 case "keydown":
543 case "keyup":
544 if (!this.ctrlKey && !this.metaKey && !this.altKey)
545 return String.fromCharCode(this.which);
546 else
547 return "";
548 }
549 });
550
551 /**
552 * @param {boolean=} preventDefault
553 */
554 Event.prototype.consume = function(preventDefault)
555 {
556 this.stopImmediatePropagation();
557 if (preventDefault)
558 this.preventDefault();
559 this.handled = true;
560 }
561
562 /**
563 * @param {number=} start
564 * @param {number=} end
565 * @return {!Text}
566 */
567 Text.prototype.select = function(start, end)
568 {
569 start = start || 0;
570 end = end || this.textContent.length;
571
572 if (start < 0)
573 start = end + start;
574
575 var selection = this.ownerDocument.defaultView.getSelection();
576 selection.removeAllRanges();
577 var range = this.ownerDocument.createRange();
578 range.setStart(this, start);
579 range.setEnd(this, end);
580 selection.addRange(range);
581 return this;
582 }
583
584 /**
585 * @return {?number}
586 */
587 Element.prototype.selectionLeftOffset = function()
588 {
589 // Calculate selection offset relative to the current element.
590
591 var selection = window.getSelection();
592 if (!selection.containsNode(this, true))
593 return null;
594
595 var leftOffset = selection.anchorOffset;
596 var node = selection.anchorNode;
597
598 while (node !== this) {
599 while (node.previousSibling) {
600 node = node.previousSibling;
601 leftOffset += node.textContent.length;
602 }
603 node = node.parentNodeOrShadowHost();
604 }
605
606 return leftOffset;
607 }
608
609 /**
610 * @return {string}
611 */
612 Node.prototype.deepTextContent = function()
613 {
614 var node = this.traverseNextTextNode(this);
615 var result = [];
616 var nonTextTags = { "STYLE": 1, "SCRIPT": 1 };
617 while (node) {
618 if (!nonTextTags[node.parentElement.nodeName])
619 result.push(node.textContent);
620 node = node.traverseNextTextNode(this);
621 }
622 return result.join("");
623 }
624
625 /**
626 * @param {?Node} node
627 * @return {boolean}
628 */
629 Node.prototype.isAncestor = function(node)
630 {
631 if (!node)
632 return false;
633
634 var currentNode = node.parentNodeOrShadowHost();
635 while (currentNode) {
636 if (this === currentNode)
637 return true;
638 currentNode = currentNode.parentNodeOrShadowHost();
639 }
640 return false;
641 }
642
643 /**
644 * @param {?Node} descendant
645 * @return {boolean}
646 */
647 Node.prototype.isDescendant = function(descendant)
648 {
649 return !!descendant && descendant.isAncestor(this);
650 }
651
652 /**
653 * @param {?Node} node
654 * @return {boolean}
655 */
656 Node.prototype.isSelfOrAncestor = function(node)
657 {
658 return !!node && (node === this || this.isAncestor(node));
659 }
660
661 /**
662 * @param {?Node} node
663 * @return {boolean}
664 */
665 Node.prototype.isSelfOrDescendant = function(node)
666 {
667 return !!node && (node === this || this.isDescendant(node));
668 }
669
670 /**
671 * @param {!Node=} stayWithin
672 * @return {?Node}
673 */
674 Node.prototype.traverseNextNode = function(stayWithin)
675 {
676 if (this.firstChild)
677 return this.firstChild;
678
679 if (this.shadowRoot)
680 return this.shadowRoot;
681
682 if (stayWithin && this === stayWithin)
683 return null;
684
685 var node = this.nextSibling;
686 if (node)
687 return node;
688
689 node = this;
690 while (node && !node.nextSibling && (!stayWithin || !node.parentNodeOrShadow Host() || node.parentNodeOrShadowHost() !== stayWithin))
691 node = node.parentNodeOrShadowHost();
692 if (!node)
693 return null;
694
695 return node.nextSibling;
696 }
697
698 /**
699 * @param {!Node=} stayWithin
700 * @return {?Node}
701 */
702 Node.prototype.traversePreviousNode = function(stayWithin)
703 {
704 if (stayWithin && this === stayWithin)
705 return null;
706 var node = this.previousSibling;
707 while (node && node.lastChild)
708 node = node.lastChild;
709 if (node)
710 return node;
711 return this.parentNodeOrShadowHost();
712 }
713
714 /**
715 * @param {*} text
716 * @param {string=} placeholder
717 * @return {boolean} true if was truncated
718 */
719 Node.prototype.setTextContentTruncatedIfNeeded = function(text, placeholder)
720 {
721 // Huge texts in the UI reduce rendering performance drastically.
722 // Moreover, Blink/WebKit uses <unsigned short> internally for storing text content
723 // length, so texts longer than 65535 are inherently displayed incorrectly.
724 const maxTextContentLength = 65535;
725
726 if (typeof text === "string" && text.length > maxTextContentLength) {
727 this.textContent = typeof placeholder === "string" ? placeholder : text. trimEnd(maxTextContentLength);
728 return true;
729 }
730
731 this.textContent = text;
732 return false;
733 }
734
735 /**
736 * @return {?Node}
737 */
738 Event.prototype.deepElementFromPoint = function()
739 {
740 // 1. climb to the component root.
741 var node = this.target;
742 while (node && node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE && node.nodeTyp e !== Node.DOCUMENT_NODE)
743 node = node.parentNode;
744
745 if (!node)
746 return null;
747
748 // 2. Find deepest node by coordinates.
749 node = node.elementFromPoint(this.pageX, this.pageY);
750 while (node && node.shadowRoot)
751 node = node.shadowRoot.elementFromPoint(this.pageX, this.pageY);
752 return node;
753 }
754
755 /**
756 * @param {number} x
757 * @param {number} y
758 * @return {?Node}
759 */
760 Document.prototype.deepElementFromPoint = function(x, y)
761 {
762 var node = this.elementFromPoint(x, y);
763 while (node && node.shadowRoot)
764 node = node.shadowRoot.elementFromPoint(x, y);
765 return node;
766 }
767
768 /**
769 * @return {boolean}
770 */
771 function isEnterKey(event) {
772 // Check if in IME.
773 return event.keyCode !== 229 && event.keyIdentifier === "Enter";
774 }
775
776 function consumeEvent(e)
777 {
778 e.consume();
779 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/main/module.json ('k') | Source/devtools/front_end/platform/Promise.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698