[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/dist/vendor/ -> wp-polyfill-object-fit.js (source)

   1  /*----------------------------------------
   2   * objectFitPolyfill 2.3.5
   3   *
   4   * Made by Constance Chen
   5   * Released under the ISC license
   6   *
   7   * https://github.com/constancecchen/object-fit-polyfill
   8   *--------------------------------------*/
   9  
  10  (function() {
  11    'use strict';
  12  
  13    // if the page is being rendered on the server, don't continue
  14    if (typeof window === 'undefined') return;
  15  
  16    // Workaround for Edge 16-18, which only implemented object-fit for <img> tags
  17    var edgeMatch = window.navigator.userAgent.match(/Edge\/(\d{2})\./);
  18    var edgeVersion = edgeMatch ? parseInt(edgeMatch[1], 10) : null;
  19    var edgePartialSupport = edgeVersion
  20      ? edgeVersion >= 16 && edgeVersion <= 18
  21      : false;
  22  
  23    // If the browser does support object-fit, we don't need to continue
  24    var hasSupport = 'objectFit' in document.documentElement.style !== false;
  25    if (hasSupport && !edgePartialSupport) {
  26      window.objectFitPolyfill = function() {
  27        return false;
  28      };
  29      return;
  30    }
  31  
  32    /**
  33     * Check the container's parent element to make sure it will
  34     * correctly handle and clip absolutely positioned children
  35     *
  36     * @param {node} $container - parent element
  37     */
  38    var checkParentContainer = function($container) {
  39      var styles = window.getComputedStyle($container, null);
  40      var position = styles.getPropertyValue('position');
  41      var overflow = styles.getPropertyValue('overflow');
  42      var display = styles.getPropertyValue('display');
  43  
  44      if (!position || position === 'static') {
  45        $container.style.position = 'relative';
  46      }
  47      if (overflow !== 'hidden') {
  48        $container.style.overflow = 'hidden';
  49      }
  50      // Guesstimating that people want the parent to act like full width/height wrapper here.
  51      // Mostly attempts to target <picture> elements, which default to inline.
  52      if (!display || display === 'inline') {
  53        $container.style.display = 'block';
  54      }
  55      if ($container.clientHeight === 0) {
  56        $container.style.height = '100%';
  57      }
  58  
  59      // Add a CSS class hook, in case people need to override styles for any reason.
  60      if ($container.className.indexOf('object-fit-polyfill') === -1) {
  61        $container.className = $container.className + ' object-fit-polyfill';
  62      }
  63    };
  64  
  65    /**
  66     * Check for pre-set max-width/height, min-width/height,
  67     * positioning, or margins, which can mess up image calculations
  68     *
  69     * @param {node} $media - img/video element
  70     */
  71    var checkMediaProperties = function($media) {
  72      var styles = window.getComputedStyle($media, null);
  73      var constraints = {
  74        'max-width': 'none',
  75        'max-height': 'none',
  76        'min-width': '0px',
  77        'min-height': '0px',
  78        top: 'auto',
  79        right: 'auto',
  80        bottom: 'auto',
  81        left: 'auto',
  82        'margin-top': '0px',
  83        'margin-right': '0px',
  84        'margin-bottom': '0px',
  85        'margin-left': '0px',
  86      };
  87  
  88      for (var property in constraints) {
  89        var constraint = styles.getPropertyValue(property);
  90  
  91        if (constraint !== constraints[property]) {
  92          $media.style[property] = constraints[property];
  93        }
  94      }
  95    };
  96  
  97    /**
  98     * Calculate & set object-position
  99     *
 100     * @param {string} axis - either "x" or "y"
 101     * @param {node} $media - img or video element
 102     * @param {string} objectPosition - e.g. "50% 50%", "top left"
 103     */
 104    var setPosition = function(axis, $media, objectPosition) {
 105      var position, other, start, end, side;
 106      objectPosition = objectPosition.split(' ');
 107  
 108      if (objectPosition.length < 2) {
 109        objectPosition[1] = objectPosition[0];
 110      }
 111  
 112      /* istanbul ignore else */
 113      if (axis === 'x') {
 114        position = objectPosition[0];
 115        other = objectPosition[1];
 116        start = 'left';
 117        end = 'right';
 118        side = $media.clientWidth;
 119      } else if (axis === 'y') {
 120        position = objectPosition[1];
 121        other = objectPosition[0];
 122        start = 'top';
 123        end = 'bottom';
 124        side = $media.clientHeight;
 125      } else {
 126        return; // Neither x or y axis specified
 127      }
 128  
 129      if (position === start || other === start) {
 130        $media.style[start] = '0';
 131        return;
 132      }
 133  
 134      if (position === end || other === end) {
 135        $media.style[end] = '0';
 136        return;
 137      }
 138  
 139      if (position === 'center' || position === '50%') {
 140        $media.style[start] = '50%';
 141        $media.style['margin-' + start] = side / -2 + 'px';
 142        return;
 143      }
 144  
 145      // Percentage values (e.g., 30% 10%)
 146      if (position.indexOf('%') >= 0) {
 147        position = parseInt(position, 10);
 148  
 149        if (position < 50) {
 150          $media.style[start] = position + '%';
 151          $media.style['margin-' + start] = side * (position / -100) + 'px';
 152        } else {
 153          position = 100 - position;
 154          $media.style[end] = position + '%';
 155          $media.style['margin-' + end] = side * (position / -100) + 'px';
 156        }
 157  
 158        return;
 159      }
 160      // Length-based values (e.g. 10px / 10em)
 161      else {
 162        $media.style[start] = position;
 163      }
 164    };
 165  
 166    /**
 167     * Calculate & set object-fit
 168     *
 169     * @param {node} $media - img/video/picture element
 170     */
 171    var objectFit = function($media) {
 172      // IE 10- data polyfill
 173      var fit = $media.dataset
 174        ? $media.dataset.objectFit
 175        : $media.getAttribute('data-object-fit');
 176      var position = $media.dataset
 177        ? $media.dataset.objectPosition
 178        : $media.getAttribute('data-object-position');
 179  
 180      // Default fallbacks
 181      fit = fit || 'cover';
 182      position = position || '50% 50%';
 183  
 184      // If necessary, make the parent container work with absolutely positioned elements
 185      var $container = $media.parentNode;
 186      checkParentContainer($container);
 187  
 188      // Check for any pre-set CSS which could mess up image calculations
 189      checkMediaProperties($media);
 190  
 191      // Reset any pre-set width/height CSS and handle fit positioning
 192      $media.style.position = 'absolute';
 193      $media.style.width = 'auto';
 194      $media.style.height = 'auto';
 195  
 196      // `scale-down` chooses either `none` or `contain`, whichever is smaller
 197      if (fit === 'scale-down') {
 198        if (
 199          $media.clientWidth < $container.clientWidth &&
 200          $media.clientHeight < $container.clientHeight
 201        ) {
 202          fit = 'none';
 203        } else {
 204          fit = 'contain';
 205        }
 206      }
 207  
 208      // `none` (width/height auto) and `fill` (100%) and are straightforward
 209      if (fit === 'none') {
 210        setPosition('x', $media, position);
 211        setPosition('y', $media, position);
 212        return;
 213      }
 214  
 215      if (fit === 'fill') {
 216        $media.style.width = '100%';
 217        $media.style.height = '100%';
 218        setPosition('x', $media, position);
 219        setPosition('y', $media, position);
 220        return;
 221      }
 222  
 223      // `cover` and `contain` must figure out which side needs covering, and add CSS positioning & centering
 224      $media.style.height = '100%';
 225  
 226      if (
 227        (fit === 'cover' && $media.clientWidth > $container.clientWidth) ||
 228        (fit === 'contain' && $media.clientWidth < $container.clientWidth)
 229      ) {
 230        $media.style.top = '0';
 231        $media.style.marginTop = '0';
 232        setPosition('x', $media, position);
 233      } else {
 234        $media.style.width = '100%';
 235        $media.style.height = 'auto';
 236        $media.style.left = '0';
 237        $media.style.marginLeft = '0';
 238        setPosition('y', $media, position);
 239      }
 240    };
 241  
 242    /**
 243     * Initialize plugin
 244     *
 245     * @param {node} media - Optional specific DOM node(s) to be polyfilled
 246     */
 247    var objectFitPolyfill = function(media) {
 248      if (typeof media === 'undefined' || media instanceof Event) {
 249        // If left blank, or a default event, all media on the page will be polyfilled.
 250        media = document.querySelectorAll('[data-object-fit]');
 251      } else if (media && media.nodeName) {
 252        // If it's a single node, wrap it in an array so it works.
 253        media = [media];
 254      } else if (typeof media === 'object' && media.length && media[0].nodeName) {
 255        // If it's an array of DOM nodes (e.g. a jQuery selector), it's fine as-is.
 256        media = media;
 257      } else {
 258        // Otherwise, if it's invalid or an incorrect type, return false to let people know.
 259        return false;
 260      }
 261  
 262      for (var i = 0; i < media.length; i++) {
 263        if (!media[i].nodeName) continue;
 264  
 265        var mediaType = media[i].nodeName.toLowerCase();
 266  
 267        if (mediaType === 'img') {
 268          if (edgePartialSupport) continue; // Edge supports object-fit for images (but nothing else), so no need to polyfill
 269  
 270          if (media[i].complete) {
 271            objectFit(media[i]);
 272          } else {
 273            media[i].addEventListener('load', function() {
 274              objectFit(this);
 275            });
 276          }
 277        } else if (mediaType === 'video') {
 278          if (media[i].readyState > 0) {
 279            objectFit(media[i]);
 280          } else {
 281            media[i].addEventListener('loadedmetadata', function() {
 282              objectFit(this);
 283            });
 284          }
 285        } else {
 286          objectFit(media[i]);
 287        }
 288      }
 289  
 290      return true;
 291    };
 292  
 293    if (document.readyState === 'loading') {
 294      // Loading hasn't finished yet
 295      document.addEventListener('DOMContentLoaded', objectFitPolyfill);
 296    } else {
 297      // `DOMContentLoaded` has already fired
 298      objectFitPolyfill();
 299    }
 300  
 301    window.addEventListener('resize', objectFitPolyfill);
 302  
 303    window.objectFitPolyfill = objectFitPolyfill;
 304  })();


Generated : Thu Apr 18 08:20:02 2024 Cross-referenced by PHPXref