webshims-rails 1.12.7 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
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 );