Merge "Fixed dependencies for jquery.collapsibleTabs"
[lhc/web/wiklou.git] / resources / 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 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 ( $ ) {
10
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 }
48 };
49
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();
62
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 }
77
78 return $target;
79 };
80
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 ) {
109 // Too big, skip!
110 } else if ( ratio > selectedRatio ) {
111 selectedRatio = ratio;
112 selectedSrc = src;
113 }
114 }
115 }
116 return selectedSrc;
117 };
118
119 }( jQuery ) );