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
;