2 * Responsive images based on 'srcset' and 'window.devicePixelRatio' emulation where needed.
4 * Call $().hidpi() on a document or part of a document to replace image srcs in that section.
6 * $.devicePixelRatio() can be used to supplement window.devicePixelRatio with support on
7 * some additional browsers.
12 * Detect reported or approximate device pixel ratio.
13 * 1.0 means 1 CSS pixel is 1 hardware pixel
14 * 2.0 means 1 CSS pixel is 2 hardware pixels
17 * Uses window.devicePixelRatio if available, or CSS media queries on IE.
20 * @returns {number} Device pixel ratio
22 $.devicePixelRatio = function () {
23 if ( window.devicePixelRatio !== undefined ) {
25 // * WebKit (Safari, Chrome, Android browser, etc)
28 return window.devicePixelRatio;
29 } else if ( window.msMatchMedia !== undefined ) {
30 // Windows 8 desktops / tablets, probably Windows Phone 8
32 // IE 10 doesn't report pixel ratio directly, but we can get the
33 // screen DPI and divide by 96. We'll bracket to [1, 1.5, 2.0] for
34 // simplicity, but you may get different values depending on zoom
35 // factor, size of screen and orientation in Metro IE.
36 if ( window.msMatchMedia( '(min-resolution: 192dpi)' ).matches ) {
38 } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
45 // Assume 1 if unknown.
51 * Implement responsive images based on srcset attributes, if browser has no
52 * native srcset support.
55 * @returns {jQuery} This selection
57 $.fn.hidpi = function () {
59 // @todo add support for dpi media query checks on Firefox, IE
60 devicePixelRatio = $.devicePixelRatio(),
61 testImage = new Image();
63 if ( devicePixelRatio > 1 && testImage.srcset === undefined ) {
64 // No native srcset support.
65 $target.find( 'img' ).each( function () {
67 srcset = $img.attr( 'srcset' ),
69 if ( typeof srcset === 'string' && srcset !== '' ) {
70 match = $.matchSrcSet( devicePixelRatio, srcset );
71 if (match !== null ) {
72 $img.attr( 'src', match );
82 * Match a srcset entry for the given device pixel ratio
84 * @param {number} devicePixelRatio
85 * @param {string} srcset
86 * @return {mixed} null or the matching src string
88 * Exposed for testing.
90 $.matchSrcSet = function ( devicePixelRatio, srcset ) {
100 candidates = srcset.split( / *, */ );
101 for ( i = 0; i < candidates.length; i++ ) {
102 candidate = candidates[i];
103 bits = candidate.split( / +/ );
105 if ( bits.length > 1 && bits[1].charAt( bits[1].length - 1 ) === 'x' ) {
106 ratioStr = bits[1].substr( 0, bits[1].length - 1 );
107 ratio = parseFloat( ratioStr );
108 if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
109 selectedRatio = ratio;