2 * Responsive images based on `srcset` and `window.devicePixelRatio` emulation where needed.
4 * Call `.hidpi()` on a document or part of a document to proces image srcsets within that section.
6 * `$.devicePixelRatio()` can be used as a substitute for `window.devicePixelRatio`.
7 * It provides a familiar interface to retrieve the pixel ratio for browsers that don't
8 * implement `window.devicePixelRatio` but do have a different way of getting it.
10 * @class jQuery.plugin.hidpi
15 * Get reported or approximate device pixel ratio.
17 * - 1.0 means 1 CSS pixel is 1 hardware pixel
18 * - 2.0 means 1 CSS pixel is 2 hardware pixels
21 * Uses `window.devicePixelRatio` if available, or CSS media queries on IE.
25 * @return {number} Device pixel ratio
27 $.devicePixelRatio = function () {
28 if ( window.devicePixelRatio !== undefined ) {
30 // * WebKit (Safari, Chrome, Android browser, etc)
33 return window.devicePixelRatio;
34 } else if ( window.msMatchMedia !== undefined ) {
35 // Windows 8 desktops / tablets, probably Windows Phone 8
37 // IE 10 doesn't report pixel ratio directly, but we can get the
38 // screen DPI and divide by 96. We'll bracket to [1, 1.5, 2.0] for
39 // simplicity, but you may get different values depending on zoom
40 // factor, size of screen and orientation in Metro IE.
41 if ( window.msMatchMedia( '(min-resolution: 192dpi)' ).matches ) {
43 } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
50 // Assume 1 if unknown.
56 * Implement responsive images based on srcset attributes, if browser has no
57 * native srcset support.
59 * @return {jQuery} This selection
62 $.fn.hidpi = function () {
64 // @todo add support for dpi media query checks on Firefox, IE
65 devicePixelRatio = $.devicePixelRatio(),
66 testImage = new Image();
68 if ( devicePixelRatio > 1 && testImage.srcset === undefined ) {
69 // No native srcset support.
70 $target.find( 'img' ).each( function () {
72 srcset = $img.attr( 'srcset' ),
74 if ( typeof srcset === 'string' && srcset !== '' ) {
75 match = $.matchSrcSet( devicePixelRatio, srcset );
76 if ( match !== null ) {
77 $img.attr( 'src', match );
87 * Match a srcset entry for the given device pixel ratio
89 * Exposed for testing.
93 * @param {number} devicePixelRatio
94 * @param {string} srcset
95 * @return {Mixed} null or the matching src string
97 $.matchSrcSet = function ( devicePixelRatio, srcset ) {
107 candidates = srcset.split( / *, */ );
108 for ( i = 0; i < candidates.length; i++ ) {
109 candidate = candidates[i];
110 bits = candidate.split( / +/ );
112 if ( bits.length > 1 && bits[1].charAt( bits[1].length - 1 ) === 'x' ) {
113 ratioStr = bits[1].slice( 0, -1 );
114 ratio = parseFloat( ratioStr );
115 if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
116 selectedRatio = ratio;
126 * @mixins jQuery.plugin.hidpi