2 Copyright (C) 2012 Google Inc. All rights reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 its contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 cursor: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAQAAAADHm0dAAABH0lEQVR4XpWTO2rDQBCG18S6gAWCoD6VFHKCCBZsN7qACgenFZn/OAZDrConMahJzmGM+oBJMfmziIUs8UMOXzHD7seyzMMwJOEDZ7r4ftEFZy5PwtvfNKIliE/Z4hVbFwmHZfRXTfWZWOEOI5iekctXINx5GqopZSdTmCOm2AmFt15lpMu9TGBOMsFe9InjXmVBzGHOMgfBR6cyJtYwF1mDYGyYEdmAmoNgZmgPcjOgjvEltEarFmaQd2hltN5cob5B6ytf/YBW//krMyIfUO99BWKiGVCbvq6+W+UFsfTd8jPQSXJGTND1MxBMViflyRe7YLK8rEuiQQ5fDRfz/o/uPD3egoIgDtJig9ZFwlGEWxASM6PVSmutaF0eh7c/zBRVQt5j3yoAAAAASUVORK5CYII=) 10 10, auto !important;
43 font-family: Menlo, Monaco;
46 body.platform-windows {
48 font-family: Consolas, Lucida Console;
53 font-family: dejavu sans mono;
65 background-color: rgba(0, 0, 0, 0.31);
74 justify-content: center;
86 background-color: rgb(255, 255, 194);
87 border: 1px solid rgb(202, 202, 202);
89 box-sizing: border-box;
92 .controls-line .button {
99 .controls-line .button:hover {
103 .controls-line .button .glyph {
106 background-color: rgba(0, 0, 0, 0.75);
108 -webkit-mask-repeat: no-repeat;
109 -webkit-mask-position: center;
113 .controls-line .button:active .glyph {
118 #resume-button .glyph {
119 -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAKCAYAAABv7tTEAAAAAXNSR0IArs4c6QAAAFJJREFUKM+10bEJgGAMBeEPbR3BLRzEVdzEVRzELRzBVohVwEJ+iODBlQfhBeJhsmHU4C0KnFjQV6J0x1SNAhdWDJUoPTB3PvLLeaUhypM3n3sD/qc7lDrdpIEAAAAASUVORK5CYII=);
120 -webkit-mask-size: 13px 10px;
121 background-color: rgb(66, 129, 235);
124 #step-over-button .glyph {
125 -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAKCAYAAAC5Sw6hAAAAAXNSR0IArs4c6QAAAOFJREFUKM+N0j8rhXEUB/DPcxW35CqhvIBrtqibkklhV8qkTHe4ZbdblcXgPVhuMdqUTUl5A2KRRCF5LGc4PT1P7qnfcr5/zu/8KdTHLFaxjHnc4RZXKI0QYxjgLQTVd42l/0wmg5iFX3iq5H6w22RS4DyRH7CB8cAXcBTGJT6xUmd0mEwuMdFQcA3fwXvGTAan8BrgPabTL9fRRyfx91PRMwyjGwcJ2EyCfsrfpPw2Pipz24NT/MZciiQYVshzOKnZ5Hturxt3k2MnCpS4SPkeHpPR8Sh3tYgttBoW9II2/AHiaEqvD2Fc0wAAAABJRU5ErkJggg==);
126 -webkit-mask-size: 18px 10px;
130 color: rgb(128, 128, 128);
139 /* Keep this in sync with view-source.css (.webkit-html-tag) */
140 color: rgb(136, 18, 128);
144 /* Keep this in sync with view-source.css (.webkit-html-attribute-value) */
145 color: rgb(26, 26, 166);
149 /* Keep this in sync with view-source.css (.webkit-html-attribute-name) */
150 color: rgb(153, 69, 0);
155 const lightGridColor = "rgba(0,0,0,0.2)";
156 const darkGridColor = "rgba(0,0,0,0.7)";
157 const transparentColor = "rgba(0, 0, 0, 0)";
158 const gridBackgroundColor = "rgba(255, 255, 255, 0.8)";
160 const shapeHighlightColor = "rgba(96, 82, 127, 0.8)";
161 const shapeMarginHighlightColor = "rgba(96, 82, 127, 0.6)";
163 function drawPausedInDebuggerMessage(message)
165 window._controlsVisible = true;
166 document.querySelector(".controls-line").style.visibility = "visible";
167 document.getElementById("paused-in-debugger").textContent = message;
168 document.body.classList.add("dimmed");
171 function _drawGrid(rulerAtRight, rulerAtBottom)
173 if (window._gridPainted)
175 window._gridPainted = true;
179 var pageFactor = pageZoomFactor * pageScaleFactor;
182 return Math.round(x * pageFactor);
186 return Math.round(x / pageFactor);
189 var width = canvasWidth / pageFactor;
190 var height = canvasHeight / pageFactor;
192 const gridSubStep = 5;
196 // Draw X grid background
198 context.fillStyle = gridBackgroundColor;
200 context.fillRect(0, zoom(height) - 15, zoom(width), zoom(height));
202 context.fillRect(0, 0, zoom(width), 15);
204 // Clip out backgrounds intersection
205 context.globalCompositeOperation = "destination-out";
206 context.fillStyle = "red";
208 context.fillRect(zoom(width) - 15, 0, zoom(width), zoom(height));
210 context.fillRect(0, 0, 15, zoom(height));
213 // Draw Y grid background
214 context.fillStyle = gridBackgroundColor;
216 context.fillRect(zoom(width) - 15, 0, zoom(width), zoom(height));
218 context.fillRect(0, 0, 15, zoom(height));
221 context.lineWidth = 1;
222 context.strokeStyle = darkGridColor;
223 context.fillStyle = darkGridColor;
227 context.translate(-scrollX, 0.5 - scrollY);
228 var maxY = height + unzoom(scrollY);
229 for (var y = 2 * gridStep; y < maxY; y += 2 * gridStep) {
231 context.translate(scrollX, zoom(y));
232 context.rotate(-Math.PI / 2);
233 context.fillText(y, 2, rulerAtRight ? zoom(width) - 7 : 13);
236 context.translate(0.5, -0.5);
237 var maxX = width + unzoom(scrollX);
238 for (var x = 2 * gridStep; x < maxX; x += 2 * gridStep) {
240 context.fillText(x, zoom(x) + 2, rulerAtBottom ? scrollY + zoom(height) - 7 : scrollY + 13);
247 // Draw vertical grid
250 context.translate(zoom(width), 0);
251 context.scale(-1, 1);
253 context.translate(-scrollX, 0.5 - scrollY);
254 var maxY = height + unzoom(scrollY);
255 for (var y = gridStep; y < maxY; y += gridStep) {
257 context.moveTo(scrollX, zoom(y));
258 var markLength = (y % (gridStep * 2)) ? 5 : 8;
259 context.lineTo(scrollX + markLength, zoom(y));
262 context.strokeStyle = lightGridColor;
263 for (var y = gridSubStep; y < maxY; y += gridSubStep) {
267 context.moveTo(scrollX, zoom(y));
268 context.lineTo(scrollX + gridSubStep, zoom(y));
275 // Draw horizontal grid
278 context.translate(0, zoom(height));
279 context.scale(1, -1);
281 context.translate(0.5 - scrollX, -scrollY);
282 var maxX = width + unzoom(scrollX);
283 for (var x = gridStep; x < maxX; x += gridStep) {
285 context.moveTo(zoom(x), scrollY);
286 var markLength = (x % (gridStep * 2)) ? 5 : 8;
287 context.lineTo(zoom(x), scrollY + markLength);
290 context.strokeStyle = lightGridColor;
291 for (var x = gridSubStep; x < maxX; x += gridSubStep) {
295 context.moveTo(zoom(x), scrollY);
296 context.lineTo(zoom(x), scrollY + gridSubStep);
305 function quadToPath(quad)
308 context.moveTo(quad[0].x, quad[0].y);
309 context.lineTo(quad[1].x, quad[1].y);
310 context.lineTo(quad[2].x, quad[2].y);
311 context.lineTo(quad[3].x, quad[3].y);
316 function drawOutlinedQuad(quad, fillColor, outlineColor)
319 context.lineWidth = 2;
320 quadToPath(quad).clip();
321 context.fillStyle = fillColor;
324 context.strokeStyle = outlineColor;
330 function drawOutlinedQuadWithClip(quad, clipQuad, fillColor)
332 context.fillStyle = fillColor;
334 context.lineWidth = 0;
335 quadToPath(quad).fill();
336 context.globalCompositeOperation = "destination-out";
337 context.fillStyle = "red";
338 quadToPath(clipQuad).fill();
342 function drawUnderlyingQuad(quad, fillColor)
345 context.lineWidth = 2;
346 context.globalCompositeOperation = "destination-over";
347 context.fillStyle = fillColor;
348 quadToPath(quad).fill();
352 function quadEquals(quad1, quad2)
354 return quad1[0].x === quad2[0].x && quad1[0].y === quad2[0].y &&
355 quad1[1].x === quad2[1].x && quad1[1].y === quad2[1].y &&
356 quad1[2].x === quad2[2].x && quad1[2].y === quad2[2].y &&
357 quad1[3].x === quad2[3].x && quad1[3].y === quad2[3].y;
360 function drawViewSize(drawViewSizeWithGrid)
362 var drawGridBoolean = drawViewSizeWithGrid === "true";
363 var text = viewportSize.width + "px \u00D7 " + viewportSize.height + "px";
365 context.font = "20px ";
367 case "windows": context.font = "14px Consolas"; break;
368 case "mac": context.font = "14px Menlo"; break;
369 case "linux": context.font = "14px dejavu sans mono"; break;
372 var frameWidth = frameViewFullSize.width || canvasWidth;
373 var textWidth = context.measureText(text).width;
374 context.fillStyle = gridBackgroundColor;
375 context.fillRect(frameWidth - textWidth - 12, drawGridBoolean ? 15 : 0, frameWidth, 25);
376 context.fillStyle = darkGridColor;
377 context.fillText(text, frameWidth - textWidth - 6, drawGridBoolean ? 33 : 18);
383 function reset(resetData)
385 window.viewportSize = resetData.viewportSize;
386 window.frameViewFullSize = resetData.frameViewFullSize;
387 window.deviceScaleFactor = resetData.deviceScaleFactor;
388 window.pageZoomFactor = resetData.pageZoomFactor;
389 window.pageScaleFactor = resetData.pageScaleFactor;
390 window.scrollX = Math.round(resetData.scrollX * pageScaleFactor);
391 window.scrollY = Math.round(resetData.scrollY * pageScaleFactor);
393 window.canvas = document.getElementById("canvas");
394 window.context = canvas.getContext("2d");
396 canvas.width = deviceScaleFactor * viewportSize.width;
397 canvas.height = deviceScaleFactor * viewportSize.height;
398 canvas.style.width = viewportSize.width + "px";
399 canvas.style.height = viewportSize.height + "px";
400 context.scale(deviceScaleFactor, deviceScaleFactor);
401 window.canvasWidth = viewportSize.width;
402 window.canvasHeight = viewportSize.height;
404 window._controlsVisible = false;
405 document.querySelector(".controls-line").style.visibility = "hidden";
406 document.getElementById("element-title").style.visibility = "hidden";
407 document.body.classList.remove("dimmed");
408 window._gridPainted = false;
411 function _drawElementTitle(highlight)
413 var elementInfo = highlight.elementInfo;
414 if (!highlight.elementInfo)
417 document.getElementById("tag-name").textContent = elementInfo.tagName;
418 document.getElementById("node-id").textContent = elementInfo.idValue ? "#" + elementInfo.idValue : "";
419 var className = elementInfo.className;
420 if (className && className.length > 50)
421 className = className.substring(0, 50) + "\u2026";
422 document.getElementById("class-name").textContent = className || "";
423 document.getElementById("node-width").textContent = elementInfo.nodeWidth;
424 document.getElementById("node-height").textContent = elementInfo.nodeHeight;
425 var elementTitle = document.getElementById("element-title");
427 var marginQuad = highlight.quads[0];
429 var titleWidth = elementTitle.offsetWidth + 6;
430 var titleHeight = elementTitle.offsetHeight + 4;
432 var anchorTop = Math.min(marginQuad[0].y, marginQuad[1].y, marginQuad[2].y, marginQuad[3].y);
433 var anchorBottom = Math.max(marginQuad[0].y, marginQuad[1].y, marginQuad[2].y, marginQuad[3].y);
434 var anchorLeft = Math.min(marginQuad[0].x, marginQuad[1].x, marginQuad[2].x, marginQuad[3].x);
436 const arrowHeight = 7;
437 var renderArrowUp = false;
438 var renderArrowDown = false;
440 var boxX = Math.max(2, anchorLeft);
441 if (boxX + titleWidth > canvasWidth)
442 boxX = canvasWidth - titleWidth - 2;
445 if (anchorTop > canvasHeight) {
446 boxY = canvasHeight - titleHeight - arrowHeight;
447 renderArrowDown = true;
448 } else if (anchorBottom < 0) {
450 renderArrowUp = true;
451 } else if (anchorBottom + titleHeight + arrowHeight < canvasHeight) {
452 boxY = anchorBottom + arrowHeight - 4;
453 renderArrowUp = true;
454 } else if (anchorTop - titleHeight - arrowHeight > 0) {
455 boxY = anchorTop - titleHeight - arrowHeight + 3;
456 renderArrowDown = true;
461 context.translate(0.5, 0.5);
463 context.moveTo(boxX, boxY);
465 context.lineTo(boxX + 2 * arrowHeight, boxY);
466 context.lineTo(boxX + 3 * arrowHeight, boxY - arrowHeight);
467 context.lineTo(boxX + 4 * arrowHeight, boxY);
469 context.lineTo(boxX + titleWidth, boxY);
470 context.lineTo(boxX + titleWidth, boxY + titleHeight);
471 if (renderArrowDown) {
472 context.lineTo(boxX + 4 * arrowHeight, boxY + titleHeight);
473 context.lineTo(boxX + 3 * arrowHeight, boxY + titleHeight + arrowHeight);
474 context.lineTo(boxX + 2 * arrowHeight, boxY + titleHeight);
476 context.lineTo(boxX, boxY + titleHeight);
478 context.fillStyle = "rgb(255, 255, 194)";
480 context.strokeStyle = "rgb(128, 128, 128)";
485 elementTitle.style.visibility = "visible";
486 elementTitle.style.top = (boxY + 3) + "px";
487 elementTitle.style.left = (boxX + 3) + "px";
490 function _drawRulers(highlight, rulerAtRight, rulerAtBottom)
493 var width = canvasWidth;
494 var height = canvasHeight;
495 context.strokeStyle = "rgba(128, 128, 128, 0.3)";
496 context.lineWidth = 1;
497 context.translate(0.5, 0.5);
498 var leftmostXForY = {};
499 var rightmostXForY = {};
500 var topmostYForX = {};
501 var bottommostYForX = {};
503 for (var i = 0; i < highlight.quads.length; ++i) {
504 var quad = highlight.quads[i];
505 for (var j = 0; j < quad.length; ++j) {
508 leftmostXForY[Math.round(y)] = Math.min(leftmostXForY[y] || Number.MAX_VALUE, Math.round(quad[j].x));
509 rightmostXForY[Math.round(y)] = Math.max(rightmostXForY[y] || Number.MIN_VALUE, Math.round(quad[j].x));
510 topmostYForX[Math.round(x)] = Math.min(topmostYForX[x] || Number.MAX_VALUE, Math.round(quad[j].y));
511 bottommostYForX[Math.round(x)] = Math.max(bottommostYForX[x] || Number.MIN_VALUE, Math.round(quad[j].y));
516 for (var y in rightmostXForY) {
518 context.moveTo(width, y);
519 context.lineTo(rightmostXForY[y], y);
523 for (var y in leftmostXForY) {
525 context.moveTo(0, y);
526 context.lineTo(leftmostXForY[y], y);
532 for (var x in bottommostYForX) {
534 context.moveTo(x, height);
535 context.lineTo(x, topmostYForX[x]);
539 for (var x in topmostYForX) {
541 context.moveTo(x, 0);
542 context.lineTo(x, topmostYForX[x]);
550 function drawPath(commands, fillColor)
555 var commandsIndex = 0;
556 var commandsLength = commands.length;
557 while (commandsIndex < commandsLength) {
558 switch (commands[commandsIndex++]) {
560 context.moveTo(commands[commandsIndex++], commands[commandsIndex++]);
563 context.lineTo(commands[commandsIndex++], commands[commandsIndex++]);
566 context.bezierCurveTo(commands[commandsIndex++], commands[commandsIndex++], commands[commandsIndex++],
567 commands[commandsIndex++], commands[commandsIndex++], commands[commandsIndex++]);
570 context.quadraticCurveTo(commands[commandsIndex++], commands[commandsIndex++], commands[commandsIndex++],
571 commands[commandsIndex++]);
579 context.fillStyle = fillColor;
585 function drawShapeHighlight(shapeInfo)
587 if (shapeInfo.marginShape)
588 drawPath(shapeInfo.marginShape, shapeMarginHighlightColor);
590 drawOutlinedQuad(shapeInfo.bounds, shapeHighlightColor, shapeHighlightColor);
593 drawPath(shapeInfo.shape, shapeHighlightColor);
595 drawOutlinedQuad(shapeInfo.bounds, shapeHighlightColor, shapeHighlightColor);
598 function drawNodeHighlight(highlight)
601 for (var i = 0; i < highlight.quads.length; ++i) {
602 var quad = highlight.quads[i];
603 for (var j = 0; j < quad.length; ++j) {
604 quad[j].x = Math.round(quad[j].x * pageScaleFactor - scrollX);
605 quad[j].y = Math.round(quad[j].y * pageScaleFactor - scrollY);
610 if (!highlight.quads.length) {
611 if (highlight.showRulers)
612 _drawGrid(false, false);
618 var quads = highlight.quads.slice();
619 var eventTargetQuad = quads.length >= 5 ? quads.pop() : null;
620 var contentQuad = quads.pop();
621 var paddingQuad = quads.pop();
622 var borderQuad = quads.pop();
623 var marginQuad = quads.pop();
625 var hasContent = contentQuad && highlight.contentColor !== transparentColor || highlight.contentOutlineColor !== transparentColor;
626 var hasPadding = paddingQuad && highlight.paddingColor !== transparentColor;
627 var hasBorder = borderQuad && highlight.borderColor !== transparentColor;
628 var hasMargin = marginQuad && highlight.marginColor !== transparentColor;
629 var hasEventTarget = eventTargetQuad && highlight.eventTargetColor !== transparentColor;
632 if (hasMargin && (!hasBorder || !quadEquals(marginQuad, borderQuad))) {
633 drawOutlinedQuadWithClip(marginQuad, borderQuad, highlight.marginColor);
634 clipQuad = borderQuad;
636 if (hasBorder && (!hasPadding || !quadEquals(borderQuad, paddingQuad))) {
637 drawOutlinedQuadWithClip(borderQuad, paddingQuad, highlight.borderColor);
638 clipQuad = paddingQuad;
640 if (hasPadding && (!hasContent || !quadEquals(paddingQuad, contentQuad))) {
641 drawOutlinedQuadWithClip(paddingQuad, contentQuad, highlight.paddingColor);
642 clipQuad = contentQuad;
645 drawOutlinedQuad(contentQuad, highlight.contentColor, highlight.contentOutlineColor);
647 drawUnderlyingQuad(eventTargetQuad, highlight.eventTargetColor);
649 var width = canvasWidth;
650 var height = canvasHeight;
651 var minX = Number.MAX_VALUE, minY = Number.MAX_VALUE, maxX = Number.MIN_VALUE; maxY = Number.MIN_VALUE;
652 for (var i = 0; i < highlight.quads.length; ++i) {
653 var quad = highlight.quads[i];
654 for (var j = 0; j < quad.length; ++j) {
655 minX = Math.min(minX, quad[j].x);
656 maxX = Math.max(maxX, quad[j].x);
657 minY = Math.min(minY, quad[j].y);
658 maxY = Math.max(maxY, quad[j].y);
662 var rulerAtRight = minX < 20 && maxX + 20 < width;
663 var rulerAtBottom = minY < 20 && maxY + 20 < height;
665 if (highlight.showRulers) {
666 _drawGrid(rulerAtRight, rulerAtBottom);
667 _drawRulers(highlight, rulerAtRight, rulerAtBottom);
669 if (highlight.elementInfo && highlight.elementInfo.shapeOutsideInfo)
670 drawShapeHighlight(highlight.elementInfo.shapeOutsideInfo);
671 _drawElementTitle(highlight);
676 function drawQuadHighlight(highlight)
679 drawOutlinedQuad(highlight.quads[0], highlight.contentColor, highlight.contentOutlineColor);
683 function setPlatform(platform)
685 window.platform = platform;
686 document.body.classList.add("platform-" + platform);
689 function dispatch(message)
691 var functionName = message.shift();
692 window[functionName].apply(null, message);
697 var logEntry = document.createElement("div");
698 logEntry.textContent = text;
699 document.getElementById("log").appendChild(logEntry);
702 function onResumeClick()
704 InspectorOverlayHost.resume();
707 function onStepOverClick()
709 InspectorOverlayHost.stepOver();
714 document.getElementById("resume-button").addEventListener("click", onResumeClick);
715 document.getElementById("step-over-button").addEventListener("click", onStepOverClick);
718 function eventHasCtrlOrMeta(event)
720 return window.platform == "mac" ? (event.metaKey && !event.ctrlKey) : (event.ctrlKey && !event.metaKey);
723 function onDocumentKeyDown(event)
725 if (!window._controlsVisible)
727 if (event.keyIdentifier == "F8" || eventHasCtrlOrMeta(event) && event.keyCode == 220 /* backslash */)
728 InspectorOverlayHost.resume();
729 else if (event.keyIdentifier == "F10" || eventHasCtrlOrMeta(event) && event.keyCode == 222 /* single quote */)
730 InspectorOverlayHost.stepOver();
733 window.addEventListener("DOMContentLoaded", onLoaded);
734 document.addEventListener("keydown", onDocumentKeyDown);
739 <div class="controls-line">
740 <div class="message-box"><div id="paused-in-debugger"></div></div>
741 <div class="button" id="resume-button" title="Resume script execution (F8)."><div class="glyph"></div></div>
742 <div class="button" id="step-over-button" title="Step over next function call (F10)."><div class="glyph"></div></div>
745 <canvas id="canvas" class="fill"></canvas>
746 <div id="element-title">
747 <span id="tag-name"></span><span id="node-id"></span><span id="class-name"></span>
748 <span id="node-width"></span><span class="px">px</span><span class="px"> × </span><span id="node-height"></span><span class="px">px</span>