webshims-rails 1.12.7 → 1.13.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/lib/webshims-rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/webshims/polyfiller.js +12 -1
  4. data/vendor/assets/javascripts/webshims/shims/combos/1.js +4 -1
  5. data/vendor/assets/javascripts/webshims/shims/combos/10.js +7 -4
  6. data/vendor/assets/javascripts/webshims/shims/combos/11.js +7 -4
  7. data/vendor/assets/javascripts/webshims/shims/combos/14.js +23 -10
  8. data/vendor/assets/javascripts/webshims/shims/combos/15.js +7 -2
  9. data/vendor/assets/javascripts/webshims/shims/combos/16.js +7 -2
  10. data/vendor/assets/javascripts/webshims/shims/combos/17.js +28 -13
  11. data/vendor/assets/javascripts/webshims/shims/combos/18.js +28 -13
  12. data/vendor/assets/javascripts/webshims/shims/combos/19.js +5 -4
  13. data/vendor/assets/javascripts/webshims/shims/combos/2.js +4 -1
  14. data/vendor/assets/javascripts/webshims/shims/combos/20.js +5 -4
  15. data/vendor/assets/javascripts/webshims/shims/combos/21.js +5 -4
  16. data/vendor/assets/javascripts/webshims/shims/combos/25.js +5 -4
  17. data/vendor/assets/javascripts/webshims/shims/combos/28.js +24 -10
  18. data/vendor/assets/javascripts/webshims/shims/combos/29.js +20 -9
  19. data/vendor/assets/javascripts/webshims/shims/combos/3.js +7 -2
  20. data/vendor/assets/javascripts/webshims/shims/combos/30.js +7 -2
  21. data/vendor/assets/javascripts/webshims/shims/combos/31.js +4 -1
  22. data/vendor/assets/javascripts/webshims/shims/combos/32.js +21 -9
  23. data/vendor/assets/javascripts/webshims/shims/combos/33.js +21 -9
  24. data/vendor/assets/javascripts/webshims/shims/combos/4.js +3 -1
  25. data/vendor/assets/javascripts/webshims/shims/combos/5.js +28 -13
  26. data/vendor/assets/javascripts/webshims/shims/combos/6.js +28 -13
  27. data/vendor/assets/javascripts/webshims/shims/combos/7.js +7 -2
  28. data/vendor/assets/javascripts/webshims/shims/combos/8.js +7 -2
  29. data/vendor/assets/javascripts/webshims/shims/combos/9.js +7 -4
  30. data/vendor/assets/javascripts/webshims/shims/form-core.js +4 -1
  31. data/vendor/assets/javascripts/webshims/shims/form-message.js +3 -1
  32. data/vendor/assets/javascripts/webshims/shims/form-number-date-api.js +20 -9
  33. data/vendor/assets/javascripts/webshims/shims/form-number-date-ui.js +7 -4
  34. data/vendor/assets/javascripts/webshims/shims/form-shim-extend2.js +7 -1
  35. data/vendor/assets/javascripts/webshims/shims/form-validation.js +4 -4
  36. data/vendor/assets/javascripts/webshims/shims/form-validators.js +6 -3
  37. data/vendor/assets/javascripts/webshims/shims/forms-picker.js +16 -13
  38. data/vendor/assets/javascripts/webshims/shims/mediaelement-jaris.js +5 -4
  39. data/vendor/assets/javascripts/webshims/shims/picture.js +570 -0
  40. data/vendor/assets/javascripts/webshims/shims/promise.js +684 -0
  41. data/vendor/assets/javascripts/webshims/shims/styles/color-picker.png +0 -0
  42. data/vendor/assets/javascripts/webshims/shims/styles/forms-ext.css +90 -38
  43. data/vendor/assets/javascripts/webshims/shims/styles/shim-ext.css +1039 -0
  44. data/vendor/assets/javascripts/webshims/shims/styles/widget.eot +0 -0
  45. data/vendor/assets/javascripts/webshims/shims/styles/widget.svg +12 -0
  46. data/vendor/assets/javascripts/webshims/shims/styles/widget.ttf +0 -0
  47. data/vendor/assets/javascripts/webshims/shims/styles/widget.woff +0 -0
  48. metadata +10 -10
  49. data/vendor/assets/javascripts/webshims/shims/styles/forms.png +0 -0
  50. data/vendor/assets/javascripts/webshims/shims/styles/scss/_api-forms-ext.scss +0 -219
  51. data/vendor/assets/javascripts/webshims/shims/styles/scss/_api-shim.scss +0 -115
  52. data/vendor/assets/javascripts/webshims/shims/styles/scss/_extends.scss +0 -31
  53. data/vendor/assets/javascripts/webshims/shims/styles/scss/forms-ext.scss +0 -479
  54. data/vendor/assets/javascripts/webshims/shims/styles/scss/forms-picker.scss +0 -488
  55. data/vendor/assets/javascripts/webshims/shims/styles/scss/shim-ext.scss +0 -2
  56. data/vendor/assets/javascripts/webshims/shims/styles/scss/shim.scss +0 -633
@@ -1136,6 +1136,12 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, u
1136
1136
  //pro forma
1137
1137
  ,color: 1
1138
1138
  },
1139
+ inputElements = {
1140
+ input: 1,
1141
+ INPUT: 1,
1142
+ textarea: 1,
1143
+ TEXTAREA: 1
1144
+ },
1139
1145
  timer,
1140
1146
  lastVal,
1141
1147
  input,
@@ -1181,7 +1187,7 @@ webshims.register('form-shim-extend2', function($, webshims, window, document, u
1181
1187
 
1182
1188
  $(doc)
1183
1189
  .on('focusin wswidgetfocusin', function(e){
1184
- if( e.target && !e.target.readOnly && !e.target.disabled && (e.target.nodeName || '').toLowerCase() == 'input' && !noInputTypes[e.target.type] && !(webshims.data(e.target, 'implemented') || {}).inputwidgets){
1190
+ if( e.target && !e.target.readOnly && !e.target.disabled && inputElements[e.target.nodeName] && !noInputTypes[e.target.type] && !(webshims.data(e.target, 'implemented') || {}).inputwidgets){
1185
1191
  observe($(e.target));
1186
1192
  }
1187
1193
  })
@@ -114,7 +114,7 @@ webshims.register('form-validation', function($, webshims, window, document, und
114
114
  return;
115
115
  }
116
116
  if(webshims.refreshCustomValidityRules && webshims.refreshCustomValidityRules(elem) == 'async'){
117
- $(elem).one('updatevalidation', switchValidityClass);
117
+ $(elem).one('updatevalidation.webshims', switchValidityClass);
118
118
  return;
119
119
  }
120
120
 
@@ -158,12 +158,12 @@ webshims.register('form-validation', function($, webshims, window, document, und
158
158
  //jQuery 1.6.1 IE9 bug (doubble trigger bug)
159
159
  setTimeout(function(){
160
160
  $(elem).trigger(trigger);
161
- }, 0);
161
+ });
162
162
  }
163
163
  if(generaltrigger){
164
164
  setTimeout(function(){
165
165
  $(elem).trigger(generaltrigger);
166
- }, 0);
166
+ });
167
167
  }
168
168
 
169
169
  $.removeData(elem, 'webshimsswitchvalidityclass');
@@ -178,7 +178,7 @@ webshims.register('form-validation', function($, webshims, window, document, und
178
178
  }
179
179
  switchClass();
180
180
  } else {
181
- $.data(elem, 'webshimsswitchvalidityclass', setTimeout(switchClass, 9));
181
+ $.data(elem, 'webshimsswitchvalidityclass', setTimeout(switchClass));
182
182
  }
183
183
  }
184
184
  };
@@ -147,7 +147,7 @@ var iValClasses = '.'+ options.iVal.errorClass +', .'+options.iVal.successClass;
147
147
  /*
148
148
  * adds support for HTML5 constraint validation
149
149
  * - partial pattern: <input data-partial-pattern="RegExp" />
150
- * - creditcard-validation: <input data-creditcard="" />
150
+ * - creditcard-validation: <input data-luhn="" />
151
151
  * - several dependent-validation patterns (examples):
152
152
  * - <input type="email" id="mail" /> <input data-dependent-validation='mail' />
153
153
  * - <input type="date" id="start" data-dependent-validation='{"from": "end", "prop": "max"}' /> <input type="date" id="end" data-dependent-validation='{"from": "start", "prop": "min"}' />
@@ -196,8 +196,11 @@ var iValClasses = '.'+ options.iVal.errorClass +', .'+options.iVal.successClass;
196
196
  }, 'Please check one of these checkboxes.');
197
197
 
198
198
  // based on https://sites.google.com/site/abapexamples/javascript/luhn-validation
199
- addCustomValidityRule('creditcard', function(elem, value, data){
200
- if(!value || (!data || !('creditcard' in data))){return;}
199
+ addCustomValidityRule('luhn', function(elem, value, data){
200
+ if(!value || (!data || (!('creditcard' in data) && !('luhn' in data)))){return;}
201
+ if(('creditcard' in data)){
202
+ webshims.error('data-creditcard was renamed to data-luhn!!!');
203
+ }
201
204
  value = value.replace(/\-/g, "");
202
205
  //if it's not numeric return true >- for invalid
203
206
  if(value != value * 1){return true;}
@@ -595,15 +595,21 @@ webshims.register('forms-picker', function($, webshims, window, document, undefi
595
595
  if(o.stepfactor){
596
596
  factor *= o.stepfactor;
597
597
  }
598
- try {
599
- that.elemHelper[name](factor);
600
-
601
- ret = that.elemHelper.prop('value');
602
-
603
- }
604
- catch (er) {
605
- if (!o.value && that.maxAsNumber >= that.minAsNumber) {
606
- ret = o.defValue;
598
+
599
+ if(factor > 0 && !isNaN(that.minAsNumber) && (isNaN(that.valueAsNumber) || that.valueAsNumber < that.minAsNumber) && that.elemHelper.prop('valueAsNumber') <= that.minAsNumber){
600
+ ret = that.asValue(that.minAsNumber);
601
+ } else if(factor < 0 && !isNaN(that.maxAsNumber) && (isNaN(that.valueAsNumber) || that.valueAsNumber > that.minAsNumber) && that.elemHelper.prop('valueAsNumber') <= that.maxAsNumber){
602
+ ret = that.asValue(that.maxAsNumber);
603
+ }
604
+
605
+ if(ret === false){
606
+ try {
607
+ that.elemHelper[name](factor);
608
+ ret = that.elemHelper.prop('value');
609
+ } catch (er) {
610
+ if (!o.value && that.maxAsNumber >= that.minAsNumber) {
611
+ ret = o.defValue;
612
+ }
607
613
  }
608
614
  }
609
615
  if (ret !== false && o.value != ret) {
@@ -645,10 +651,7 @@ webshims.register('forms-picker', function($, webshims, window, document, undefi
645
651
  }
646
652
  };
647
653
 
648
- spinElement.attr({
649
- 'autocomplete': 'off',
650
- role: 'spinbutton'
651
- }).on(spinEvents);
654
+ spinElement.on(spinEvents);
652
655
  }
653
656
  $(this.buttonWrapper)
654
657
  .on('mousepressstart mousepressend', '.step-up, .step-down', mousePress)
@@ -1229,14 +1229,15 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document,
1229
1229
 
1230
1230
 
1231
1231
  if(hasNative && hasFlash && !options.preferFlash){
1232
- var noSwitch = {
1233
- 1: 1
1232
+ var switchErrors = {
1233
+ 3: 1,
1234
+ 4: 1
1234
1235
  };
1235
1236
  var switchOptions = function(e){
1236
1237
  var media, error, parent;
1237
1238
  if(!options.preferFlash &&
1238
1239
  ($(e.target).is('audio, video') || ((parent = e.target.parentNode) && $('source', parent).last()[0] == e.target)) &&
1239
- (media = $(e.target).closest('audio, video')) && (error = media.prop('error')) && !noSwitch[error.code]
1240
+ (media = $(e.target).closest('audio, video')) && (error = media.prop('error')) && switchErrors[error.code]
1240
1241
  ){
1241
1242
 
1242
1243
  if(!options.preferFlash){
@@ -1257,7 +1258,7 @@ webshims.register('mediaelement-jaris', function($, webshims, window, document,
1257
1258
  document.addEventListener('error', switchOptions, true);
1258
1259
  $('audio, video').each(function(){
1259
1260
  var error = $.prop(this, 'error');
1260
- if(error && !noSwitch[error]){
1261
+ if(error && switchErrors[error]){
1261
1262
  switchOptions({target: this});
1262
1263
  return false;
1263
1264
  }
@@ -0,0 +1,570 @@
1
+ (function(){
2
+ "use strict";
3
+ try {
4
+ new Image();
5
+ } catch(e){
6
+ window.Image = function(){
7
+ return document.createElement('img');
8
+ };
9
+ }
10
+ setTimeout(function(){
11
+ var sel = 'picture, img[srcset]';
12
+ webshims.addReady(function(context, insertedElement){
13
+ if(context == document || !window.picturefill){return;}
14
+ if(context.querySelector(sel) || insertedElement.filter(sel).length){
15
+ window.picturefill();
16
+ }
17
+ });
18
+ });
19
+ })();
20
+
21
+ /*! Picturefill - v2.0.0-beta - 2014-05-02
22
+ * http://scottjehl.github.io/picturefill
23
+ * Copyright (c) 2014 https://github.com/scottjehl/picturefill/blob/master/Authors.txt; Licensed MIT */
24
+ /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license */
25
+
26
+ window.matchMedia || (window.matchMedia = function() {
27
+ "use strict";
28
+
29
+ // For browsers that support matchMedium api such as IE 9 and webkit
30
+ var styleMedia = (window.styleMedia || window.media);
31
+
32
+ // For those that don't support matchMedium
33
+ if (!styleMedia) {
34
+ var style = document.createElement('style'),
35
+ script = document.getElementsByTagName('script')[0],
36
+ info = null;
37
+
38
+ style.type = 'text/css';
39
+ style.id = 'matchmediajs-test';
40
+
41
+ script.parentNode.insertBefore(style, script);
42
+
43
+ // 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers
44
+ info = ('getComputedStyle' in window) && window.getComputedStyle(style, null) || style.currentStyle;
45
+
46
+ styleMedia = {
47
+ matchMedium: function(media) {
48
+ var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }';
49
+
50
+ // 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers
51
+ if (style.styleSheet) {
52
+ style.styleSheet.cssText = text;
53
+ } else {
54
+ style.textContent = text;
55
+ }
56
+
57
+ // Test if media query is true or false
58
+ return info.width === '1px';
59
+ }
60
+ };
61
+ }
62
+
63
+ return function(media) {
64
+ return {
65
+ matches: styleMedia.matchMedium(media || 'all'),
66
+ media: media || 'all'
67
+ };
68
+ };
69
+ }());
70
+ /*! Picturefill - Responsive Images that work today.
71
+ * Author: Scott Jehl, Filament Group, 2012 ( new proposal implemented by Shawn Jansepar )
72
+ * License: MIT/GPLv2
73
+ * Spec: http://picture.responsiveimages.org/
74
+ */
75
+ (function( w, doc ) {
76
+ // Enable strict mode
77
+ "use strict";
78
+
79
+ // If picture is supported, well, that's awesome. Let's get outta here...
80
+ if( w.HTMLPictureElement ){
81
+ return;
82
+ }
83
+
84
+ // HTML shim|v it for old IE (IE9 will still need the HTML video tag workaround)
85
+ doc.createElement( "picture" );
86
+
87
+ // local object for method references and testing exposure
88
+ var pf = {};
89
+
90
+ // namespace
91
+ pf.ns = "picturefill";
92
+
93
+ // srcset support test
94
+ pf.srcsetSupported = new w.Image().srcset !== undefined;
95
+
96
+ // just a string trim workaround
97
+ pf.trim = function( str ){
98
+ return str.trim ? str.trim() : str.replace( /^\s+|\s+$/g, "" );
99
+ };
100
+
101
+ // just a string endsWith workaround
102
+ pf.endsWith = function( str, suffix ){
103
+ return str.endsWith ? str.endsWith( suffix ) : str.indexOf( suffix, str.length - suffix.length ) !== -1;
104
+ };
105
+
106
+ /**
107
+ * Shortcut method for matchMedia ( for easy overriding in tests )
108
+ */
109
+ pf.matchesMedia = function( media ) {
110
+ return w.matchMedia && w.matchMedia( media ).matches;
111
+ };
112
+
113
+ /**
114
+ * Shortcut method for `devicePixelRatio` ( for easy overriding in tests )
115
+ */
116
+ pf.getDpr = function() {
117
+ return ( w.devicePixelRatio || 1 );
118
+ };
119
+
120
+ /**
121
+ * Get width in css pixel value from a "length" value
122
+ * http://dev.w3.org/csswg/css-values-3/#length-value
123
+ */
124
+ pf.getWidthFromLength = function( length ) {
125
+ // If no length was specified, or it is 0, default to `100vw` (per the spec).
126
+ length = length && parseFloat( length ) > 0 ? length : "100vw";
127
+
128
+ /**
129
+ * If length is specified in `vw` units, use `%` instead since the div we’re measuring
130
+ * is injected at the top of the document.
131
+ *
132
+ * TODO: maybe we should put this behind a feature test for `vw`?
133
+ */
134
+ length = length.replace( "vw", "%" );
135
+
136
+ // Create a cached element for getting length value widths
137
+ if( !pf.lengthEl ){
138
+ pf.lengthEl = doc.createElement( "div" );
139
+ doc.documentElement.insertBefore( pf.lengthEl, doc.documentElement.firstChild );
140
+ }
141
+
142
+ // Positioning styles help prevent padding/margin/width on `html` from throwing calculations off.
143
+ pf.lengthEl.style.cssText = "position: absolute; left: 0; width: " + length + ";";
144
+ // Using offsetWidth to get width from CSS
145
+ return pf.lengthEl.offsetWidth;
146
+ };
147
+
148
+ // container of supported mime types that one might need to qualify before using
149
+ pf.types = {};
150
+
151
+ // test svg support
152
+ pf.types[ "image/svg+xml" ] = doc.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Image', '1.1');
153
+
154
+ // test webp support, only when the markup calls for it
155
+ pf.types[ "image/webp" ] = function(){
156
+ // based on Modernizr's lossless img-webp test
157
+ // note: asynchronous
158
+ var img = new w.Image(),
159
+ type = "image/webp";
160
+
161
+ img.onerror = function(){
162
+ pf.types[ type ] = false;
163
+ picturefill();
164
+ };
165
+ img.onload = function(){
166
+ pf.types[ type ] = img.width === 1;
167
+ picturefill();
168
+ };
169
+ img.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
170
+ };
171
+
172
+ /**
173
+ * Takes a source element and checks if its type attribute is present and if so, supported
174
+ * Note: for type tests that require a async logic,
175
+ * you can define them as a function that'll run only if that type needs to be tested. Just make the test function call picturefill again when it is complete.
176
+ * see the async webp test above for example
177
+ */
178
+ pf.verifyTypeSupport = function( source ){
179
+ var type = source.getAttribute( "type" );
180
+ // if type attribute exists, return test result, otherwise return true
181
+ if( type === null || type === "" ){
182
+ return true;
183
+ }
184
+ else {
185
+ // if the type test is a function, run it and return "pending" status. The function will rerun picturefill on pending elements once finished.
186
+ if( typeof( pf.types[ type ] ) === "function" ){
187
+ pf.types[ type ]();
188
+ return "pending";
189
+ }
190
+ else {
191
+ return pf.types[ type ];
192
+ }
193
+ }
194
+ };
195
+
196
+ /**
197
+ * Parses an individual `size` and returns the length, and optional media query
198
+ */
199
+ pf.parseSize = function( sourceSizeStr ) {
200
+ var match = /(\([^)]+\))?\s*(.+)/g.exec( sourceSizeStr );
201
+ return {
202
+ media: match && match[1],
203
+ length: match && match[2]
204
+ };
205
+ };
206
+
207
+ /**
208
+ * Takes a string of sizes and returns the width in pixels as a number
209
+ */
210
+ pf.findWidthFromSourceSize = function( sourceSizeListStr ) {
211
+ // Split up source size list, ie ( max-width: 30em ) 100%, ( max-width: 50em ) 50%, 33%
212
+ // or (min-width:30em) calc(30% - 15px)
213
+ var sourceSizeList = pf.trim( sourceSizeListStr ).split( /\s*,\s*/ ),
214
+ winningLength;
215
+
216
+ for ( var i=0, len=sourceSizeList.length; i < len; i++ ) {
217
+ // Match <media-condition>? length, ie ( min-width: 50em ) 100%
218
+ var sourceSize = sourceSizeList[ i ],
219
+ // Split "( min-width: 50em ) 100%" into separate strings
220
+ parsedSize = pf.parseSize( sourceSize ),
221
+ length = parsedSize.length,
222
+ media = parsedSize.media;
223
+
224
+ if ( !length ) {
225
+ continue;
226
+ }
227
+ if ( !media || pf.matchesMedia( media ) ) {
228
+ // if there is no media query or it matches, choose this as our winning length
229
+ // and end algorithm
230
+ winningLength = length;
231
+ break;
232
+ }
233
+ }
234
+
235
+ // pass the length to a method that can properly determine length
236
+ // in pixels based on these formats: http://dev.w3.org/csswg/css-values-3/#length-value
237
+ return pf.getWidthFromLength( winningLength );
238
+ };
239
+
240
+ /**
241
+ * Takes a srcset in the form of url/
242
+ * ex. "images/pic-medium.png 1x, images/pic-medium-2x.png 2x" or
243
+ * "images/pic-medium.png 400w, images/pic-medium-2x.png 800w" or
244
+ * "images/pic-small.png"
245
+ * Get an array of image candidates in the form of
246
+ * {url: "/foo/bar.png", resolution: 1}
247
+ * where resolution is http://dev.w3.org/csswg/css-values-3/#resolution-value
248
+ * If sizes is specified, resolution is calculated
249
+ */
250
+ pf.getCandidatesFromSourceSet = function( srcset, sizes ) {
251
+ var candidates = pf.trim( srcset ).split( /,\s+/ ),
252
+ widthInCssPixels = sizes ? pf.findWidthFromSourceSize( sizes ) : "100%",
253
+ formattedCandidates = [];
254
+
255
+ for ( var i = 0, len = candidates.length; i < len; i++ ) {
256
+ var candidate = candidates[ i ],
257
+ candidateArr = candidate.split( /\s+/ ),
258
+ sizeDescriptor = candidateArr[ 1 ],
259
+ resolution;
260
+ if ( sizeDescriptor && ( sizeDescriptor.slice( -1 ) === "w" || sizeDescriptor.slice( -1 ) === "x" ) ) {
261
+ sizeDescriptor = sizeDescriptor.slice( 0, -1 );
262
+ }
263
+ if ( sizes ) {
264
+ // get the dpr by taking the length / width in css pixels
265
+ resolution = parseFloat( ( parseInt( sizeDescriptor, 10 ) / widthInCssPixels ) );
266
+ } else {
267
+ // get the dpr by grabbing the value of Nx
268
+ resolution = sizeDescriptor ? parseFloat( sizeDescriptor, 10 ) : 1;
269
+ }
270
+
271
+ var formattedCandidate = {
272
+ url: candidateArr[ 0 ],
273
+ resolution: resolution
274
+ };
275
+ formattedCandidates.push( formattedCandidate );
276
+ }
277
+ return formattedCandidates;
278
+ };
279
+
280
+ /*
281
+ * if it's an img element and it has a srcset property,
282
+ * we need to remove the attribute so we can manipulate src
283
+ * (the property's existence infers native srcset support, and a srcset-supporting browser will prioritize srcset's value over our winning picture candidate)
284
+ * this moves srcset's value to memory for later use and removes the attr
285
+ */
286
+ pf.dodgeSrcset = function( img ){
287
+ if( img.srcset ){
288
+ img[ pf.ns ].srcset = img.srcset;
289
+ img.removeAttribute( "srcset" );
290
+ }
291
+ };
292
+
293
+ /*
294
+ * Accept a source or img element and process its srcset and sizes attrs
295
+ */
296
+ pf.processSourceSet = function( el ) {
297
+ var srcset = el.getAttribute( "srcset" ),
298
+ sizes = el.getAttribute( "sizes" ),
299
+ candidates = [];
300
+
301
+ // if it's an img element, use the cached srcset property (defined or not)
302
+ if( el.nodeName.toUpperCase() === "IMG" && el[ pf.ns ] && el[ pf.ns ].srcset ){
303
+ srcset = el[ pf.ns ].srcset;
304
+ }
305
+
306
+ if( srcset ) {
307
+ candidates = pf.getCandidatesFromSourceSet( srcset, sizes );
308
+ }
309
+ return candidates;
310
+ };
311
+
312
+ pf.applyBestCandidate = function( candidates, picImg ) {
313
+ var candidate,
314
+ length,
315
+ bestCandidate;
316
+
317
+ candidates.sort( pf.ascendingSort );
318
+
319
+ length = candidates.length;
320
+ bestCandidate = candidates[ length - 1 ];
321
+
322
+ for ( var l=0; l < length; l++ ) {
323
+ candidate = candidates[ l ];
324
+ if ( candidate.resolution >= pf.getDpr() ) {
325
+ bestCandidate = candidate;
326
+ break;
327
+ }
328
+ }
329
+
330
+ if ( !pf.endsWith( picImg.src, bestCandidate.url ) ) {
331
+ picImg.src = bestCandidate.url;
332
+ // currentSrc attribute and property to match
333
+ // http://picture.responsiveimages.org/#the-img-element
334
+ picImg.currentSrc = picImg.src;
335
+ }
336
+ };
337
+
338
+ pf.ascendingSort = function( a, b ) {
339
+ return a.resolution - b.resolution;
340
+ };
341
+
342
+ /*
343
+ * In IE9, <source> elements get removed if they aren"t children of
344
+ * video elements. Thus, we conditionally wrap source elements
345
+ * using <!--[if IE 9]><video style="display: none;"><![endif]-->
346
+ * and must account for that here by moving those source elements
347
+ * back into the picture element.
348
+ */
349
+ pf.removeVideoShim = function( picture ){
350
+ var videos = picture.getElementsByTagName( "video" );
351
+ if ( videos.length ) {
352
+ var video = videos[ 0 ],
353
+ vsources = video.getElementsByTagName( "source" );
354
+ while ( vsources.length ) {
355
+ picture.insertBefore( vsources[ 0 ], video );
356
+ }
357
+ // Remove the video element once we're finished removing its children
358
+ video.parentNode.removeChild( video );
359
+ }
360
+ };
361
+
362
+ /*
363
+ * Find all picture elements and,
364
+ * in browsers that don't natively support srcset, find all img elements
365
+ * with srcset attrs that don't have picture parents
366
+ */
367
+ pf.getAllElements = function() {
368
+ var pictures = doc.getElementsByTagName( "picture" ),
369
+ elems = [],
370
+ imgs = doc.getElementsByTagName( "img" );
371
+
372
+ for ( var h = 0, len = pictures.length + imgs.length; h < len; h++ ) {
373
+ if ( h < pictures.length ){
374
+ elems[ h ] = pictures[ h ];
375
+ }
376
+ else {
377
+ var currImg = imgs[ h - pictures.length ];
378
+
379
+ if ( currImg.parentNode.nodeName.toUpperCase() !== "PICTURE" &&
380
+ ( ( pf.srcsetSupported && currImg.getAttribute( "sizes" ) ) ||
381
+ currImg.getAttribute( "srcset" ) !== null ) ) {
382
+ elems.push( currImg );
383
+ }
384
+ }
385
+ }
386
+ return elems;
387
+ };
388
+
389
+ pf.getMatch = function( picture ) {
390
+ var sources = picture.childNodes,
391
+ match;
392
+
393
+ // Go through each child, and if they have media queries, evaluate them
394
+ for ( var j=0, slen = sources.length; j < slen; j++ ) {
395
+ var source = sources[ j ];
396
+
397
+ // ignore non-element nodes
398
+ if( source.nodeType !== 1 ){
399
+ continue;
400
+ }
401
+
402
+ // Hitting an `img` element stops the search for `sources`.
403
+ // If no previous `source` matches, the `img` itself is evaluated later.
404
+ if( source.nodeName.toUpperCase() === "IMG" ) {
405
+ return match;
406
+ }
407
+
408
+ // ignore non-`source` nodes
409
+ if( source.nodeName.toUpperCase() !== "SOURCE" ){
410
+ continue;
411
+ }
412
+
413
+ var media = source.getAttribute( "media" );
414
+
415
+ // if source does not have a srcset attribute, skip
416
+ if ( !source.getAttribute( "srcset" ) ) {
417
+ continue;
418
+ }
419
+
420
+ // if there"s no media specified, OR w.matchMedia is supported
421
+ if( ( !media || pf.matchesMedia( media ) ) ){
422
+ var typeSupported = pf.verifyTypeSupport( source );
423
+
424
+ if( typeSupported === true ){
425
+ match = source;
426
+ break;
427
+ } else if( typeSupported === "pending" ){
428
+ return false;
429
+ }
430
+ }
431
+ }
432
+
433
+ return match;
434
+ };
435
+
436
+ function picturefill( options ) {
437
+ var elements,
438
+ element,
439
+ elemType,
440
+ firstMatch,
441
+ candidates,
442
+ picImg;
443
+
444
+ options = options || {};
445
+ elements = options.elements || pf.getAllElements();
446
+
447
+ // Loop through all elements
448
+ for ( var i=0, plen = elements.length; i < plen; i++ ) {
449
+ element = elements[ i ];
450
+ elemType = element.nodeName.toUpperCase();
451
+ firstMatch = undefined;
452
+ candidates = undefined;
453
+ picImg = undefined;
454
+
455
+ // expando for caching data on the img
456
+ if( !element[ pf.ns ] ){
457
+ element[ pf.ns ] = {};
458
+ }
459
+
460
+ // if the element has already been evaluated, skip it
461
+ // unless `options.force` is set to true ( this, for example,
462
+ // is set to true when running `picturefill` on `resize` ).
463
+ if ( !options.reevaluate && element[ pf.ns ].evaluated ) {
464
+ continue;
465
+ }
466
+
467
+ // if element is a picture element
468
+ if( elemType === "PICTURE" ){
469
+
470
+ // IE9 video workaround
471
+ pf.removeVideoShim( element );
472
+
473
+ // return the first match which might undefined
474
+ // returns false if there is a pending source
475
+ // TODO the return type here is brutal, cleanup
476
+ firstMatch = pf.getMatch( element );
477
+
478
+ // if any sources are pending in this picture due to async type test(s)
479
+ // remove the evaluated attr and skip for now ( the pending test will
480
+ // rerun picturefill on this element when complete)
481
+ if( firstMatch === false ) {
482
+ continue;
483
+ }
484
+
485
+ // Find any existing img element in the picture element
486
+ picImg = element.getElementsByTagName( "img" )[ 0 ];
487
+ } else {
488
+ // if it's an img element
489
+ firstMatch = undefined;
490
+ picImg = element;
491
+ }
492
+
493
+ if( picImg ) {
494
+
495
+ // expando for caching data on the img
496
+ if( !picImg[ pf.ns ] ){
497
+ picImg[ pf.ns ] = {};
498
+ }
499
+
500
+ // Cache and remove `srcset` if present and we’re going to be doing `sizes`/`picture` polyfilling to it.
501
+ if( picImg.srcset && ( elemType === "PICTURE" || picImg.getAttribute( "sizes" ) ) ){
502
+ pf.dodgeSrcset( picImg );
503
+ }
504
+
505
+ if ( firstMatch ) {
506
+ candidates = pf.processSourceSet( firstMatch );
507
+ pf.applyBestCandidate( candidates, picImg );
508
+ } else {
509
+ // No sources matched, so we’re down to processing the inner `img` as a source.
510
+ candidates = pf.processSourceSet( picImg );
511
+
512
+ if( picImg.srcset === undefined || picImg.getAttribute( "sizes" ) ) {
513
+ // Either `srcset` is completely unsupported, or we need to polyfill `sizes` functionality.
514
+ pf.applyBestCandidate( candidates, picImg );
515
+ } // Else, resolution-only `srcset` is supported natively.
516
+ }
517
+
518
+ // set evaluated to true to avoid unnecessary reparsing
519
+ element[ pf.ns ].evaluated = true;
520
+ }
521
+ }
522
+ }
523
+
524
+ /**
525
+ * Sets up picture polyfill by polling the document and running
526
+ * the polyfill every 250ms until the document is ready.
527
+ * Also attaches picturefill on resize
528
+ */
529
+ function runPicturefill() {
530
+ picturefill();
531
+ var intervalId = setInterval( function(){
532
+ // When the document has finished loading, stop checking for new images
533
+ // https://github.com/ded/domready/blob/master/ready.js#L15
534
+ w.picturefill();
535
+ if ( /^loaded|^i|^c/.test( doc.readyState ) ) {
536
+ clearInterval( intervalId );
537
+ return;
538
+ }
539
+ }, 250 );
540
+ if( w.addEventListener ){
541
+ var resizeThrottle;
542
+ w.addEventListener( "resize", function() {
543
+ w.clearTimeout( resizeThrottle );
544
+ resizeThrottle = w.setTimeout( function(){
545
+ picturefill({ reevaluate: true });
546
+ }, 60 );
547
+ }, false );
548
+ }
549
+ }
550
+
551
+ runPicturefill();
552
+
553
+ /* expose methods for testing */
554
+ picturefill._ = pf;
555
+
556
+ /* expose picturefill */
557
+ if ( typeof module === "object" && typeof module.exports === "object" ){
558
+ // CommonJS, just export
559
+ module.exports = picturefill;
560
+ }
561
+ else if( typeof define === "object" && define.amd ){
562
+ // AMD support
563
+ define( function(){ return picturefill; } );
564
+ }
565
+ else if( typeof w === "object" ){
566
+ // If no AMD and we are in the browser, attach to window
567
+ w.picturefill = picturefill;
568
+ }
569
+
570
+ } )( this, this.document );