+++ /dev/null
-/**
- * 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
- */
-
-}() );
+++ /dev/null
-( function () {
- QUnit.module( 'jquery.hidpi', QUnit.newMwEnvironment() );
-
- QUnit.test( 'devicePixelRatio', function ( assert ) {
- var devicePixelRatio = $.devicePixelRatio();
- assert.strictEqual( typeof devicePixelRatio, 'number', '$.devicePixelRatio() returns a number' );
- } );
-
- QUnit.test( 'bracketedDevicePixelRatio', function ( assert ) {
- var ratio = $.bracketedDevicePixelRatio();
- assert.strictEqual( typeof ratio, 'number', '$.bracketedDevicePixelRatio() returns a number' );
- } );
-
- QUnit.test( 'bracketDevicePixelRatio', function ( assert ) {
- assert.strictEqual( $.bracketDevicePixelRatio( 0.75 ), 1, '0.75 gives 1' );
- assert.strictEqual( $.bracketDevicePixelRatio( 1 ), 1, '1 gives 1' );
- assert.strictEqual( $.bracketDevicePixelRatio( 1.25 ), 1.5, '1.25 gives 1.5' );
- assert.strictEqual( $.bracketDevicePixelRatio( 1.5 ), 1.5, '1.5 gives 1.5' );
- assert.strictEqual( $.bracketDevicePixelRatio( 1.75 ), 2, '1.75 gives 2' );
- assert.strictEqual( $.bracketDevicePixelRatio( 2 ), 2, '2 gives 2' );
- assert.strictEqual( $.bracketDevicePixelRatio( 2.5 ), 2, '2.5 gives 2' );
- assert.strictEqual( $.bracketDevicePixelRatio( 3 ), 2, '3 gives 2' );
- } );
-
- QUnit.test( 'matchSrcSet', function ( assert ) {
- var srcset = 'onefive.png 1.5x, two.png 2x';
-
- // Nice exact matches
- assert.strictEqual( $.matchSrcSet( 1, srcset ), null, '1.0 gives no match' );
- assert.strictEqual( $.matchSrcSet( 1.5, srcset ), 'onefive.png', '1.5 gives match' );
- assert.strictEqual( $.matchSrcSet( 2, srcset ), 'two.png', '2 gives match' );
-
- // Non-exact matches; should return the next-biggest specified
- assert.strictEqual( $.matchSrcSet( 1.25, srcset ), null, '1.25 gives no match' );
- assert.strictEqual( $.matchSrcSet( 1.75, srcset ), 'onefive.png', '1.75 gives match to 1.5' );
- assert.strictEqual( $.matchSrcSet( 2.25, srcset ), 'two.png', '2.25 gives match to 2' );
- } );
-}() );