[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
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 })();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Thu Nov 21 08:20:01 2024 | Cross-referenced by PHPXref |