summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js')
-rw-r--r--devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js145
1 files changed, 145 insertions, 0 deletions
diff --git a/devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js b/devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js
new file mode 100644
index 0000000000..c73bd4b6b6
--- /dev/null
+++ b/devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js
@@ -0,0 +1,145 @@
+/* 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;