tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ImageTooltipHelper.js (5435B)


      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 { LocalizationHelper } = require("resource://devtools/shared/l10n.js");
      8 const L10N = new LocalizationHelper(
      9  "devtools/client/locales/inspector.properties"
     10 );
     11 
     12 const XHTML_NS = "http://www.w3.org/1999/xhtml";
     13 
     14 // Default image tooltip max dimension
     15 const MAX_DIMENSION = 200;
     16 const CONTAINER_MIN_WIDTH = 100;
     17 // Should remain synchronized with tooltips.css --image-tooltip-image-padding
     18 const IMAGE_PADDING = 4;
     19 // Should remain synchronized with tooltips.css --image-tooltip-label-height
     20 const LABEL_HEIGHT = 20;
     21 
     22 /**
     23 * Image preview tooltips should be provided with the naturalHeight and
     24 * naturalWidth value for the image to display. This helper loads the provided
     25 * image URL in an image object in order to retrieve the image dimensions after
     26 * the load.
     27 *
     28 * @param {Document} doc the document element to use to create the image object
     29 * @param {string} imageUrl the url of the image to measure
     30 * @return {Promise} returns a promise that will resolve after the iamge load:
     31 *         - {Number} naturalWidth natural width of the loaded image
     32 *         - {Number} naturalHeight natural height of the loaded image
     33 */
     34 function getImageDimensions(doc, imageUrl) {
     35  return new Promise(resolve => {
     36    const imgObj = new doc.defaultView.Image();
     37    imgObj.onload = () => {
     38      imgObj.onload = null;
     39      const { naturalWidth, naturalHeight } = imgObj;
     40      resolve({ naturalWidth, naturalHeight });
     41    };
     42    imgObj.src = imageUrl;
     43  });
     44 }
     45 
     46 /**
     47 * Set the tooltip content of a provided HTMLTooltip instance to display an
     48 * image preview matching the provided imageUrl.
     49 *
     50 * @param {HTMLTooltip} tooltip
     51 *        The tooltip instance on which the image preview content should be set
     52 * @param {Document} doc
     53 *        A document element to create the HTML elements needed for the tooltip
     54 * @param {string} imageUrl
     55 *        Absolute URL of the image to display in the tooltip
     56 * @param {object} options
     57 *        - {Number} naturalWidth mandatory, width of the image to display
     58 *        - {Number} naturalHeight mandatory, height of the image to display
     59 *        - {Number} maxDim optional, max width/height of the preview
     60 *        - {Boolean} hideDimensionLabel optional, pass true to hide the label
     61 *        - {Boolean} hideCheckeredBackground optional, pass true to hide
     62                      the checkered background
     63 */
     64 function setImageTooltip(tooltip, doc, imageUrl, options) {
     65  let {
     66    naturalWidth,
     67    naturalHeight,
     68    hideDimensionLabel,
     69    hideCheckeredBackground,
     70    maxDim,
     71  } = options;
     72  maxDim = maxDim || MAX_DIMENSION;
     73 
     74  let imgHeight = naturalHeight;
     75  let imgWidth = naturalWidth;
     76  if (imgHeight > maxDim || imgWidth > maxDim) {
     77    const scale = maxDim / Math.max(imgHeight, imgWidth);
     78    // Only allow integer values to avoid rounding errors.
     79    imgHeight = Math.floor(scale * naturalHeight);
     80    imgWidth = Math.ceil(scale * naturalWidth);
     81  }
     82 
     83  // Create tooltip content
     84  const container = doc.createElementNS(XHTML_NS, "div");
     85  container.classList.add("devtools-tooltip-image-container");
     86 
     87  const wrapper = doc.createElementNS(XHTML_NS, "div");
     88  wrapper.classList.add("devtools-tooltip-image-wrapper");
     89  container.appendChild(wrapper);
     90 
     91  const img = doc.createElementNS(XHTML_NS, "img");
     92  img.classList.add("devtools-tooltip-image");
     93  img.classList.toggle(
     94    "devtools-checkered-background",
     95    !hideCheckeredBackground
     96  );
     97  img.style.height = imgHeight;
     98  img.src = encodeURI(imageUrl);
     99  wrapper.appendChild(img);
    100 
    101  if (!hideDimensionLabel) {
    102    const dimensions = doc.createElementNS(XHTML_NS, "div");
    103    dimensions.classList.add("devtools-tooltip-image-dimensions");
    104    container.appendChild(dimensions);
    105 
    106    const label = naturalWidth + " \u00D7 " + naturalHeight;
    107    const span = doc.createElementNS(XHTML_NS, "span");
    108    span.classList.add("devtools-tooltip-caption");
    109    span.textContent = label;
    110    dimensions.appendChild(span);
    111  }
    112 
    113  tooltip.panel.innerHTML = "";
    114  tooltip.panel.appendChild(container);
    115 
    116  // Calculate tooltip dimensions
    117  const width = Math.max(CONTAINER_MIN_WIDTH, imgWidth + 2 * IMAGE_PADDING);
    118  let height = imgHeight + 2 * IMAGE_PADDING;
    119  if (!hideDimensionLabel) {
    120    height += parseFloat(LABEL_HEIGHT);
    121  }
    122 
    123  tooltip.setContentSize({ width, height });
    124 }
    125 
    126 /**
    127 * Set the tooltip content of a provided HTMLTooltip instance to display a
    128 * fallback error message when an image preview tooltip can not be displayed.
    129 *
    130 * @param {HTMLTooltip} tooltip
    131 *        The tooltip instance on which the image preview content should be set
    132 * @param {Document} doc
    133 *        A document element to create the HTML elements needed for the tooltip
    134 */
    135 function setBrokenImageTooltip(tooltip, doc) {
    136  const div = doc.createElementNS(XHTML_NS, "div");
    137  div.className = "devtools-tooltip-image-broken";
    138  const message = L10N.getStr("previewTooltip.image.brokenImage");
    139  div.textContent = message;
    140 
    141  tooltip.panel.innerHTML = "";
    142  tooltip.panel.appendChild(div);
    143  tooltip.setContentSize({ width: "auto", height: "auto" });
    144 }
    145 
    146 module.exports.getImageDimensions = getImageDimensions;
    147 module.exports.setImageTooltip = setImageTooltip;
    148 module.exports.setBrokenImageTooltip = setBrokenImageTooltip;