/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; const { LocalizationHelper } = require("resource://devtools/shared/l10n.js"); const L10N = new LocalizationHelper( "devtools/client/locales/inspector.properties" ); const XHTML_NS = "http://www.w3.org/1999/xhtml"; // Default image tooltip max dimension const MAX_DIMENSION = 200; const CONTAINER_MIN_WIDTH = 100; // Should remain synchronized with tooltips.css --image-tooltip-image-padding const IMAGE_PADDING = 4; // Should remain synchronized with tooltips.css --image-tooltip-label-height const LABEL_HEIGHT = 20; /** * Image preview tooltips should be provided with the naturalHeight and * naturalWidth value for the image to display. This helper loads the provided * image URL in an image object in order to retrieve the image dimensions after * the load. * * @param {Document} doc the document element to use to create the image object * @param {String} imageUrl the url of the image to measure * @return {Promise} returns a promise that will resolve after the iamge load: * - {Number} naturalWidth natural width of the loaded image * - {Number} naturalHeight natural height of the loaded image */ function getImageDimensions(doc, imageUrl) { return new Promise(resolve => { const imgObj = new doc.defaultView.Image(); imgObj.onload = () => { imgObj.onload = null; const { naturalWidth, naturalHeight } = imgObj; resolve({ naturalWidth, naturalHeight }); }; imgObj.src = imageUrl; }); } /** * Set the tooltip content of a provided HTMLTooltip instance to display an * image preview matching the provided imageUrl. * * @param {HTMLTooltip} tooltip * The tooltip instance on which the image preview content should be set * @param {Document} doc * A document element to create the HTML elements needed for the tooltip * @param {String} imageUrl * Absolute URL of the image to display in the tooltip * @param {Object} options * - {Number} naturalWidth mandatory, width of the image to display * - {Number} naturalHeight mandatory, height of the image to display * - {Number} maxDim optional, max width/height of the preview * - {Boolean} hideDimensionLabel optional, pass true to hide the label * - {Boolean} hideCheckeredBackground optional, pass true to hide the checkered background */ function setImageTooltip(tooltip, doc, imageUrl, options) { let { naturalWidth, naturalHeight, hideDimensionLabel, hideCheckeredBackground, maxDim, } = options; maxDim = maxDim || MAX_DIMENSION; let imgHeight = naturalHeight; let imgWidth = naturalWidth; if (imgHeight > maxDim || imgWidth > maxDim) { const scale = maxDim / Math.max(imgHeight, imgWidth); // Only allow integer values to avoid rounding errors. imgHeight = Math.floor(scale * naturalHeight); imgWidth = Math.ceil(scale * naturalWidth); } // Create tooltip content const container = doc.createElementNS(XHTML_NS, "div"); container.classList.add("devtools-tooltip-image-container"); const wrapper = doc.createElementNS(XHTML_NS, "div"); wrapper.classList.add("devtools-tooltip-image-wrapper"); container.appendChild(wrapper); const img = doc.createElementNS(XHTML_NS, "img"); img.classList.add("devtools-tooltip-image"); img.classList.toggle("devtools-tooltip-tiles", !hideCheckeredBackground); img.style.height = imgHeight; img.src = encodeURI(imageUrl); wrapper.appendChild(img); if (!hideDimensionLabel) { const dimensions = doc.createElementNS(XHTML_NS, "div"); dimensions.classList.add("devtools-tooltip-image-dimensions"); container.appendChild(dimensions); const label = naturalWidth + " \u00D7 " + naturalHeight; const span = doc.createElementNS(XHTML_NS, "span"); span.classList.add("devtools-tooltip-caption"); span.textContent = label; dimensions.appendChild(span); } tooltip.panel.innerHTML = ""; tooltip.panel.appendChild(container); // Calculate tooltip dimensions const width = Math.max(CONTAINER_MIN_WIDTH, imgWidth + 2 * IMAGE_PADDING); let height = imgHeight + 2 * IMAGE_PADDING; if (!hideDimensionLabel) { height += parseFloat(LABEL_HEIGHT); } tooltip.setContentSize({ width, height }); } /* * Set the tooltip content of a provided HTMLTooltip instance to display a * fallback error message when an image preview tooltip can not be displayed. * * @param {HTMLTooltip} tooltip * The tooltip instance on which the image preview content should be set * @param {Document} doc * A document element to create the HTML elements needed for the tooltip */ function setBrokenImageTooltip(tooltip, doc) { const div = doc.createElementNS(XHTML_NS, "div"); div.className = "devtools-tooltip-image-broken"; const message = L10N.getStr("previewTooltip.image.brokenImage"); div.textContent = message; tooltip.panel.innerHTML = ""; tooltip.panel.appendChild(div); tooltip.setContentSize({ width: "auto", height: "auto" }); } module.exports.getImageDimensions = getImageDimensions; module.exports.setImageTooltip = setImageTooltip; module.exports.setBrokenImageTooltip = setBrokenImageTooltip;