viewport-size.js (6326B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 const { 8 setIgnoreLayoutChanges, 9 } = require("resource://devtools/shared/layout/utils.js"); 10 const { 11 CanvasFrameAnonymousContentHelper, 12 } = require("resource://devtools/server/actors/highlighters/utils/markup.js"); 13 14 /** 15 * The ViewportSizeHighlighter is a class that displays the viewport 16 * width and height on a small overlay on the top right edge of the page 17 * while the rulers are turned on. This class is also extended by ViewportSizeOnResizeHighlighter, 18 * which is used to show the viewport information when the rulers aren't displayed. 19 */ 20 class ViewportSizeHighlighter { 21 /** 22 * 23 * @param {HighlighterEnvironment} highlighterEnv 24 * @param {InspectorActor} parent 25 * @param {object} options 26 * @param {number} options.hideTimeout: An optional number. When passed, the viewport 27 * information will automatically hide after {hideTimeout} ms. 28 * @param {string} options.extraCls: An extra class to add to the infobar container. 29 * @param {boolean} options.waitForDocumentToLoad: Option that will be passed to 30 * CanvasFrameAnonymousContentHelper. Defaults to true 31 */ 32 constructor(highlighterEnv, parent, options = {}) { 33 this.env = highlighterEnv; 34 this.parent = parent; 35 36 this.extraCls = options?.extraCls; 37 this.hideTimeout = options?.hideTimeout; 38 39 this.markup = new CanvasFrameAnonymousContentHelper( 40 highlighterEnv, 41 this._buildMarkup.bind(this), 42 { 43 contentRootHostClassName: "devtools-highlighter-viewport-size", 44 waitForDocumentToLoad: options?.waitForDocumentToLoad ?? true, 45 } 46 ); 47 this._onPageResize = this._onPageResize.bind(this); 48 this.isReady = this.markup.initialize(); 49 50 const { pageListenerTarget } = highlighterEnv; 51 pageListenerTarget.addEventListener("pagehide", this); 52 } 53 54 /** 55 * Static getter that indicates that BoxModelHighlighter supports 56 * highlighting in XUL windows. 57 */ 58 static get XULSupported() { 59 return true; 60 } 61 62 get isFadingViewportHighlighter() { 63 return this.hideTimeout !== undefined; 64 } 65 66 _buildMarkup() { 67 const container = this.markup.createNode({ 68 attributes: { class: "highlighter-container" }, 69 }); 70 71 this.markup.createNode({ 72 parent: container, 73 attributes: { 74 id: "viewport-size-highlighter-viewport-infobar-container", 75 class: 76 "viewport-size-highlighter-viewport-infobar-container" + 77 (this.extraCls ? " " + this.extraCls : ""), 78 position: "top", 79 hidden: "true", 80 }, 81 }); 82 83 return container; 84 } 85 86 handleEvent(event) { 87 switch (event.type) { 88 case "pagehide": 89 // If a page hide event is triggered for current window's highlighter, hide the 90 // highlighter. 91 if (event.target.defaultView === this.env.window) { 92 this.destroy(); 93 } 94 break; 95 } 96 } 97 98 _update() { 99 const { window } = this.env; 100 101 setIgnoreLayoutChanges(true); 102 this.updateViewportInfobar(); 103 setIgnoreLayoutChanges(false, window.document.documentElement); 104 } 105 106 updateViewportInfobar() { 107 const { window } = this.env; 108 const { innerHeight, innerWidth } = window; 109 const infobarId = "viewport-size-highlighter-viewport-infobar-container"; 110 const textContent = innerWidth + "px \u00D7 " + innerHeight + "px"; 111 this.markup.getElement(infobarId).setTextContent(textContent); 112 } 113 114 destroy() { 115 if (this._destroyed) { 116 return; 117 } 118 this._destroyed = true; 119 120 if ( 121 this.isFadingViewportHighlighter && 122 this.parent.highlightersState?.fadingViewportSizeHiglighter 123 ) { 124 this.parent.highlightersState.fadingViewportSizeHiglighter = null; 125 } 126 127 this.hide(); 128 129 const { pageListenerTarget } = this.env; 130 131 if (pageListenerTarget) { 132 pageListenerTarget.removeEventListener("pagehide", this); 133 } 134 135 this.markup.destroy(); 136 137 this.env = null; 138 this.parent = null; 139 this.markup = null; 140 this.isReady = null; 141 } 142 143 show() { 144 // pagehide may destroy this custom highlighter before its parent Highlighters class 145 if (this._destroyed) { 146 return false; 147 } 148 149 const { pageListenerTarget } = this.env; 150 pageListenerTarget.addEventListener("resize", this._onPageResize); 151 if (this.isFadingViewportHighlighter) { 152 this.parent.highlightersState.fadingViewportSizeHiglighter = this; 153 } else { 154 // If this is handling the regular viewport highlighter (i.e. we want to show rulers) 155 // hide the viewport on resize highlighter we might have. 156 if (this.parent.highlightersState.fadingViewportSizeHiglighter) { 157 this.parent.highlightersState.fadingViewportSizeHiglighter.hide(); 158 } 159 160 // show infobar so that it's not hidden after re-enabling rulers 161 this._showInfobarContainer(); 162 this._update(); 163 } 164 165 return true; 166 } 167 168 _onPageResize() { 169 const { window } = this.env; 170 if (this.isFadingViewportHighlighter) { 171 window.clearTimeout(this.resizeTimer); 172 } 173 this._showInfobarContainer(); 174 this._update(); 175 176 if (this.isFadingViewportHighlighter) { 177 this.resizeTimer = window.setTimeout(() => { 178 this._hideInfobarContainer(); 179 }, this.hideTimeout); 180 } 181 } 182 183 _showInfobarContainer() { 184 this.markup.removeAttributeForElement( 185 "viewport-size-highlighter-viewport-infobar-container", 186 "hidden" 187 ); 188 } 189 190 hide() { 191 const { pageListenerTarget, window } = this.env; 192 pageListenerTarget.removeEventListener("resize", this._onPageResize); 193 this._hideInfobarContainer(); 194 if (this.isFadingViewportHighlighter) { 195 window.clearTimeout(this.resizeTimer); 196 } else if (this.parent.highlightersState?.fadingViewportSizeHiglighter) { 197 // Re-set the viewport on resize highlighter when hiding the rulers 198 this.parent.highlightersState.fadingViewportSizeHiglighter.show(); 199 } 200 } 201 202 _hideInfobarContainer() { 203 this.markup.setAttributeForElement( 204 "viewport-size-highlighter-viewport-infobar-container", 205 "hidden", 206 "true" 207 ); 208 } 209 } 210 exports.ViewportSizeHighlighter = ViewportSizeHighlighter;