Merge "Add ss_active_users in SiteStats::isSane"
[mediawiki.git] / resources / jquery / jquery.hidpi.js
blob70bfc4ea3c664570102bd697140912fedfd98373
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 replace image srcs in that section.
5  *
6  * $.devicePixelRatio() can be used to supplement window.devicePixelRatio with support on
7  * some additional browsers.
8  */
9 ( function ( $ ) {
11 /**
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
15  * etc
16  *
17  * Uses window.devicePixelRatio if available, or CSS media queries on IE.
18  *
19  * @method
20  * @returns {number} Device pixel ratio
21  */
22 $.devicePixelRatio = function () {
23         if ( window.devicePixelRatio !== undefined ) {
24                 // Most web browsers:
25                 // * WebKit (Safari, Chrome, Android browser, etc)
26                 // * Opera
27                 // * Firefox 18+
28                 return window.devicePixelRatio;
29         } else if ( window.msMatchMedia !== undefined ) {
30                 // Windows 8 desktops / tablets, probably Windows Phone 8
31                 //
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 ) {
37                         return 2;
38                 } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
39                         return 1.5;
40                 } else {
41                         return 1;
42                 }
43         } else {
44                 // Legacy browsers...
45                 // Assume 1 if unknown.
46                 return 1;
47         }
50 /**
51  * Implement responsive images based on srcset attributes, if browser has no
52  * native srcset support.
53  *
54  * @method
55  * @returns {jQuery} This selection
56  */
57 $.fn.hidpi = function () {
58         var $target = this,
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 () {
66                         var $img = $( this ),
67                                 srcset = $img.attr( 'srcset' ),
68                                 match;
69                         if ( typeof srcset === 'string' && srcset !== '' ) {
70                                 match = $.matchSrcSet( devicePixelRatio, srcset );
71                                 if (match !== null ) {
72                                         $img.attr( 'src', match );
73                                 }
74                         }
75                 });
76         }
78         return $target;
81 /**
82  * Match a srcset entry for the given device pixel ratio
83  *
84  * @param {number} devicePixelRatio
85  * @param {string} srcset
86  * @return {mixed} null or the matching src string
87  *
88  * Exposed for testing.
89  */
90 $.matchSrcSet = function ( devicePixelRatio, srcset ) {
91         var candidates,
92                 candidate,
93                 bits,
94                 src,
95                 i,
96                 ratioStr,
97                 ratio,
98                 selectedRatio = 1,
99                 selectedSrc = null;
100         candidates = srcset.split( / *, */ );
101         for ( i = 0; i < candidates.length; i++ ) {
102                 candidate = candidates[i];
103                 bits = candidate.split( / +/ );
104                 src = bits[0];
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;
110                                 selectedSrc = src;
111                         }
112                 }
113         }
114         return selectedSrc;
117 }( jQuery ) );