jumbo-jekyll-theme-test 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +26 -0
  4. data/_config.yml +122 -0
  5. data/_data/authors.yml +7 -0
  6. data/_data/footer.yml +55 -0
  7. data/_data/nav.yml +77 -0
  8. data/_data/news.yaml +230 -0
  9. data/_data/settings.yml +148 -0
  10. data/_data/sidebar-nav.yml +23 -0
  11. data/_data/sticky-tab-bar.yml +29 -0
  12. data/_includes/breadcrumb.html +97 -0
  13. data/_includes/css.html +9 -0
  14. data/_includes/custom.html +1 -0
  15. data/_includes/display-blog-posts.html +67 -0
  16. data/_includes/disqus-comments.html +14 -0
  17. data/_includes/footer.html +70 -0
  18. data/_includes/github-edit.html +73 -0
  19. data/_includes/google-analytics-script.html +9 -0
  20. data/_includes/gtm-noscript.html +5 -0
  21. data/_includes/gtm-script.html +7 -0
  22. data/_includes/head.html +44 -0
  23. data/_includes/hero-banner.html +21 -0
  24. data/_includes/image.html +6 -0
  25. data/_includes/javascript.html +9 -0
  26. data/_includes/jumbotron.html +87 -0
  27. data/_includes/linaro-404.html +13 -0
  28. data/_includes/linaro-svg.html +1 -0
  29. data/_includes/media.html +11 -0
  30. data/_includes/members.html +63 -0
  31. data/_includes/nav.html +132 -0
  32. data/_includes/newsletter-script.html +30 -0
  33. data/_includes/owl-carousel-homepage.html +103 -0
  34. data/_includes/pagination-authors.html +36 -0
  35. data/_includes/pagination-news.html +36 -0
  36. data/_includes/pagination.html +36 -0
  37. data/_includes/post-comments.html +9 -0
  38. data/_includes/post-sidebar.html +74 -0
  39. data/_includes/post-tags.html +9 -0
  40. data/_includes/schema.html +50 -0
  41. data/_includes/shape-divider.html +12 -0
  42. data/_includes/shape.html +52 -0
  43. data/_includes/sidebar.html +55 -0
  44. data/_includes/sticky-tab-bar.html +63 -0
  45. data/_includes/universal-nav.html +28 -0
  46. data/_includes/youtube.html +7 -0
  47. data/_layouts/container-breadcrumb-left-sidebar.html +10 -0
  48. data/_layouts/container-breadcrumb-right-sidebar.html +9 -0
  49. data/_layouts/container-breadcrumb-tabs.html +7 -0
  50. data/_layouts/container-breadcrumb.html +6 -0
  51. data/_layouts/container-left-sidebar.html +9 -0
  52. data/_layouts/container-right-sidebar.html +9 -0
  53. data/_layouts/container.html +9 -0
  54. data/_layouts/default.html +31 -0
  55. data/_layouts/full-width-breadcrumb.html +10 -0
  56. data/_layouts/full-width.html +9 -0
  57. data/_layouts/home.html +21 -0
  58. data/_layouts/post-index.html +19 -0
  59. data/_layouts/post-no-sidebar.html +0 -0
  60. data/_layouts/post-old.html +70 -0
  61. data/_layouts/post.html +240 -0
  62. data/_sass/_bootstrap-compass.scss +9 -0
  63. data/_sass/_bootstrap-mincer.scss +19 -0
  64. data/_sass/_bootstrap-sprockets.scss +9 -0
  65. data/_sass/_bootstrap.scss +56 -0
  66. data/_sass/app/blog.scss +58 -0
  67. data/_sass/app/contact.scss +3 -0
  68. data/_sass/app/custom.scss +1 -0
  69. data/_sass/app/home.scss +18 -0
  70. data/_sass/app/overrides.scss +36 -0
  71. data/_sass/app/search.scss +1 -0
  72. data/_sass/blog.scss +9 -0
  73. data/_sass/bootstrap/_alerts.scss +73 -0
  74. data/_sass/bootstrap/_badges.scss +68 -0
  75. data/_sass/bootstrap/_breadcrumbs.scss +28 -0
  76. data/_sass/bootstrap/_button-groups.scss +244 -0
  77. data/_sass/bootstrap/_buttons.scss +168 -0
  78. data/_sass/bootstrap/_carousel.scss +270 -0
  79. data/_sass/bootstrap/_close.scss +36 -0
  80. data/_sass/bootstrap/_code.scss +69 -0
  81. data/_sass/bootstrap/_component-animations.scss +37 -0
  82. data/_sass/bootstrap/_dropdowns.scss +216 -0
  83. data/_sass/bootstrap/_forms.scss +617 -0
  84. data/_sass/bootstrap/_glyphicons.scss +307 -0
  85. data/_sass/bootstrap/_grid.scss +84 -0
  86. data/_sass/bootstrap/_input-groups.scss +171 -0
  87. data/_sass/bootstrap/_jumbotron.scss +54 -0
  88. data/_sass/bootstrap/_labels.scss +66 -0
  89. data/_sass/bootstrap/_list-group.scss +130 -0
  90. data/_sass/bootstrap/_media.scss +66 -0
  91. data/_sass/bootstrap/_mixins.scss +40 -0
  92. data/_sass/bootstrap/_modals.scss +150 -0
  93. data/_sass/bootstrap/_navbar.scss +662 -0
  94. data/_sass/bootstrap/_navs.scss +242 -0
  95. data/_sass/bootstrap/_normalize.scss +424 -0
  96. data/_sass/bootstrap/_pager.scss +54 -0
  97. data/_sass/bootstrap/_pagination.scss +89 -0
  98. data/_sass/bootstrap/_panels.scss +271 -0
  99. data/_sass/bootstrap/_popovers.scss +131 -0
  100. data/_sass/bootstrap/_print.scss +101 -0
  101. data/_sass/bootstrap/_progress-bars.scss +87 -0
  102. data/_sass/bootstrap/_responsive-embed.scss +35 -0
  103. data/_sass/bootstrap/_responsive-utilities.scss +179 -0
  104. data/_sass/bootstrap/_scaffolding.scss +161 -0
  105. data/_sass/bootstrap/_tables.scss +234 -0
  106. data/_sass/bootstrap/_theme.scss +291 -0
  107. data/_sass/bootstrap/_thumbnails.scss +38 -0
  108. data/_sass/bootstrap/_tooltip.scss +101 -0
  109. data/_sass/bootstrap/_type.scss +298 -0
  110. data/_sass/bootstrap/_utilities.scss +55 -0
  111. data/_sass/bootstrap/_variables.scss +922 -0
  112. data/_sass/bootstrap/_wells.scss +29 -0
  113. data/_sass/bootstrap/mixins/_alerts.scss +14 -0
  114. data/_sass/bootstrap/mixins/_background-variant.scss +12 -0
  115. data/_sass/bootstrap/mixins/_border-radius.scss +18 -0
  116. data/_sass/bootstrap/mixins/_buttons.scss +65 -0
  117. data/_sass/bootstrap/mixins/_center-block.scss +7 -0
  118. data/_sass/bootstrap/mixins/_clearfix.scss +22 -0
  119. data/_sass/bootstrap/mixins/_forms.scss +88 -0
  120. data/_sass/bootstrap/mixins/_gradients.scss +58 -0
  121. data/_sass/bootstrap/mixins/_grid-framework.scss +81 -0
  122. data/_sass/bootstrap/mixins/_grid.scss +122 -0
  123. data/_sass/bootstrap/mixins/_hide-text.scss +21 -0
  124. data/_sass/bootstrap/mixins/_image.scss +33 -0
  125. data/_sass/bootstrap/mixins/_labels.scss +12 -0
  126. data/_sass/bootstrap/mixins/_list-group.scss +32 -0
  127. data/_sass/bootstrap/mixins/_nav-divider.scss +10 -0
  128. data/_sass/bootstrap/mixins/_nav-vertical-align.scss +9 -0
  129. data/_sass/bootstrap/mixins/_opacity.scss +8 -0
  130. data/_sass/bootstrap/mixins/_pagination.scss +24 -0
  131. data/_sass/bootstrap/mixins/_panels.scss +24 -0
  132. data/_sass/bootstrap/mixins/_progress-bar.scss +10 -0
  133. data/_sass/bootstrap/mixins/_reset-filter.scss +8 -0
  134. data/_sass/bootstrap/mixins/_reset-text.scss +18 -0
  135. data/_sass/bootstrap/mixins/_resize.scss +6 -0
  136. data/_sass/bootstrap/mixins/_responsive-visibility.scss +21 -0
  137. data/_sass/bootstrap/mixins/_size.scss +10 -0
  138. data/_sass/bootstrap/mixins/_tab-focus.scss +9 -0
  139. data/_sass/bootstrap/mixins/_table-row.scss +28 -0
  140. data/_sass/bootstrap/mixins/_text-emphasis.scss +12 -0
  141. data/_sass/bootstrap/mixins/_text-overflow.scss +8 -0
  142. data/_sass/bootstrap/mixins/_vendor-prefixes.scss +222 -0
  143. data/_sass/core.scss +12 -0
  144. data/_sass/core/404.scss +189 -0
  145. data/_sass/core/animations.scss +125 -0
  146. data/_sass/core/blog.scss +441 -0
  147. data/_sass/core/breadcrumb.scss +97 -0
  148. data/_sass/core/carousel-styles.scss +3 -0
  149. data/_sass/core/carousel.scss +318 -0
  150. data/_sass/core/cookieconsent.scss +42 -0
  151. data/_sass/core/critical.scss +0 -0
  152. data/_sass/core/custom.scss +3 -0
  153. data/_sass/core/fa.scss +2336 -0
  154. data/_sass/core/flipclock.scss +434 -0
  155. data/_sass/core/font-awesome.min.scss +4 -0
  156. data/_sass/core/fonts.scss +3 -0
  157. data/_sass/core/footer.scss +169 -0
  158. data/_sass/core/forms.scss +3 -0
  159. data/_sass/core/homepage.scss +106 -0
  160. data/_sass/core/jumbotron.scss +51 -0
  161. data/_sass/core/lightbox.scss +212 -0
  162. data/_sass/core/nav.scss +971 -0
  163. data/_sass/core/owl.carousel.min.scss +6 -0
  164. data/_sass/core/owl.theme.default.min.scss +6 -0
  165. data/_sass/core/social-media-icons.scss +67 -0
  166. data/_sass/core/syntax.scss +65 -0
  167. data/_sass/core/tables.scss +145 -0
  168. data/_sass/core/theme.scss +630 -0
  169. data/_sass/core/twitter-feed.scss +414 -0
  170. data/_sass/core/universal-nav.scss +154 -0
  171. data/_sass/core/youtube.scss +65 -0
  172. data/_sass/home.scss +6 -0
  173. data/assets/css/main-404.scss +18 -0
  174. data/assets/css/main-blog.scss +19 -0
  175. data/assets/css/main-contact.scss +23 -0
  176. data/assets/css/main-home.scss +22 -0
  177. data/assets/css/main-lightbox.scss +29 -0
  178. data/assets/css/main-search.scss +13 -0
  179. data/assets/css/main.scss +12 -0
  180. data/assets/fonts/fontawesome-webfont.eot +0 -0
  181. data/assets/fonts/fontawesome-webfont.svg +2671 -0
  182. data/assets/fonts/fontawesome-webfont.ttf +0 -0
  183. data/assets/fonts/fontawesome-webfont.woff +0 -0
  184. data/assets/fonts/fontawesome-webfont.woff2 +0 -0
  185. data/assets/fonts/fontello.eot +0 -0
  186. data/assets/fonts/fontello.svg +44 -0
  187. data/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  188. data/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  189. data/assets/fonts/glyphicons-halflings-regular.woff2 +0 -0
  190. data/assets/fonts/lato-regular/LICENSE.txt +93 -0
  191. data/assets/fonts/lato-regular/Lato-regular.eot +0 -0
  192. data/assets/fonts/lato-regular/Lato-regular.svg +435 -0
  193. data/assets/fonts/lato-regular/Lato-regular.ttf +0 -0
  194. data/assets/fonts/lato-regular/Lato-regular.woff +0 -0
  195. data/assets/fonts/lato-regular/Lato-regular.woff2 +0 -0
  196. data/assets/images/Linaro-Logo.svg +1 -0
  197. data/assets/images/Linaro-Logo_light.png +0 -0
  198. data/assets/images/Linaro-Logo_standard.svg +1 -0
  199. data/assets/images/Linaro-Sprinkle.png +0 -0
  200. data/assets/images/avatar-placeholder.png +0 -0
  201. data/assets/images/background-image.jpg +0 -0
  202. data/assets/images/banner.jpg +0 -0
  203. data/assets/images/breadcrumb-image.jpg +0 -0
  204. data/assets/images/close.png +0 -0
  205. data/assets/images/favicon.ico +0 -0
  206. data/assets/images/favicon.png +0 -0
  207. data/assets/images/loading.gif +0 -0
  208. data/assets/images/next.png +0 -0
  209. data/assets/images/owl.video.play.png +0 -0
  210. data/assets/images/placeholder.png +0 -0
  211. data/assets/images/prev.png +0 -0
  212. data/assets/images/social-media-image.png +0 -0
  213. data/assets/js/app/custom.js +0 -0
  214. data/assets/js/app/facebook.js +8 -0
  215. data/assets/js/app/home.js +46 -0
  216. data/assets/js/app/main.js +143 -0
  217. data/assets/js/app/scroll-to-anchors.js +10 -0
  218. data/assets/js/app/sticky-tab-bar.js +72 -0
  219. data/assets/js/app/tables.js +35 -0
  220. data/assets/js/package-blog.js +10 -0
  221. data/assets/js/package-extended.js +14 -0
  222. data/assets/js/package-home.js +12 -0
  223. data/assets/js/package-main.js +10 -0
  224. data/assets/js/package-search.js +8 -0
  225. data/assets/js/vendor/bootstrap.js +2377 -0
  226. data/assets/js/vendor/cognito.js +11 -0
  227. data/assets/js/vendor/cookieconsent.js +1504 -0
  228. data/assets/js/vendor/jquery.js +10364 -0
  229. data/assets/js/vendor/jquery.rss.js +333 -0
  230. data/assets/js/vendor/jquery.validate.js +1601 -0
  231. data/assets/js/vendor/lazysizes.js +698 -0
  232. data/assets/js/vendor/lightbox.js +523 -0
  233. data/assets/js/vendor/loadCSS.js +35 -0
  234. data/assets/js/vendor/ls.unveilhooks.js +145 -0
  235. data/assets/js/vendor/mc.js +255 -0
  236. data/assets/js/vendor/owl.carousel.js +3475 -0
  237. data/assets/js/vendor/picturefill.js +1471 -0
  238. data/assets/js/vendor/shuffle.js +2004 -0
  239. data/robots.txt +9 -0
  240. metadata +528 -0
@@ -0,0 +1,1471 @@
1
+ /*! Picturefill - v3.0.2
2
+ * http://scottjehl.github.io/picturefill
3
+ * Copyright (c) 2015 https://github.com/scottjehl/picturefill/blob/master/Authors.txt;
4
+ * License: MIT
5
+ */
6
+
7
+ (function( window, document, undefined ) {
8
+ // Enable strict mode
9
+ "use strict";
10
+
11
+ // HTML shim|v it for old IE (IE9 will still need the HTML video tag workaround)
12
+ document.createElement( "picture" );
13
+
14
+ var warn, eminpx, alwaysCheckWDescriptor, evalId;
15
+ // local object for method references and testing exposure
16
+ var pf = {};
17
+ var isSupportTestReady = false;
18
+ var noop = function() {};
19
+ var image = document.createElement( "img" );
20
+ var getImgAttr = image.getAttribute;
21
+ var setImgAttr = image.setAttribute;
22
+ var removeImgAttr = image.removeAttribute;
23
+ var docElem = document.documentElement;
24
+ var types = {};
25
+ var cfg = {
26
+ //resource selection:
27
+ algorithm: ""
28
+ };
29
+ var srcAttr = "data-pfsrc";
30
+ var srcsetAttr = srcAttr + "set";
31
+ // ua sniffing is done for undetectable img loading features,
32
+ // to do some non crucial perf optimizations
33
+ var ua = navigator.userAgent;
34
+ var supportAbort = (/rident/).test(ua) || ((/ecko/).test(ua) && ua.match(/rv\:(\d+)/) && RegExp.$1 > 35 );
35
+ var curSrcProp = "currentSrc";
36
+ var regWDesc = /\s+\+?\d+(e\d+)?w/;
37
+ var regSize = /(\([^)]+\))?\s*(.+)/;
38
+ var setOptions = window.picturefillCFG;
39
+ /**
40
+ * Shortcut property for https://w3c.github.io/webappsec/specs/mixedcontent/#restricts-mixed-content ( for easy overriding in tests )
41
+ */
42
+ // baseStyle also used by getEmValue (i.e.: width: 1em is important)
43
+ var baseStyle = "position:absolute;left:0;visibility:hidden;display:block;padding:0;border:none;font-size:1em;width:1em;overflow:hidden;clip:rect(0px, 0px, 0px, 0px)";
44
+ var fsCss = "font-size:100%!important;";
45
+ var isVwDirty = true;
46
+
47
+ var cssCache = {};
48
+ var sizeLengthCache = {};
49
+ var DPR = window.devicePixelRatio;
50
+ var units = {
51
+ px: 1,
52
+ "in": 96
53
+ };
54
+ var anchor = document.createElement( "a" );
55
+ /**
56
+ * alreadyRun flag used for setOptions. is it true setOptions will reevaluate
57
+ * @type {boolean}
58
+ */
59
+ var alreadyRun = false;
60
+
61
+ // Reusable, non-"g" Regexes
62
+
63
+ // (Don't use \s, to avoid matching non-breaking space.)
64
+ var regexLeadingSpaces = /^[ \t\n\r\u000c]+/,
65
+ regexLeadingCommasOrSpaces = /^[, \t\n\r\u000c]+/,
66
+ regexLeadingNotSpaces = /^[^ \t\n\r\u000c]+/,
67
+ regexTrailingCommas = /[,]+$/,
68
+ regexNonNegativeInteger = /^\d+$/,
69
+
70
+ // ( Positive or negative or unsigned integers or decimals, without or without exponents.
71
+ // Must include at least one digit.
72
+ // According to spec tests any decimal point must be followed by a digit.
73
+ // No leading plus sign is allowed.)
74
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-floating-point-number
75
+ regexFloatingPoint = /^-?(?:[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?[0-9]+)?$/;
76
+
77
+ var on = function(obj, evt, fn, capture) {
78
+ if ( obj.addEventListener ) {
79
+ obj.addEventListener(evt, fn, capture || false);
80
+ } else if ( obj.attachEvent ) {
81
+ obj.attachEvent( "on" + evt, fn);
82
+ }
83
+ };
84
+
85
+ /**
86
+ * simple memoize function:
87
+ */
88
+
89
+ var memoize = function(fn) {
90
+ var cache = {};
91
+ return function(input) {
92
+ if ( !(input in cache) ) {
93
+ cache[ input ] = fn(input);
94
+ }
95
+ return cache[ input ];
96
+ };
97
+ };
98
+
99
+ // UTILITY FUNCTIONS
100
+
101
+ // Manual is faster than RegEx
102
+ // http://jsperf.com/whitespace-character/5
103
+ function isSpace(c) {
104
+ return (c === "\u0020" || // space
105
+ c === "\u0009" || // horizontal tab
106
+ c === "\u000A" || // new line
107
+ c === "\u000C" || // form feed
108
+ c === "\u000D"); // carriage return
109
+ }
110
+
111
+ /**
112
+ * gets a mediaquery and returns a boolean or gets a css length and returns a number
113
+ * @param css mediaqueries or css length
114
+ * @returns {boolean|number}
115
+ *
116
+ * based on: https://gist.github.com/jonathantneal/db4f77009b155f083738
117
+ */
118
+ var evalCSS = (function() {
119
+
120
+ var regLength = /^([\d\.]+)(em|vw|px)$/;
121
+ var replace = function() {
122
+ var args = arguments, index = 0, string = args[0];
123
+ while (++index in args) {
124
+ string = string.replace(args[index], args[++index]);
125
+ }
126
+ return string;
127
+ };
128
+
129
+ var buildStr = memoize(function(css) {
130
+
131
+ return "return " + replace((css || "").toLowerCase(),
132
+ // interpret `and`
133
+ /\band\b/g, "&&",
134
+
135
+ // interpret `,`
136
+ /,/g, "||",
137
+
138
+ // interpret `min-` as >=
139
+ /min-([a-z-\s]+):/g, "e.$1>=",
140
+
141
+ // interpret `max-` as <=
142
+ /max-([a-z-\s]+):/g, "e.$1<=",
143
+
144
+ //calc value
145
+ /calc([^)]+)/g, "($1)",
146
+
147
+ // interpret css values
148
+ /(\d+[\.]*[\d]*)([a-z]+)/g, "($1 * e.$2)",
149
+ //make eval less evil
150
+ /^(?!(e.[a-z]|[0-9\.&=|><\+\-\*\(\)\/])).*/ig, ""
151
+ ) + ";";
152
+ });
153
+
154
+ return function(css, length) {
155
+ var parsedLength;
156
+ if (!(css in cssCache)) {
157
+ cssCache[css] = false;
158
+ if (length && (parsedLength = css.match( regLength ))) {
159
+ cssCache[css] = parsedLength[ 1 ] * units[parsedLength[ 2 ]];
160
+ } else {
161
+ /*jshint evil:true */
162
+ try{
163
+ cssCache[css] = new Function("e", buildStr(css))(units);
164
+ } catch(e) {}
165
+ /*jshint evil:false */
166
+ }
167
+ }
168
+ return cssCache[css];
169
+ };
170
+ })();
171
+
172
+ var setResolution = function( candidate, sizesattr ) {
173
+ if ( candidate.w ) { // h = means height: || descriptor.type === 'h' do not handle yet...
174
+ candidate.cWidth = pf.calcListLength( sizesattr || "100vw" );
175
+ candidate.res = candidate.w / candidate.cWidth ;
176
+ } else {
177
+ candidate.res = candidate.d;
178
+ }
179
+ return candidate;
180
+ };
181
+
182
+ /**
183
+ *
184
+ * @param opt
185
+ */
186
+ var picturefill = function( opt ) {
187
+
188
+ if (!isSupportTestReady) {return;}
189
+
190
+ var elements, i, plen;
191
+
192
+ var options = opt || {};
193
+
194
+ if ( options.elements && options.elements.nodeType === 1 ) {
195
+ if ( options.elements.nodeName.toUpperCase() === "IMG" ) {
196
+ options.elements = [ options.elements ];
197
+ } else {
198
+ options.context = options.elements;
199
+ options.elements = null;
200
+ }
201
+ }
202
+
203
+ elements = options.elements || pf.qsa( (options.context || document), ( options.reevaluate || options.reselect ) ? pf.sel : pf.selShort );
204
+
205
+ if ( (plen = elements.length) ) {
206
+
207
+ pf.setupRun( options );
208
+ alreadyRun = true;
209
+
210
+ // Loop through all elements
211
+ for ( i = 0; i < plen; i++ ) {
212
+ pf.fillImg(elements[ i ], options);
213
+ }
214
+
215
+ pf.teardownRun( options );
216
+ }
217
+ };
218
+
219
+ /**
220
+ * outputs a warning for the developer
221
+ * @param {message}
222
+ * @type {Function}
223
+ */
224
+ warn = ( window.console && console.warn ) ?
225
+ function( message ) {
226
+ console.warn( message );
227
+ } :
228
+ noop
229
+ ;
230
+
231
+ if ( !(curSrcProp in image) ) {
232
+ curSrcProp = "src";
233
+ }
234
+
235
+ // Add support for standard mime types.
236
+ types[ "image/jpeg" ] = true;
237
+ types[ "image/gif" ] = true;
238
+ types[ "image/png" ] = true;
239
+
240
+ function detectTypeSupport( type, typeUri ) {
241
+ // based on Modernizr's lossless img-webp test
242
+ // note: asynchronous
243
+ var image = new window.Image();
244
+ image.onerror = function() {
245
+ types[ type ] = false;
246
+ picturefill();
247
+ };
248
+ image.onload = function() {
249
+ types[ type ] = image.width === 1;
250
+ picturefill();
251
+ };
252
+ image.src = typeUri;
253
+ return "pending";
254
+ }
255
+
256
+ // test svg support
257
+ types[ "image/svg+xml" ] = document.implementation.hasFeature( "http://www.w3.org/TR/SVG11/feature#Image", "1.1" );
258
+
259
+ /**
260
+ * updates the internal vW property with the current viewport width in px
261
+ */
262
+ function updateMetrics() {
263
+
264
+ isVwDirty = false;
265
+ DPR = window.devicePixelRatio;
266
+ cssCache = {};
267
+ sizeLengthCache = {};
268
+
269
+ pf.DPR = DPR || 1;
270
+
271
+ units.width = Math.max(window.innerWidth || 0, docElem.clientWidth);
272
+ units.height = Math.max(window.innerHeight || 0, docElem.clientHeight);
273
+
274
+ units.vw = units.width / 100;
275
+ units.vh = units.height / 100;
276
+
277
+ evalId = [ units.height, units.width, DPR ].join("-");
278
+
279
+ units.em = pf.getEmValue();
280
+ units.rem = units.em;
281
+ }
282
+
283
+ function chooseLowRes( lowerValue, higherValue, dprValue, isCached ) {
284
+ var bonusFactor, tooMuch, bonus, meanDensity;
285
+
286
+ //experimental
287
+ if (cfg.algorithm === "saveData" ){
288
+ if ( lowerValue > 2.7 ) {
289
+ meanDensity = dprValue + 1;
290
+ } else {
291
+ tooMuch = higherValue - dprValue;
292
+ bonusFactor = Math.pow(lowerValue - 0.6, 1.5);
293
+
294
+ bonus = tooMuch * bonusFactor;
295
+
296
+ if (isCached) {
297
+ bonus += 0.1 * bonusFactor;
298
+ }
299
+
300
+ meanDensity = lowerValue + bonus;
301
+ }
302
+ } else {
303
+ meanDensity = (dprValue > 1) ?
304
+ Math.sqrt(lowerValue * higherValue) :
305
+ lowerValue;
306
+ }
307
+
308
+ return meanDensity > dprValue;
309
+ }
310
+
311
+ function applyBestCandidate( img ) {
312
+ var srcSetCandidates;
313
+ var matchingSet = pf.getSet( img );
314
+ var evaluated = false;
315
+ if ( matchingSet !== "pending" ) {
316
+ evaluated = evalId;
317
+ if ( matchingSet ) {
318
+ srcSetCandidates = pf.setRes( matchingSet );
319
+ pf.applySetCandidate( srcSetCandidates, img );
320
+ }
321
+ }
322
+ img[ pf.ns ].evaled = evaluated;
323
+ }
324
+
325
+ function ascendingSort( a, b ) {
326
+ return a.res - b.res;
327
+ }
328
+
329
+ function setSrcToCur( img, src, set ) {
330
+ var candidate;
331
+ if ( !set && src ) {
332
+ set = img[ pf.ns ].sets;
333
+ set = set && set[set.length - 1];
334
+ }
335
+
336
+ candidate = getCandidateForSrc(src, set);
337
+
338
+ if ( candidate ) {
339
+ src = pf.makeUrl(src);
340
+ img[ pf.ns ].curSrc = src;
341
+ img[ pf.ns ].curCan = candidate;
342
+
343
+ if ( !candidate.res ) {
344
+ setResolution( candidate, candidate.set.sizes );
345
+ }
346
+ }
347
+ return candidate;
348
+ }
349
+
350
+ function getCandidateForSrc( src, set ) {
351
+ var i, candidate, candidates;
352
+ if ( src && set ) {
353
+ candidates = pf.parseSet( set );
354
+ src = pf.makeUrl(src);
355
+ for ( i = 0; i < candidates.length; i++ ) {
356
+ if ( src === pf.makeUrl(candidates[ i ].url) ) {
357
+ candidate = candidates[ i ];
358
+ break;
359
+ }
360
+ }
361
+ }
362
+ return candidate;
363
+ }
364
+
365
+ function getAllSourceElements( picture, candidates ) {
366
+ var i, len, source, srcset;
367
+
368
+ // SPEC mismatch intended for size and perf:
369
+ // actually only source elements preceding the img should be used
370
+ // also note: don't use qsa here, because IE8 sometimes doesn't like source as the key part in a selector
371
+ var sources = picture.getElementsByTagName( "source" );
372
+
373
+ for ( i = 0, len = sources.length; i < len; i++ ) {
374
+ source = sources[ i ];
375
+ source[ pf.ns ] = true;
376
+ srcset = source.getAttribute( "srcset" );
377
+
378
+ // if source does not have a srcset attribute, skip
379
+ if ( srcset ) {
380
+ candidates.push( {
381
+ srcset: srcset,
382
+ media: source.getAttribute( "media" ),
383
+ type: source.getAttribute( "type" ),
384
+ sizes: source.getAttribute( "sizes" )
385
+ } );
386
+ }
387
+ }
388
+ }
389
+
390
+ /**
391
+ * Srcset Parser
392
+ * By Alex Bell | MIT License
393
+ *
394
+ * @returns Array [{url: _, d: _, w: _, h:_, set:_(????)}, ...]
395
+ *
396
+ * Based super duper closely on the reference algorithm at:
397
+ * https://html.spec.whatwg.org/multipage/embedded-content.html#parse-a-srcset-attribute
398
+ */
399
+
400
+ // 1. Let input be the value passed to this algorithm.
401
+ // (TO-DO : Explain what "set" argument is here. Maybe choose a more
402
+ // descriptive & more searchable name. Since passing the "set" in really has
403
+ // nothing to do with parsing proper, I would prefer this assignment eventually
404
+ // go in an external fn.)
405
+ function parseSrcset(input, set) {
406
+
407
+ function collectCharacters(regEx) {
408
+ var chars,
409
+ match = regEx.exec(input.substring(pos));
410
+ if (match) {
411
+ chars = match[ 0 ];
412
+ pos += chars.length;
413
+ return chars;
414
+ }
415
+ }
416
+
417
+ var inputLength = input.length,
418
+ url,
419
+ descriptors,
420
+ currentDescriptor,
421
+ state,
422
+ c,
423
+
424
+ // 2. Let position be a pointer into input, initially pointing at the start
425
+ // of the string.
426
+ pos = 0,
427
+
428
+ // 3. Let candidates be an initially empty source set.
429
+ candidates = [];
430
+
431
+ /**
432
+ * Adds descriptor properties to a candidate, pushes to the candidates array
433
+ * @return undefined
434
+ */
435
+ // (Declared outside of the while loop so that it's only created once.
436
+ // (This fn is defined before it is used, in order to pass JSHINT.
437
+ // Unfortunately this breaks the sequencing of the spec comments. :/ )
438
+ function parseDescriptors() {
439
+
440
+ // 9. Descriptor parser: Let error be no.
441
+ var pError = false,
442
+
443
+ // 10. Let width be absent.
444
+ // 11. Let density be absent.
445
+ // 12. Let future-compat-h be absent. (We're implementing it now as h)
446
+ w, d, h, i,
447
+ candidate = {},
448
+ desc, lastChar, value, intVal, floatVal;
449
+
450
+ // 13. For each descriptor in descriptors, run the appropriate set of steps
451
+ // from the following list:
452
+ for (i = 0 ; i < descriptors.length; i++) {
453
+ desc = descriptors[ i ];
454
+
455
+ lastChar = desc[ desc.length - 1 ];
456
+ value = desc.substring(0, desc.length - 1);
457
+ intVal = parseInt(value, 10);
458
+ floatVal = parseFloat(value);
459
+
460
+ // If the descriptor consists of a valid non-negative integer followed by
461
+ // a U+0077 LATIN SMALL LETTER W character
462
+ if (regexNonNegativeInteger.test(value) && (lastChar === "w")) {
463
+
464
+ // If width and density are not both absent, then let error be yes.
465
+ if (w || d) {pError = true;}
466
+
467
+ // Apply the rules for parsing non-negative integers to the descriptor.
468
+ // If the result is zero, let error be yes.
469
+ // Otherwise, let width be the result.
470
+ if (intVal === 0) {pError = true;} else {w = intVal;}
471
+
472
+ // If the descriptor consists of a valid floating-point number followed by
473
+ // a U+0078 LATIN SMALL LETTER X character
474
+ } else if (regexFloatingPoint.test(value) && (lastChar === "x")) {
475
+
476
+ // If width, density and future-compat-h are not all absent, then let error
477
+ // be yes.
478
+ if (w || d || h) {pError = true;}
479
+
480
+ // Apply the rules for parsing floating-point number values to the descriptor.
481
+ // If the result is less than zero, let error be yes. Otherwise, let density
482
+ // be the result.
483
+ if (floatVal < 0) {pError = true;} else {d = floatVal;}
484
+
485
+ // If the descriptor consists of a valid non-negative integer followed by
486
+ // a U+0068 LATIN SMALL LETTER H character
487
+ } else if (regexNonNegativeInteger.test(value) && (lastChar === "h")) {
488
+
489
+ // If height and density are not both absent, then let error be yes.
490
+ if (h || d) {pError = true;}
491
+
492
+ // Apply the rules for parsing non-negative integers to the descriptor.
493
+ // If the result is zero, let error be yes. Otherwise, let future-compat-h
494
+ // be the result.
495
+ if (intVal === 0) {pError = true;} else {h = intVal;}
496
+
497
+ // Anything else, Let error be yes.
498
+ } else {pError = true;}
499
+ } // (close step 13 for loop)
500
+
501
+ // 15. If error is still no, then append a new image source to candidates whose
502
+ // URL is url, associated with a width width if not absent and a pixel
503
+ // density density if not absent. Otherwise, there is a parse error.
504
+ if (!pError) {
505
+ candidate.url = url;
506
+
507
+ if (w) { candidate.w = w;}
508
+ if (d) { candidate.d = d;}
509
+ if (h) { candidate.h = h;}
510
+ if (!h && !d && !w) {candidate.d = 1;}
511
+ if (candidate.d === 1) {set.has1x = true;}
512
+ candidate.set = set;
513
+
514
+ candidates.push(candidate);
515
+ }
516
+ } // (close parseDescriptors fn)
517
+
518
+ /**
519
+ * Tokenizes descriptor properties prior to parsing
520
+ * Returns undefined.
521
+ * (Again, this fn is defined before it is used, in order to pass JSHINT.
522
+ * Unfortunately this breaks the logical sequencing of the spec comments. :/ )
523
+ */
524
+ function tokenize() {
525
+
526
+ // 8.1. Descriptor tokeniser: Skip whitespace
527
+ collectCharacters(regexLeadingSpaces);
528
+
529
+ // 8.2. Let current descriptor be the empty string.
530
+ currentDescriptor = "";
531
+
532
+ // 8.3. Let state be in descriptor.
533
+ state = "in descriptor";
534
+
535
+ while (true) {
536
+
537
+ // 8.4. Let c be the character at position.
538
+ c = input.charAt(pos);
539
+
540
+ // Do the following depending on the value of state.
541
+ // For the purpose of this step, "EOF" is a special character representing
542
+ // that position is past the end of input.
543
+
544
+ // In descriptor
545
+ if (state === "in descriptor") {
546
+ // Do the following, depending on the value of c:
547
+
548
+ // Space character
549
+ // If current descriptor is not empty, append current descriptor to
550
+ // descriptors and let current descriptor be the empty string.
551
+ // Set state to after descriptor.
552
+ if (isSpace(c)) {
553
+ if (currentDescriptor) {
554
+ descriptors.push(currentDescriptor);
555
+ currentDescriptor = "";
556
+ state = "after descriptor";
557
+ }
558
+
559
+ // U+002C COMMA (,)
560
+ // Advance position to the next character in input. If current descriptor
561
+ // is not empty, append current descriptor to descriptors. Jump to the step
562
+ // labeled descriptor parser.
563
+ } else if (c === ",") {
564
+ pos += 1;
565
+ if (currentDescriptor) {
566
+ descriptors.push(currentDescriptor);
567
+ }
568
+ parseDescriptors();
569
+ return;
570
+
571
+ // U+0028 LEFT PARENTHESIS (()
572
+ // Append c to current descriptor. Set state to in parens.
573
+ } else if (c === "\u0028") {
574
+ currentDescriptor = currentDescriptor + c;
575
+ state = "in parens";
576
+
577
+ // EOF
578
+ // If current descriptor is not empty, append current descriptor to
579
+ // descriptors. Jump to the step labeled descriptor parser.
580
+ } else if (c === "") {
581
+ if (currentDescriptor) {
582
+ descriptors.push(currentDescriptor);
583
+ }
584
+ parseDescriptors();
585
+ return;
586
+
587
+ // Anything else
588
+ // Append c to current descriptor.
589
+ } else {
590
+ currentDescriptor = currentDescriptor + c;
591
+ }
592
+ // (end "in descriptor"
593
+
594
+ // In parens
595
+ } else if (state === "in parens") {
596
+
597
+ // U+0029 RIGHT PARENTHESIS ())
598
+ // Append c to current descriptor. Set state to in descriptor.
599
+ if (c === ")") {
600
+ currentDescriptor = currentDescriptor + c;
601
+ state = "in descriptor";
602
+
603
+ // EOF
604
+ // Append current descriptor to descriptors. Jump to the step labeled
605
+ // descriptor parser.
606
+ } else if (c === "") {
607
+ descriptors.push(currentDescriptor);
608
+ parseDescriptors();
609
+ return;
610
+
611
+ // Anything else
612
+ // Append c to current descriptor.
613
+ } else {
614
+ currentDescriptor = currentDescriptor + c;
615
+ }
616
+
617
+ // After descriptor
618
+ } else if (state === "after descriptor") {
619
+
620
+ // Do the following, depending on the value of c:
621
+ // Space character: Stay in this state.
622
+ if (isSpace(c)) {
623
+
624
+ // EOF: Jump to the step labeled descriptor parser.
625
+ } else if (c === "") {
626
+ parseDescriptors();
627
+ return;
628
+
629
+ // Anything else
630
+ // Set state to in descriptor. Set position to the previous character in input.
631
+ } else {
632
+ state = "in descriptor";
633
+ pos -= 1;
634
+
635
+ }
636
+ }
637
+
638
+ // Advance position to the next character in input.
639
+ pos += 1;
640
+
641
+ // Repeat this step.
642
+ } // (close while true loop)
643
+ }
644
+
645
+ // 4. Splitting loop: Collect a sequence of characters that are space
646
+ // characters or U+002C COMMA characters. If any U+002C COMMA characters
647
+ // were collected, that is a parse error.
648
+ while (true) {
649
+ collectCharacters(regexLeadingCommasOrSpaces);
650
+
651
+ // 5. If position is past the end of input, return candidates and abort these steps.
652
+ if (pos >= inputLength) {
653
+ return candidates; // (we're done, this is the sole return path)
654
+ }
655
+
656
+ // 6. Collect a sequence of characters that are not space characters,
657
+ // and let that be url.
658
+ url = collectCharacters(regexLeadingNotSpaces);
659
+
660
+ // 7. Let descriptors be a new empty list.
661
+ descriptors = [];
662
+
663
+ // 8. If url ends with a U+002C COMMA character (,), follow these substeps:
664
+ // (1). Remove all trailing U+002C COMMA characters from url. If this removed
665
+ // more than one character, that is a parse error.
666
+ if (url.slice(-1) === ",") {
667
+ url = url.replace(regexTrailingCommas, "");
668
+ // (Jump ahead to step 9 to skip tokenization and just push the candidate).
669
+ parseDescriptors();
670
+
671
+ // Otherwise, follow these substeps:
672
+ } else {
673
+ tokenize();
674
+ } // (close else of step 8)
675
+
676
+ // 16. Return to the step labeled splitting loop.
677
+ } // (Close of big while loop.)
678
+ }
679
+
680
+ /*
681
+ * Sizes Parser
682
+ *
683
+ * By Alex Bell | MIT License
684
+ *
685
+ * Non-strict but accurate and lightweight JS Parser for the string value <img sizes="here">
686
+ *
687
+ * Reference algorithm at:
688
+ * https://html.spec.whatwg.org/multipage/embedded-content.html#parse-a-sizes-attribute
689
+ *
690
+ * Most comments are copied in directly from the spec
691
+ * (except for comments in parens).
692
+ *
693
+ * Grammar is:
694
+ * <source-size-list> = <source-size># [ , <source-size-value> ]? | <source-size-value>
695
+ * <source-size> = <media-condition> <source-size-value>
696
+ * <source-size-value> = <length>
697
+ * http://www.w3.org/html/wg/drafts/html/master/embedded-content.html#attr-img-sizes
698
+ *
699
+ * E.g. "(max-width: 30em) 100vw, (max-width: 50em) 70vw, 100vw"
700
+ * or "(min-width: 30em), calc(30vw - 15px)" or just "30vw"
701
+ *
702
+ * Returns the first valid <css-length> with a media condition that evaluates to true,
703
+ * or "100vw" if all valid media conditions evaluate to false.
704
+ *
705
+ */
706
+
707
+ function parseSizes(strValue) {
708
+
709
+ // (Percentage CSS lengths are not allowed in this case, to avoid confusion:
710
+ // https://html.spec.whatwg.org/multipage/embedded-content.html#valid-source-size-list
711
+ // CSS allows a single optional plus or minus sign:
712
+ // http://www.w3.org/TR/CSS2/syndata.html#numbers
713
+ // CSS is ASCII case-insensitive:
714
+ // http://www.w3.org/TR/CSS2/syndata.html#characters )
715
+ // Spec allows exponential notation for <number> type:
716
+ // http://dev.w3.org/csswg/css-values/#numbers
717
+ var regexCssLengthWithUnits = /^(?:[+-]?[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?[0-9]+)?(?:ch|cm|em|ex|in|mm|pc|pt|px|rem|vh|vmin|vmax|vw)$/i;
718
+
719
+ // (This is a quick and lenient test. Because of optional unlimited-depth internal
720
+ // grouping parens and strict spacing rules, this could get very complicated.)
721
+ var regexCssCalc = /^calc\((?:[0-9a-z \.\+\-\*\/\(\)]+)\)$/i;
722
+
723
+ var i;
724
+ var unparsedSizesList;
725
+ var unparsedSizesListLength;
726
+ var unparsedSize;
727
+ var lastComponentValue;
728
+ var size;
729
+
730
+ // UTILITY FUNCTIONS
731
+
732
+ // (Toy CSS parser. The goals here are:
733
+ // 1) expansive test coverage without the weight of a full CSS parser.
734
+ // 2) Avoiding regex wherever convenient.
735
+ // Quick tests: http://jsfiddle.net/gtntL4gr/3/
736
+ // Returns an array of arrays.)
737
+ function parseComponentValues(str) {
738
+ var chrctr;
739
+ var component = "";
740
+ var componentArray = [];
741
+ var listArray = [];
742
+ var parenDepth = 0;
743
+ var pos = 0;
744
+ var inComment = false;
745
+
746
+ function pushComponent() {
747
+ if (component) {
748
+ componentArray.push(component);
749
+ component = "";
750
+ }
751
+ }
752
+
753
+ function pushComponentArray() {
754
+ if (componentArray[0]) {
755
+ listArray.push(componentArray);
756
+ componentArray = [];
757
+ }
758
+ }
759
+
760
+ // (Loop forwards from the beginning of the string.)
761
+ while (true) {
762
+ chrctr = str.charAt(pos);
763
+
764
+ if (chrctr === "") { // ( End of string reached.)
765
+ pushComponent();
766
+ pushComponentArray();
767
+ return listArray;
768
+ } else if (inComment) {
769
+ if ((chrctr === "*") && (str[pos + 1] === "/")) { // (At end of a comment.)
770
+ inComment = false;
771
+ pos += 2;
772
+ pushComponent();
773
+ continue;
774
+ } else {
775
+ pos += 1; // (Skip all characters inside comments.)
776
+ continue;
777
+ }
778
+ } else if (isSpace(chrctr)) {
779
+ // (If previous character in loop was also a space, or if
780
+ // at the beginning of the string, do not add space char to
781
+ // component.)
782
+ if ( (str.charAt(pos - 1) && isSpace( str.charAt(pos - 1) ) ) || !component ) {
783
+ pos += 1;
784
+ continue;
785
+ } else if (parenDepth === 0) {
786
+ pushComponent();
787
+ pos +=1;
788
+ continue;
789
+ } else {
790
+ // (Replace any space character with a plain space for legibility.)
791
+ chrctr = " ";
792
+ }
793
+ } else if (chrctr === "(") {
794
+ parenDepth += 1;
795
+ } else if (chrctr === ")") {
796
+ parenDepth -= 1;
797
+ } else if (chrctr === ",") {
798
+ pushComponent();
799
+ pushComponentArray();
800
+ pos += 1;
801
+ continue;
802
+ } else if ( (chrctr === "/") && (str.charAt(pos + 1) === "*") ) {
803
+ inComment = true;
804
+ pos += 2;
805
+ continue;
806
+ }
807
+
808
+ component = component + chrctr;
809
+ pos += 1;
810
+ }
811
+ }
812
+
813
+ function isValidNonNegativeSourceSizeValue(s) {
814
+ if (regexCssLengthWithUnits.test(s) && (parseFloat(s) >= 0)) {return true;}
815
+ if (regexCssCalc.test(s)) {return true;}
816
+ // ( http://www.w3.org/TR/CSS2/syndata.html#numbers says:
817
+ // "-0 is equivalent to 0 and is not a negative number." which means that
818
+ // unitless zero and unitless negative zero must be accepted as special cases.)
819
+ if ((s === "0") || (s === "-0") || (s === "+0")) {return true;}
820
+ return false;
821
+ }
822
+
823
+ // When asked to parse a sizes attribute from an element, parse a
824
+ // comma-separated list of component values from the value of the element's
825
+ // sizes attribute (or the empty string, if the attribute is absent), and let
826
+ // unparsed sizes list be the result.
827
+ // http://dev.w3.org/csswg/css-syntax/#parse-comma-separated-list-of-component-values
828
+
829
+ unparsedSizesList = parseComponentValues(strValue);
830
+ unparsedSizesListLength = unparsedSizesList.length;
831
+
832
+ // For each unparsed size in unparsed sizes list:
833
+ for (i = 0; i < unparsedSizesListLength; i++) {
834
+ unparsedSize = unparsedSizesList[i];
835
+
836
+ // 1. Remove all consecutive <whitespace-token>s from the end of unparsed size.
837
+ // ( parseComponentValues() already omits spaces outside of parens. )
838
+
839
+ // If unparsed size is now empty, that is a parse error; continue to the next
840
+ // iteration of this algorithm.
841
+ // ( parseComponentValues() won't push an empty array. )
842
+
843
+ // 2. If the last component value in unparsed size is a valid non-negative
844
+ // <source-size-value>, let size be its value and remove the component value
845
+ // from unparsed size. Any CSS function other than the calc() function is
846
+ // invalid. Otherwise, there is a parse error; continue to the next iteration
847
+ // of this algorithm.
848
+ // http://dev.w3.org/csswg/css-syntax/#parse-component-value
849
+ lastComponentValue = unparsedSize[unparsedSize.length - 1];
850
+
851
+ if (isValidNonNegativeSourceSizeValue(lastComponentValue)) {
852
+ size = lastComponentValue;
853
+ unparsedSize.pop();
854
+ } else {
855
+ continue;
856
+ }
857
+
858
+ // 3. Remove all consecutive <whitespace-token>s from the end of unparsed
859
+ // size. If unparsed size is now empty, return size and exit this algorithm.
860
+ // If this was not the last item in unparsed sizes list, that is a parse error.
861
+ if (unparsedSize.length === 0) {
862
+ return size;
863
+ }
864
+
865
+ // 4. Parse the remaining component values in unparsed size as a
866
+ // <media-condition>. If it does not parse correctly, or it does parse
867
+ // correctly but the <media-condition> evaluates to false, continue to the
868
+ // next iteration of this algorithm.
869
+ // (Parsing all possible compound media conditions in JS is heavy, complicated,
870
+ // and the payoff is unclear. Is there ever an situation where the
871
+ // media condition parses incorrectly but still somehow evaluates to true?
872
+ // Can we just rely on the browser/polyfill to do it?)
873
+ unparsedSize = unparsedSize.join(" ");
874
+ if (!(pf.matchesMedia( unparsedSize ) ) ) {
875
+ continue;
876
+ }
877
+
878
+ // 5. Return size and exit this algorithm.
879
+ return size;
880
+ }
881
+
882
+ // If the above algorithm exhausts unparsed sizes list without returning a
883
+ // size value, return 100vw.
884
+ return "100vw";
885
+ }
886
+
887
+ // namespace
888
+ pf.ns = ("pf" + new Date().getTime()).substr(0, 9);
889
+
890
+ // srcset support test
891
+ pf.supSrcset = "srcset" in image;
892
+ pf.supSizes = "sizes" in image;
893
+ pf.supPicture = !!window.HTMLPictureElement;
894
+
895
+ // UC browser does claim to support srcset and picture, but not sizes,
896
+ // this extended test reveals the browser does support nothing
897
+ if (pf.supSrcset && pf.supPicture && !pf.supSizes) {
898
+ (function(image2) {
899
+ image.srcset = "data:,a";
900
+ image2.src = "data:,a";
901
+ pf.supSrcset = image.complete === image2.complete;
902
+ pf.supPicture = pf.supSrcset && pf.supPicture;
903
+ })(document.createElement("img"));
904
+ }
905
+
906
+ // Safari9 has basic support for sizes, but does't expose the `sizes` idl attribute
907
+ if (pf.supSrcset && !pf.supSizes) {
908
+
909
+ (function() {
910
+ var width2 = "data:image/gif;base64,R0lGODlhAgABAPAAAP///wAAACH5BAAAAAAALAAAAAACAAEAAAICBAoAOw==";
911
+ var width1 = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
912
+ var img = document.createElement("img");
913
+ var test = function() {
914
+ var width = img.width;
915
+
916
+ if (width === 2) {
917
+ pf.supSizes = true;
918
+ }
919
+
920
+ alwaysCheckWDescriptor = pf.supSrcset && !pf.supSizes;
921
+
922
+ isSupportTestReady = true;
923
+ // force async
924
+ setTimeout(picturefill);
925
+ };
926
+
927
+ img.onload = test;
928
+ img.onerror = test;
929
+ img.setAttribute("sizes", "9px");
930
+
931
+ img.srcset = width1 + " 1w," + width2 + " 9w";
932
+ img.src = width1;
933
+ })();
934
+
935
+ } else {
936
+ isSupportTestReady = true;
937
+ }
938
+
939
+ // using pf.qsa instead of dom traversing does scale much better,
940
+ // especially on sites mixing responsive and non-responsive images
941
+ pf.selShort = "picture>img,img[srcset]";
942
+ pf.sel = pf.selShort;
943
+ pf.cfg = cfg;
944
+
945
+ /**
946
+ * Shortcut property for `devicePixelRatio` ( for easy overriding in tests )
947
+ */
948
+ pf.DPR = (DPR || 1 );
949
+ pf.u = units;
950
+
951
+ // container of supported mime types that one might need to qualify before using
952
+ pf.types = types;
953
+
954
+ pf.setSize = noop;
955
+
956
+ /**
957
+ * Gets a string and returns the absolute URL
958
+ * @param src
959
+ * @returns {String} absolute URL
960
+ */
961
+
962
+ pf.makeUrl = memoize(function(src) {
963
+ anchor.href = src;
964
+ return anchor.href;
965
+ });
966
+
967
+ /**
968
+ * Gets a DOM element or document and a selctor and returns the found matches
969
+ * Can be extended with jQuery/Sizzle for IE7 support
970
+ * @param context
971
+ * @param sel
972
+ * @returns {NodeList|Array}
973
+ */
974
+ pf.qsa = function(context, sel) {
975
+ return ( "querySelector" in context ) ? context.querySelectorAll(sel) : [];
976
+ };
977
+
978
+ /**
979
+ * Shortcut method for matchMedia ( for easy overriding in tests )
980
+ * wether native or pf.mMQ is used will be decided lazy on first call
981
+ * @returns {boolean}
982
+ */
983
+ pf.matchesMedia = function() {
984
+ if ( window.matchMedia && (matchMedia( "(min-width: 0.1em)" ) || {}).matches ) {
985
+ pf.matchesMedia = function( media ) {
986
+ return !media || ( matchMedia( media ).matches );
987
+ };
988
+ } else {
989
+ pf.matchesMedia = pf.mMQ;
990
+ }
991
+
992
+ return pf.matchesMedia.apply( this, arguments );
993
+ };
994
+
995
+ /**
996
+ * A simplified matchMedia implementation for IE8 and IE9
997
+ * handles only min-width/max-width with px or em values
998
+ * @param media
999
+ * @returns {boolean}
1000
+ */
1001
+ pf.mMQ = function( media ) {
1002
+ return media ? evalCSS(media) : true;
1003
+ };
1004
+
1005
+ /**
1006
+ * Returns the calculated length in css pixel from the given sourceSizeValue
1007
+ * http://dev.w3.org/csswg/css-values-3/#length-value
1008
+ * intended Spec mismatches:
1009
+ * * Does not check for invalid use of CSS functions
1010
+ * * Does handle a computed length of 0 the same as a negative and therefore invalid value
1011
+ * @param sourceSizeValue
1012
+ * @returns {Number}
1013
+ */
1014
+ pf.calcLength = function( sourceSizeValue ) {
1015
+
1016
+ var value = evalCSS(sourceSizeValue, true) || false;
1017
+ if (value < 0) {
1018
+ value = false;
1019
+ }
1020
+
1021
+ return value;
1022
+ };
1023
+
1024
+ /**
1025
+ * Takes a type string and checks if its supported
1026
+ */
1027
+
1028
+ pf.supportsType = function( type ) {
1029
+ return ( type ) ? types[ type ] : true;
1030
+ };
1031
+
1032
+ /**
1033
+ * Parses a sourceSize into mediaCondition (media) and sourceSizeValue (length)
1034
+ * @param sourceSizeStr
1035
+ * @returns {*}
1036
+ */
1037
+ pf.parseSize = memoize(function( sourceSizeStr ) {
1038
+ var match = ( sourceSizeStr || "" ).match(regSize);
1039
+ return {
1040
+ media: match && match[1],
1041
+ length: match && match[2]
1042
+ };
1043
+ });
1044
+
1045
+ pf.parseSet = function( set ) {
1046
+ if ( !set.cands ) {
1047
+ set.cands = parseSrcset(set.srcset, set);
1048
+ }
1049
+ return set.cands;
1050
+ };
1051
+
1052
+ /**
1053
+ * returns 1em in css px for html/body default size
1054
+ * function taken from respondjs
1055
+ * @returns {*|number}
1056
+ */
1057
+ pf.getEmValue = function() {
1058
+ var body;
1059
+ if ( !eminpx && (body = document.body) ) {
1060
+ var div = document.createElement( "div" ),
1061
+ originalHTMLCSS = docElem.style.cssText,
1062
+ originalBodyCSS = body.style.cssText;
1063
+
1064
+ div.style.cssText = baseStyle;
1065
+
1066
+ // 1em in a media query is the value of the default font size of the browser
1067
+ // reset docElem and body to ensure the correct value is returned
1068
+ docElem.style.cssText = fsCss;
1069
+ body.style.cssText = fsCss;
1070
+
1071
+ body.appendChild( div );
1072
+ eminpx = div.offsetWidth;
1073
+ body.removeChild( div );
1074
+
1075
+ //also update eminpx before returning
1076
+ eminpx = parseFloat( eminpx, 10 );
1077
+
1078
+ // restore the original values
1079
+ docElem.style.cssText = originalHTMLCSS;
1080
+ body.style.cssText = originalBodyCSS;
1081
+
1082
+ }
1083
+ return eminpx || 16;
1084
+ };
1085
+
1086
+ /**
1087
+ * Takes a string of sizes and returns the width in pixels as a number
1088
+ */
1089
+ pf.calcListLength = function( sourceSizeListStr ) {
1090
+ // Split up source size list, ie ( max-width: 30em ) 100%, ( max-width: 50em ) 50%, 33%
1091
+ //
1092
+ // or (min-width:30em) calc(30% - 15px)
1093
+ if ( !(sourceSizeListStr in sizeLengthCache) || cfg.uT ) {
1094
+ var winningLength = pf.calcLength( parseSizes( sourceSizeListStr ) );
1095
+
1096
+ sizeLengthCache[ sourceSizeListStr ] = !winningLength ? units.width : winningLength;
1097
+ }
1098
+
1099
+ return sizeLengthCache[ sourceSizeListStr ];
1100
+ };
1101
+
1102
+ /**
1103
+ * Takes a candidate object with a srcset property in the form of url/
1104
+ * ex. "images/pic-medium.png 1x, images/pic-medium-2x.png 2x" or
1105
+ * "images/pic-medium.png 400w, images/pic-medium-2x.png 800w" or
1106
+ * "images/pic-small.png"
1107
+ * Get an array of image candidates in the form of
1108
+ * {url: "/foo/bar.png", resolution: 1}
1109
+ * where resolution is http://dev.w3.org/csswg/css-values-3/#resolution-value
1110
+ * If sizes is specified, res is calculated
1111
+ */
1112
+ pf.setRes = function( set ) {
1113
+ var candidates;
1114
+ if ( set ) {
1115
+
1116
+ candidates = pf.parseSet( set );
1117
+
1118
+ for ( var i = 0, len = candidates.length; i < len; i++ ) {
1119
+ setResolution( candidates[ i ], set.sizes );
1120
+ }
1121
+ }
1122
+ return candidates;
1123
+ };
1124
+
1125
+ pf.setRes.res = setResolution;
1126
+
1127
+ pf.applySetCandidate = function( candidates, img ) {
1128
+ if ( !candidates.length ) {return;}
1129
+ var candidate,
1130
+ i,
1131
+ j,
1132
+ length,
1133
+ bestCandidate,
1134
+ curSrc,
1135
+ curCan,
1136
+ candidateSrc,
1137
+ abortCurSrc;
1138
+
1139
+ var imageData = img[ pf.ns ];
1140
+ var dpr = pf.DPR;
1141
+
1142
+ curSrc = imageData.curSrc || img[curSrcProp];
1143
+
1144
+ curCan = imageData.curCan || setSrcToCur(img, curSrc, candidates[0].set);
1145
+
1146
+ // if we have a current source, we might either become lazy or give this source some advantage
1147
+ if ( curCan && curCan.set === candidates[ 0 ].set ) {
1148
+
1149
+ // if browser can abort image request and the image has a higher pixel density than needed
1150
+ // and this image isn't downloaded yet, we skip next part and try to save bandwidth
1151
+ abortCurSrc = (supportAbort && !img.complete && curCan.res - 0.1 > dpr);
1152
+
1153
+ if ( !abortCurSrc ) {
1154
+ curCan.cached = true;
1155
+
1156
+ // if current candidate is "best", "better" or "okay",
1157
+ // set it to bestCandidate
1158
+ if ( curCan.res >= dpr ) {
1159
+ bestCandidate = curCan;
1160
+ }
1161
+ }
1162
+ }
1163
+
1164
+ if ( !bestCandidate ) {
1165
+
1166
+ candidates.sort( ascendingSort );
1167
+
1168
+ length = candidates.length;
1169
+ bestCandidate = candidates[ length - 1 ];
1170
+
1171
+ for ( i = 0; i < length; i++ ) {
1172
+ candidate = candidates[ i ];
1173
+ if ( candidate.res >= dpr ) {
1174
+ j = i - 1;
1175
+
1176
+ // we have found the perfect candidate,
1177
+ // but let's improve this a little bit with some assumptions ;-)
1178
+ if (candidates[ j ] &&
1179
+ (abortCurSrc || curSrc !== pf.makeUrl( candidate.url )) &&
1180
+ chooseLowRes(candidates[ j ].res, candidate.res, dpr, candidates[ j ].cached)) {
1181
+
1182
+ bestCandidate = candidates[ j ];
1183
+
1184
+ } else {
1185
+ bestCandidate = candidate;
1186
+ }
1187
+ break;
1188
+ }
1189
+ }
1190
+ }
1191
+
1192
+ if ( bestCandidate ) {
1193
+
1194
+ candidateSrc = pf.makeUrl( bestCandidate.url );
1195
+
1196
+ imageData.curSrc = candidateSrc;
1197
+ imageData.curCan = bestCandidate;
1198
+
1199
+ if ( candidateSrc !== curSrc ) {
1200
+ pf.setSrc( img, bestCandidate );
1201
+ }
1202
+ pf.setSize( img );
1203
+ }
1204
+ };
1205
+
1206
+ pf.setSrc = function( img, bestCandidate ) {
1207
+ var origWidth;
1208
+ img.src = bestCandidate.url;
1209
+
1210
+ // although this is a specific Safari issue, we don't want to take too much different code paths
1211
+ if ( bestCandidate.set.type === "image/svg+xml" ) {
1212
+ origWidth = img.style.width;
1213
+ img.style.width = (img.offsetWidth + 1) + "px";
1214
+
1215
+ // next line only should trigger a repaint
1216
+ // if... is only done to trick dead code removal
1217
+ if ( img.offsetWidth + 1 ) {
1218
+ img.style.width = origWidth;
1219
+ }
1220
+ }
1221
+ };
1222
+
1223
+ pf.getSet = function( img ) {
1224
+ var i, set, supportsType;
1225
+ var match = false;
1226
+ var sets = img [ pf.ns ].sets;
1227
+
1228
+ for ( i = 0; i < sets.length && !match; i++ ) {
1229
+ set = sets[i];
1230
+
1231
+ if ( !set.srcset || !pf.matchesMedia( set.media ) || !(supportsType = pf.supportsType( set.type )) ) {
1232
+ continue;
1233
+ }
1234
+
1235
+ if ( supportsType === "pending" ) {
1236
+ set = supportsType;
1237
+ }
1238
+
1239
+ match = set;
1240
+ break;
1241
+ }
1242
+
1243
+ return match;
1244
+ };
1245
+
1246
+ pf.parseSets = function( element, parent, options ) {
1247
+ var srcsetAttribute, imageSet, isWDescripor, srcsetParsed;
1248
+
1249
+ var hasPicture = parent && parent.nodeName.toUpperCase() === "PICTURE";
1250
+ var imageData = element[ pf.ns ];
1251
+
1252
+ if ( imageData.src === undefined || options.src ) {
1253
+ imageData.src = getImgAttr.call( element, "src" );
1254
+ if ( imageData.src ) {
1255
+ setImgAttr.call( element, srcAttr, imageData.src );
1256
+ } else {
1257
+ removeImgAttr.call( element, srcAttr );
1258
+ }
1259
+ }
1260
+
1261
+ if ( imageData.srcset === undefined || options.srcset || !pf.supSrcset || element.srcset ) {
1262
+ srcsetAttribute = getImgAttr.call( element, "srcset" );
1263
+ imageData.srcset = srcsetAttribute;
1264
+ srcsetParsed = true;
1265
+ }
1266
+
1267
+ imageData.sets = [];
1268
+
1269
+ if ( hasPicture ) {
1270
+ imageData.pic = true;
1271
+ getAllSourceElements( parent, imageData.sets );
1272
+ }
1273
+
1274
+ if ( imageData.srcset ) {
1275
+ imageSet = {
1276
+ srcset: imageData.srcset,
1277
+ sizes: getImgAttr.call( element, "sizes" )
1278
+ };
1279
+
1280
+ imageData.sets.push( imageSet );
1281
+
1282
+ isWDescripor = (alwaysCheckWDescriptor || imageData.src) && regWDesc.test(imageData.srcset || "");
1283
+
1284
+ // add normal src as candidate, if source has no w descriptor
1285
+ if ( !isWDescripor && imageData.src && !getCandidateForSrc(imageData.src, imageSet) && !imageSet.has1x ) {
1286
+ imageSet.srcset += ", " + imageData.src;
1287
+ imageSet.cands.push({
1288
+ url: imageData.src,
1289
+ d: 1,
1290
+ set: imageSet
1291
+ });
1292
+ }
1293
+
1294
+ } else if ( imageData.src ) {
1295
+ imageData.sets.push( {
1296
+ srcset: imageData.src,
1297
+ sizes: null
1298
+ } );
1299
+ }
1300
+
1301
+ imageData.curCan = null;
1302
+ imageData.curSrc = undefined;
1303
+
1304
+ // if img has picture or the srcset was removed or has a srcset and does not support srcset at all
1305
+ // or has a w descriptor (and does not support sizes) set support to false to evaluate
1306
+ imageData.supported = !( hasPicture || ( imageSet && !pf.supSrcset ) || (isWDescripor && !pf.supSizes) );
1307
+
1308
+ if ( srcsetParsed && pf.supSrcset && !imageData.supported ) {
1309
+ if ( srcsetAttribute ) {
1310
+ setImgAttr.call( element, srcsetAttr, srcsetAttribute );
1311
+ element.srcset = "";
1312
+ } else {
1313
+ removeImgAttr.call( element, srcsetAttr );
1314
+ }
1315
+ }
1316
+
1317
+ if (imageData.supported && !imageData.srcset && ((!imageData.src && element.src) || element.src !== pf.makeUrl(imageData.src))) {
1318
+ if (imageData.src === null) {
1319
+ element.removeAttribute("src");
1320
+ } else {
1321
+ element.src = imageData.src;
1322
+ }
1323
+ }
1324
+
1325
+ imageData.parsed = true;
1326
+ };
1327
+
1328
+ pf.fillImg = function(element, options) {
1329
+ var imageData;
1330
+ var extreme = options.reselect || options.reevaluate;
1331
+
1332
+ // expando for caching data on the img
1333
+ if ( !element[ pf.ns ] ) {
1334
+ element[ pf.ns ] = {};
1335
+ }
1336
+
1337
+ imageData = element[ pf.ns ];
1338
+
1339
+ // if the element has already been evaluated, skip it
1340
+ // unless `options.reevaluate` is set to true ( this, for example,
1341
+ // is set to true when running `picturefill` on `resize` ).
1342
+ if ( !extreme && imageData.evaled === evalId ) {
1343
+ return;
1344
+ }
1345
+
1346
+ if ( !imageData.parsed || options.reevaluate ) {
1347
+ pf.parseSets( element, element.parentNode, options );
1348
+ }
1349
+
1350
+ if ( !imageData.supported ) {
1351
+ applyBestCandidate( element );
1352
+ } else {
1353
+ imageData.evaled = evalId;
1354
+ }
1355
+ };
1356
+
1357
+ pf.setupRun = function() {
1358
+ if ( !alreadyRun || isVwDirty || (DPR !== window.devicePixelRatio) ) {
1359
+ updateMetrics();
1360
+ }
1361
+ };
1362
+
1363
+ // If picture is supported, well, that's awesome.
1364
+ if ( pf.supPicture ) {
1365
+ picturefill = noop;
1366
+ pf.fillImg = noop;
1367
+ } else {
1368
+
1369
+ // Set up picture polyfill by polling the document
1370
+ (function() {
1371
+ var isDomReady;
1372
+ var regReady = window.attachEvent ? /d$|^c/ : /d$|^c|^i/;
1373
+
1374
+ var run = function() {
1375
+ var readyState = document.readyState || "";
1376
+
1377
+ timerId = setTimeout(run, readyState === "loading" ? 200 : 999);
1378
+ if ( document.body ) {
1379
+ pf.fillImgs();
1380
+ isDomReady = isDomReady || regReady.test(readyState);
1381
+ if ( isDomReady ) {
1382
+ clearTimeout( timerId );
1383
+ }
1384
+
1385
+ }
1386
+ };
1387
+
1388
+ var timerId = setTimeout(run, document.body ? 9 : 99);
1389
+
1390
+ // Also attach picturefill on resize and readystatechange
1391
+ // http://modernjavascript.blogspot.com/2013/08/building-better-debounce.html
1392
+ var debounce = function(func, wait) {
1393
+ var timeout, timestamp;
1394
+ var later = function() {
1395
+ var last = (new Date()) - timestamp;
1396
+
1397
+ if (last < wait) {
1398
+ timeout = setTimeout(later, wait - last);
1399
+ } else {
1400
+ timeout = null;
1401
+ func();
1402
+ }
1403
+ };
1404
+
1405
+ return function() {
1406
+ timestamp = new Date();
1407
+
1408
+ if (!timeout) {
1409
+ timeout = setTimeout(later, wait);
1410
+ }
1411
+ };
1412
+ };
1413
+ var lastClientWidth = docElem.clientHeight;
1414
+ var onResize = function() {
1415
+ isVwDirty = Math.max(window.innerWidth || 0, docElem.clientWidth) !== units.width || docElem.clientHeight !== lastClientWidth;
1416
+ lastClientWidth = docElem.clientHeight;
1417
+ if ( isVwDirty ) {
1418
+ pf.fillImgs();
1419
+ }
1420
+ };
1421
+
1422
+ on( window, "resize", debounce(onResize, 99 ) );
1423
+ on( document, "readystatechange", run );
1424
+ })();
1425
+ }
1426
+
1427
+ pf.picturefill = picturefill;
1428
+ //use this internally for easy monkey patching/performance testing
1429
+ pf.fillImgs = picturefill;
1430
+ pf.teardownRun = noop;
1431
+
1432
+ /* expose methods for testing */
1433
+ picturefill._ = pf;
1434
+
1435
+ window.picturefillCFG = {
1436
+ pf: pf,
1437
+ push: function(args) {
1438
+ var name = args.shift();
1439
+ if (typeof pf[name] === "function") {
1440
+ pf[name].apply(pf, args);
1441
+ } else {
1442
+ cfg[name] = args[0];
1443
+ if (alreadyRun) {
1444
+ pf.fillImgs( { reselect: true } );
1445
+ }
1446
+ }
1447
+ }
1448
+ };
1449
+
1450
+ while (setOptions && setOptions.length) {
1451
+ window.picturefillCFG.push(setOptions.shift());
1452
+ }
1453
+
1454
+ /* expose picturefill */
1455
+ window.picturefill = picturefill;
1456
+
1457
+ /* expose picturefill */
1458
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
1459
+ // CommonJS, just export
1460
+ module.exports = picturefill;
1461
+ } else if ( typeof define === "function" && define.amd ) {
1462
+ // AMD support
1463
+ define( "picturefill", function() { return picturefill; } );
1464
+ }
1465
+
1466
+ // IE8 evals this sync, so it must be the last thing we do
1467
+ if ( !pf.supPicture ) {
1468
+ types[ "image/webp" ] = detectTypeSupport("image/webp", "data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAABBxAR/Q9ERP8DAABWUDggGAAAADABAJ0BKgEAAQADADQlpAADcAD++/1QAA==" );
1469
+ }
1470
+
1471
+ } )( window, document );