Merge "Addition of a parser test for page= parameter of image inclusion"
[lhc/web/wiklou.git] / resources / src / jquery / jquery.hidpi.js
1 /**
2 * Responsive images based on `srcset` and `window.devicePixelRatio` emulation where needed.
3 *
4 * Call `.hidpi()` on a document or part of a document to proces image srcsets within that section.
5 *
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.
9 *
10 * @class jQuery.plugin.hidpi
11 */
12 ( function ( $ ) {
13
14 /**
15 * Get reported or approximate device pixel ratio.
16 *
17 * - 1.0 means 1 CSS pixel is 1 hardware pixel
18 * - 2.0 means 1 CSS pixel is 2 hardware pixels
19 * - etc.
20 *
21 * Uses `window.devicePixelRatio` if available, or CSS media queries on IE.
22 *
23 * @static
24 * @return {number} Device pixel ratio
25 */
26 $.devicePixelRatio = function () {
27 if ( window.devicePixelRatio !== undefined ) {
28 // Most web browsers:
29 // * WebKit (Safari, Chrome, Android browser, etc)
30 // * Opera
31 // * Firefox 18+
32 return window.devicePixelRatio;
33 } else if ( window.msMatchMedia !== undefined ) {
34 // Windows 8 desktops / tablets, probably Windows Phone 8
35 //
36 // IE 10 doesn't report pixel ratio directly, but we can get the
37 // screen DPI and divide by 96. We'll bracket to [1, 1.5, 2.0] for
38 // simplicity, but you may get different values depending on zoom
39 // factor, size of screen and orientation in Metro IE.
40 if ( window.msMatchMedia( '(min-resolution: 192dpi)' ).matches ) {
41 return 2;
42 } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
43 return 1.5;
44 } else {
45 return 1;
46 }
47 } else {
48 // Legacy browsers...
49 // Assume 1 if unknown.
50 return 1;
51 }
52 };
53
54 /**
55 * Implement responsive images based on srcset attributes, if browser has no
56 * native srcset support.
57 *
58 * @return {jQuery} This selection
59 * @chainable
60 */
61 $.fn.hidpi = function () {
62 var $target = this,
63 // @todo add support for dpi media query checks on Firefox, IE
64 devicePixelRatio = $.devicePixelRatio(),
65 testImage = new Image();
66
67 if ( devicePixelRatio > 1 && testImage.srcset === undefined ) {
68 // No native srcset support.
69 $target.find( 'img' ).each( function () {
70 var $img = $( this ),
71 srcset = $img.attr( 'srcset' ),
72 match;
73 if ( typeof srcset === 'string' && srcset !== '' ) {
74 match = $.matchSrcSet( devicePixelRatio, srcset );
75 if (match !== null ) {
76 $img.attr( 'src', match );
77 }
78 }
79 });
80 }
81
82 return $target;
83 };
84
85 /**
86 * Match a srcset entry for the given device pixel ratio
87 *
88 * Exposed for testing.
89 *
90 * @private
91 * @static
92 * @param {number} devicePixelRatio
93 * @param {string} srcset
94 * @return {Mixed} null or the matching src string
95 */
96 $.matchSrcSet = function ( devicePixelRatio, srcset ) {
97 var candidates,
98 candidate,
99 bits,
100 src,
101 i,
102 ratioStr,
103 ratio,
104 selectedRatio = 1,
105 selectedSrc = null;
106 candidates = srcset.split( / *, */ );
107 for ( i = 0; i < candidates.length; i++ ) {
108 candidate = candidates[i];
109 bits = candidate.split( / +/ );
110 src = bits[0];
111 if ( bits.length > 1 && bits[1].charAt( bits[1].length - 1 ) === 'x' ) {
112 ratioStr = bits[1].substr( 0, bits[1].length - 1 );
113 ratio = parseFloat( ratioStr );
114 if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
115 selectedRatio = ratio;
116 selectedSrc = src;
117 }
118 }
119 }
120 return selectedSrc;
121 };
122
123 /**
124 * @class jQuery
125 * @mixins jQuery.plugin.hidpi
126 */
127
128 }( jQuery ) );