-/**
- * Responsive images based on `srcset` and `window.devicePixelRatio` emulation where needed.
- *
- * Call `.hidpi()` on a document or part of a document to proces image srcsets within that section.
- *
- * `$.devicePixelRatio()` can be used as a substitute for `window.devicePixelRatio`.
- * It provides a familiar interface to retrieve the pixel ratio for browsers that don't
- * implement `window.devicePixelRatio` but do have a different way of getting it.
- *
- * @class jQuery.plugin.hidpi
- */
-( function () {
-
- /**
- * Get reported or approximate device pixel ratio.
- *
- * - 1.0 means 1 CSS pixel is 1 hardware pixel
- * - 2.0 means 1 CSS pixel is 2 hardware pixels
- * - etc.
- *
- * Uses `window.devicePixelRatio` if available, or CSS media queries on IE.
- *
- * @static
- * @inheritable
- * @return {number} Device pixel ratio
- */
- $.devicePixelRatio = function () {
- if ( window.devicePixelRatio !== undefined ) {
- // Most web browsers:
- // * WebKit/Blink (Safari, Chrome, Android browser, etc)
- // * Opera
- // * Firefox 18+
- // * Microsoft Edge (Windows 10)
- return window.devicePixelRatio;
- } else if ( window.msMatchMedia !== undefined ) {
- // Windows 8 desktops / tablets, probably Windows Phone 8
- //
- // IE 10/11 doesn't report pixel ratio directly, but we can get the
- // screen DPI and divide by 96. We'll bracket to [1, 1.5, 2.0] for
- // simplicity, but you may get different values depending on zoom
- // factor, size of screen and orientation in Metro IE.
- if ( window.msMatchMedia( '(min-resolution: 192dpi)' ).matches ) {
- return 2;
- } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
- return 1.5;
- } else {
- return 1;
- }
- } else {
- // Legacy browsers...
- // Assume 1 if unknown.
- return 1;
- }
- };
-
- /**
- * Bracket a given device pixel ratio to one of [1, 1.5, 2].
- *
- * This is useful for grabbing images on the fly with sizes based on the display
- * density, without causing slowdown and extra thumbnail renderings on devices
- * that are slightly different from the most common sizes.
- *
- * The bracketed ratios match the default 'srcset' output on MediaWiki thumbnails,
- * so will be consistent with default renderings.
- *
- * @static
- * @inheritable
- * @param {number} baseRatio Base ratio
- * @return {number} Device pixel ratio
- */
- $.bracketDevicePixelRatio = function ( baseRatio ) {
- if ( baseRatio > 1.5 ) {
- return 2;
- } else if ( baseRatio > 1 ) {
- return 1.5;
- } else {
- return 1;
- }
- };
-
- /**
- * Get reported or approximate device pixel ratio, bracketed to [1, 1.5, 2].
- *
- * This is useful for grabbing images on the fly with sizes based on the display
- * density, without causing slowdown and extra thumbnail renderings on devices
- * that are slightly different from the most common sizes.
- *
- * The bracketed ratios match the default 'srcset' output on MediaWiki thumbnails,
- * so will be consistent with default renderings.
- *
- * - 1.0 means 1 CSS pixel is 1 hardware pixel
- * - 1.5 means 1 CSS pixel is 1.5 hardware pixels
- * - 2.0 means 1 CSS pixel is 2 hardware pixels
- *
- * @static
- * @inheritable
- * @return {number} Device pixel ratio
- */
- $.bracketedDevicePixelRatio = function () {
- return $.bracketDevicePixelRatio( $.devicePixelRatio() );
- };
-
- /**
- * Implement responsive images based on srcset attributes, if browser has no
- * native srcset support.
- *
- * @return {jQuery} This selection
- * @chainable
- */
- $.fn.hidpi = function () {
- var $target = this,
- // TODO add support for dpi media query checks on Firefox, IE
- devicePixelRatio = $.devicePixelRatio(),
- testImage = new Image();
-
- if ( devicePixelRatio > 1 && testImage.srcset === undefined ) {
- // No native srcset support.
- $target.find( 'img' ).each( function () {
- var $img = $( this ),
- srcset = $img.attr( 'srcset' ),
- match;
- if ( typeof srcset === 'string' && srcset !== '' ) {
- match = $.matchSrcSet( devicePixelRatio, srcset );
- if ( match !== null ) {
- $img.attr( 'src', match );
- }
- }
- } );
- }
-
- return $target;
- };
-
- /**
- * Match a srcset entry for the given device pixel ratio
- *
- * Exposed for testing.
- *
- * @private
- * @static
- * @param {number} devicePixelRatio
- * @param {string} srcset
- * @return {Mixed} null or the matching src string
- */
- $.matchSrcSet = function ( devicePixelRatio, srcset ) {
- var candidates,
- candidate,
- bits,
- src,
- i,
- ratioStr,
- ratio,
- selectedRatio = 1,
- selectedSrc = null;
- candidates = srcset.split( / *, */ );
- for ( i = 0; i < candidates.length; i++ ) {
- candidate = candidates[ i ];
- bits = candidate.split( / +/ );
- src = bits[ 0 ];
- if ( bits.length > 1 && bits[ 1 ].charAt( bits[ 1 ].length - 1 ) === 'x' ) {
- ratioStr = bits[ 1 ].slice( 0, -1 );
- ratio = parseFloat( ratioStr );
- if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
- selectedRatio = ratio;
- selectedSrc = src;
- }
- }
- }
- return selectedSrc;
- };
-
- /**
- * @class jQuery
- * @mixins jQuery.plugin.hidpi
- */
-
-}() );