modernizr-rails 2.6.2.2 → 2.6.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # modernizr-rails
2
2
 
3
- The modernizr-rails gem will include the [Modernizr.js](https://github.com/Modernizr/Modernizr) library into your `Rails 3.1+` app via the asset pipeline. This modernizr.js file was built using the builder located at http://www.modernizr.com/download/ with all options checked.
3
+ The modernizr-rails gem will include the [Modernizr.js](https://github.com/Modernizr/Modernizr) library into your `Rails 3.1+` app via the asset pipeline. This gem is bundled with the development version from the [Modernizr site](http://modernizr.com), which is minified by the Rails Assets Pipeline for you automatically. If you need custom feature detection tests, consider the [Custom feature detection tests](#custom-feature-detection-tests) section in this README.
4
4
 
5
5
  ## Installation
6
6
  Add the following to your `assets` group in your Gemfile:
@@ -21,7 +21,7 @@ Example of your `app/views/layouts/application.html.erb`:
21
21
  ```erb
22
22
  <html>
23
23
  <head>
24
- <title>Your App</title>
24
+ <title>Your Awesome App</title>
25
25
  <%= stylesheet_link_tag :application, media: :all %>
26
26
  <%= javascript_include_tag :modernizr %>
27
27
  <%= csrf_meta_tags %>
@@ -33,6 +33,15 @@ Example of your `app/views/layouts/application.html.erb`:
33
33
  </html>
34
34
  ```
35
35
 
36
+ ## Custom feature detection tests
37
+ I you need a custom feature detection test not included in the Modernizr build shipped with this gem, please consider using your own version instead of sending a pull request to include your test. You can easily do this by moving your Modernizr build in to one of the assets folder. Rails will automagically use your build instead of the shipped one. However you can still continue to use this gem and its features (like the precompile hook, and so on).
38
+
39
+ 1. Configure your build on [modernizr.com/download](http://modernizr.com/download/).
40
+ 2. Download it.
41
+ 3. Rename it from `modernizr.custom.12345.js` to just `modernizr.js`.
42
+ 4. Move it to your asset pipeline folder, ideally `vendor/assets/javascripts`.
43
+ 5. Enjoy your custom build! :)
44
+
36
45
  ## Contributing
37
46
 
38
47
  1. Fork it
@@ -1,5 +1,5 @@
1
1
  module Modernizr
2
2
  module Rails
3
- VERSION = '2.6.2.2'
3
+ VERSION = '2.6.2.3'
4
4
  end
5
5
  end
@@ -1,9 +1,26 @@
1
- /* Modernizr 2.6.2 (Custom Build) | MIT & BSD
2
- * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexboxlegacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-printshiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-a_download-audio_audiodata_api-audio_webaudio_api-battery_api-battery_level-blob_constructor-canvas_todataurl_type-contenteditable-contentsecuritypolicy-contextmenu-cookies-cors-css_backgroundposition_shorthand-css_backgroundposition_xy-css_backgroundrepeat-css_backgroundsizecover-css_boxsizing-css_calc-css_cubicbezierrange-css_displayrunin-css_displaytable-css_filters-css_hyphens-css_lastchild-css_mask-css_mediaqueries-css_objectfit-css_overflow_scrolling-css_pointerevents-css_positionsticky-css_remunit-css_regions-css_resize-css_scrollbars-css_subpixelfont-css_supports-css_userselect-css_vhunit-css_vmaxunit-css_vminunit-css_vwunit-custom_protocol_handler-dataview_api-dom_classlist-dom_createElement_attrs-dom_dataset-dom_microdata-elem_datalist-elem_details-elem_output-elem_progress_meter-elem_ruby-elem_time-elem_track-emoji-es5_strictmode-event_deviceorientation_motion-exif_orientation-file_api-forms_fileinput-forms_formattribute-file_filesystem-forms_placeholder-forms_speechinput-forms_validation-fullscreen_api-gamepad-getusermedia-ie8compat-iframe_sandbox-iframe_seamless-iframe_srcdoc-img_apng-img_webp-json-lists_reversed-mathml-network_connection-network_eventsource-network_xhr2-notification-performance-pointerlock_api-quota_management_api-requestanimationframe-script_async-script_defer-style_scoped-svg_filters-unicode-url_data_uri-userdata-vibration-web_intents-webgl_extensions-websockets_binary-window_framed-workers_blobworkers-workers_dataworkers-workers_sharedworkers-load
1
+ /*!
2
+ * Modernizr v2.6.2
3
+ * www.modernizr.com
4
+ *
5
+ * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton
6
+ * Available under the BSD and MIT licenses: www.modernizr.com/license/
3
7
  */
4
- ;
5
-
6
8
 
9
+ /*
10
+ * Modernizr tests which native CSS3 and HTML5 features are available in
11
+ * the current UA and makes the results available to you in two ways:
12
+ * as properties on a global Modernizr object, and as classes on the
13
+ * <html> element. This information allows you to progressively enhance
14
+ * your pages with a granular level of control over the experience.
15
+ *
16
+ * Modernizr has an optional (not included) conditional resource loader
17
+ * called Modernizr.load(), based on Yepnope.js (yepnopejs.com).
18
+ * To get a build that includes Modernizr.load(), as well as choosing
19
+ * which tests to include, go to www.modernizr.com/download/
20
+ *
21
+ * Authors Faruk Ates, Paul Irish, Alex Sexton
22
+ * Contributors Ryan Seddon, Ben Alman
23
+ */
7
24
 
8
25
  window.Modernizr = (function( window, document, undefined ) {
9
26
 
@@ -11,31 +28,58 @@ window.Modernizr = (function( window, document, undefined ) {
11
28
 
12
29
  Modernizr = {},
13
30
 
31
+ /*>>cssclasses*/
32
+ // option for enabling the HTML classes to be added
14
33
  enableClasses = true,
34
+ /*>>cssclasses*/
15
35
 
16
36
  docElement = document.documentElement,
17
37
 
38
+ /**
39
+ * Create our "modernizr" element that we do most feature tests on.
40
+ */
18
41
  mod = 'modernizr',
19
42
  modElem = document.createElement(mod),
20
43
  mStyle = modElem.style,
21
44
 
22
- inputElem = document.createElement('input') ,
45
+ /**
46
+ * Create the input element for various Web Forms feature tests.
47
+ */
48
+ inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ ,
23
49
 
50
+ /*>>smile*/
24
51
  smile = ':)',
52
+ /*>>smile*/
25
53
 
26
54
  toString = {}.toString,
27
55
 
56
+ // TODO :: make the prefixes more granular
57
+ /*>>prefixes*/
58
+ // List of property values to set for css tests. See ticket #21
28
59
  prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
60
+ /*>>prefixes*/
29
61
 
62
+ /*>>domprefixes*/
63
+ // Following spec is to expose vendor-specific style properties as:
64
+ // elem.style.WebkitBorderRadius
65
+ // and the following would be incorrect:
66
+ // elem.style.webkitBorderRadius
30
67
 
68
+ // Webkit ghosts their properties in lowercase but Opera & Moz do not.
69
+ // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
70
+ // erik.eae.net/archives/2008/03/10/21.48.10/
31
71
 
72
+ // More here: github.com/Modernizr/Modernizr/issues/issue/21
32
73
  omPrefixes = 'Webkit Moz O ms',
33
74
 
34
75
  cssomPrefixes = omPrefixes.split(' '),
35
76
 
36
77
  domPrefixes = omPrefixes.toLowerCase().split(' '),
78
+ /*>>domprefixes*/
37
79
 
80
+ /*>>ns*/
38
81
  ns = {'svg': 'http://www.w3.org/2000/svg'},
82
+ /*>>ns*/
39
83
 
40
84
  tests = {},
41
85
  inputs = {},
@@ -45,38 +89,54 @@ window.Modernizr = (function( window, document, undefined ) {
45
89
 
46
90
  slice = classes.slice,
47
91
 
48
- featureName,
92
+ featureName, // used in testing loop
49
93
 
50
94
 
95
+ /*>>teststyles*/
96
+ // Inject element with style element and some CSS rules
51
97
  injectElementWithStyles = function( rule, callback, nodes, testnames ) {
52
98
 
53
99
  var style, ret, node, docOverflow,
54
100
  div = document.createElement('div'),
55
- body = document.body,
56
- fakeBody = body || document.createElement('body');
101
+ // After page load injecting a fake body doesn't work so check if body exists
102
+ body = document.body,
103
+ // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it.
104
+ fakeBody = body || document.createElement('body');
57
105
 
58
106
  if ( parseInt(nodes, 10) ) {
59
- while ( nodes-- ) {
107
+ // In order not to give false positives we create a node for each test
108
+ // This also allows the method to scale for unspecified uses
109
+ while ( nodes-- ) {
60
110
  node = document.createElement('div');
61
111
  node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
62
112
  div.appendChild(node);
63
113
  }
64
114
  }
65
115
 
66
- style = ['&#173;','<style id="s', mod, '">', rule, '</style>'].join('');
116
+ // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed
117
+ // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element
118
+ // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements.
119
+ // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx
120
+ // Documents served as xml will throw if using &shy; so use xml friendly encoded version. See issue #277
121
+ style = ['&#173;','<style id="s', mod, '">', rule, '</style>'].join('');
67
122
  div.id = mod;
68
- (body ? div : fakeBody).innerHTML += style;
123
+ // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.
124
+ // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
125
+ (body ? div : fakeBody).innerHTML += style;
69
126
  fakeBody.appendChild(div);
70
127
  if ( !body ) {
71
- fakeBody.style.background = '';
72
- fakeBody.style.overflow = 'hidden';
128
+ //avoid crashing IE8, if background image is used
129
+ fakeBody.style.background = '';
130
+ //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
131
+ fakeBody.style.overflow = 'hidden';
73
132
  docOverflow = docElement.style.overflow;
74
133
  docElement.style.overflow = 'hidden';
75
134
  docElement.appendChild(fakeBody);
76
135
  }
77
136
 
78
137
  ret = callback(div, rule);
79
- if ( !body ) {
138
+ // If this is done after page load we don't want to remove the body so check if body exists
139
+ if ( !body ) {
80
140
  fakeBody.parentNode.removeChild(fakeBody);
81
141
  docElement.style.overflow = docOverflow;
82
142
  } else {
@@ -86,7 +146,12 @@ window.Modernizr = (function( window, document, undefined ) {
86
146
  return !!ret;
87
147
 
88
148
  },
149
+ /*>>teststyles*/
89
150
 
151
+ /*>>mq*/
152
+ // adapted from matchMedia polyfill
153
+ // by Scott Jehl and Paul Irish
154
+ // gist.github.com/786768
90
155
  testMediaQuery = function( mq ) {
91
156
 
92
157
  var matchMedia = window.matchMedia || window.msMatchMedia;
@@ -105,8 +170,18 @@ window.Modernizr = (function( window, document, undefined ) {
105
170
  return bool;
106
171
 
107
172
  },
108
-
109
-
173
+ /*>>mq*/
174
+
175
+
176
+ /*>>hasevent*/
177
+ //
178
+ // isEventSupported determines if a given element supports the given event
179
+ // kangax.github.com/iseventsupported/
180
+ //
181
+ // The following results are known incorrects:
182
+ // Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative
183
+ // Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333
184
+ // ...
110
185
  isEventSupported = (function() {
111
186
 
112
187
  var TAGNAMES = {
@@ -120,17 +195,20 @@ window.Modernizr = (function( window, document, undefined ) {
120
195
  element = element || document.createElement(TAGNAMES[eventName] || 'div');
121
196
  eventName = 'on' + eventName;
122
197
 
123
- var isSupported = eventName in element;
198
+ // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
199
+ var isSupported = eventName in element;
124
200
 
125
201
  if ( !isSupported ) {
126
- if ( !element.setAttribute ) {
202
+ // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
203
+ if ( !element.setAttribute ) {
127
204
  element = document.createElement('div');
128
205
  }
129
206
  if ( element.setAttribute && element.removeAttribute ) {
130
207
  element.setAttribute(eventName, '');
131
208
  isSupported = is(element[eventName], 'function');
132
209
 
133
- if ( !is(element[eventName], 'undefined') ) {
210
+ // If property was created, "remove it" (by setting value to `undefined`)
211
+ if ( !is(element[eventName], 'undefined') ) {
134
212
  element[eventName] = undefined;
135
213
  }
136
214
  element.removeAttribute(eventName);
@@ -142,8 +220,11 @@ window.Modernizr = (function( window, document, undefined ) {
142
220
  }
143
221
  return isEventSupported;
144
222
  })(),
223
+ /*>>hasevent*/
145
224
 
225
+ // TODO :: Add flag for hasownprop ? didn't last time
146
226
 
227
+ // hasOwnProperty shim by kangax needed for Safari 2.0 support
147
228
  _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
148
229
 
149
230
  if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
@@ -152,11 +233,13 @@ window.Modernizr = (function( window, document, undefined ) {
152
233
  };
153
234
  }
154
235
  else {
155
- hasOwnProp = function (object, property) {
236
+ hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
156
237
  return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
157
238
  };
158
239
  }
159
240
 
241
+ // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js
242
+ // es5.github.com/#x15.3.4.5
160
243
 
161
244
  if (!Function.prototype.bind) {
162
245
  Function.prototype.bind = function bind(that) {
@@ -200,22 +283,54 @@ window.Modernizr = (function( window, document, undefined ) {
200
283
  };
201
284
  }
202
285
 
286
+ /**
287
+ * setCss applies given styles to the Modernizr DOM node.
288
+ */
203
289
  function setCss( str ) {
204
290
  mStyle.cssText = str;
205
291
  }
206
292
 
293
+ /**
294
+ * setCssAll extrapolates all vendor-specific css strings.
295
+ */
207
296
  function setCssAll( str1, str2 ) {
208
297
  return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
209
298
  }
210
299
 
300
+ /**
301
+ * is returns a boolean for if typeof obj is exactly type.
302
+ */
211
303
  function is( obj, type ) {
212
304
  return typeof obj === type;
213
305
  }
214
306
 
307
+ /**
308
+ * contains returns a boolean for if substr is found within str.
309
+ */
215
310
  function contains( str, substr ) {
216
311
  return !!~('' + str).indexOf(substr);
217
312
  }
218
313
 
314
+ /*>>testprop*/
315
+
316
+ // testProps is a generic CSS / DOM property test.
317
+
318
+ // In testing support for a given CSS property, it's legit to test:
319
+ // `elem.style[styleName] !== undefined`
320
+ // If the property is supported it will return an empty string,
321
+ // if unsupported it will return undefined.
322
+
323
+ // We'll take advantage of this quick test and skip setting a style
324
+ // on our modernizr element, but instead just testing undefined vs
325
+ // empty string.
326
+
327
+ // Because the testing of the CSS property names (with "-", as
328
+ // opposed to the camelCase DOM properties) is non-portable and
329
+ // non-standard but works in WebKit and IE (but not Gecko or Opera),
330
+ // we explicitly reject properties with dashes so that authors
331
+ // developing in WebKit or IE first don't end up with
332
+ // browser-specific content by accident.
333
+
219
334
  function testProps( props, prefixed ) {
220
335
  for ( var i in props ) {
221
336
  var prop = props[i];
@@ -225,45 +340,81 @@ window.Modernizr = (function( window, document, undefined ) {
225
340
  }
226
341
  return false;
227
342
  }
343
+ /*>>testprop*/
228
344
 
345
+ // TODO :: add testDOMProps
346
+ /**
347
+ * testDOMProps is a generic DOM property test; if a browser supports
348
+ * a certain property, it won't return undefined for it.
349
+ */
229
350
  function testDOMProps( props, obj, elem ) {
230
351
  for ( var i in props ) {
231
352
  var item = obj[props[i]];
232
353
  if ( item !== undefined) {
233
354
 
234
- if (elem === false) return props[i];
355
+ // return the property name as a string
356
+ if (elem === false) return props[i];
235
357
 
236
- if (is(item, 'function')){
237
- return item.bind(elem || obj);
358
+ // let's bind a function
359
+ if (is(item, 'function')){
360
+ // default to autobind unless override
361
+ return item.bind(elem || obj);
238
362
  }
239
363
 
240
- return item;
364
+ // return the unbound function or obj or value
365
+ return item;
241
366
  }
242
367
  }
243
368
  return false;
244
369
  }
245
370
 
371
+ /*>>testallprops*/
372
+ /**
373
+ * testPropsAll tests a list of DOM properties we want to check against.
374
+ * We specify literally ALL possible (known and/or likely) properties on
375
+ * the element including the non-vendor prefixed one, for forward-
376
+ * compatibility.
377
+ */
246
378
  function testPropsAll( prop, prefixed, elem ) {
247
379
 
248
380
  var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
249
381
  props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
250
382
 
251
- if(is(prefixed, "string") || is(prefixed, "undefined")) {
383
+ // did they call .prefixed('boxSizing') or are we just testing a prop?
384
+ if(is(prefixed, "string") || is(prefixed, "undefined")) {
252
385
  return testProps(props, prefixed);
253
386
 
254
- } else {
387
+ // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
388
+ } else {
255
389
  props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
256
390
  return testDOMProps(props, prefixed, elem);
257
391
  }
258
- } tests['flexbox'] = function() {
392
+ }
393
+ /*>>testallprops*/
394
+
395
+
396
+ /**
397
+ * Tests
398
+ * -----
399
+ */
400
+
401
+ // The *new* flexbox
402
+ // dev.w3.org/csswg/css3-flexbox
403
+
404
+ tests['flexbox'] = function() {
259
405
  return testPropsAll('flexWrap');
260
406
  };
261
407
 
408
+ // The *old* flexbox
409
+ // www.w3.org/TR/2009/WD-css3-flexbox-20090723/
262
410
 
263
411
  tests['flexboxlegacy'] = function() {
264
412
  return testPropsAll('boxDirection');
265
413
  };
266
414
 
415
+ // On the S60 and BB Storm, getContext exists, but always returns undefined
416
+ // so we actually have to call getContext() to verify
417
+ // github.com/Modernizr/Modernizr/issues/issue/97/
267
418
 
268
419
  tests['canvas'] = function() {
269
420
  var elem = document.createElement('canvas');
@@ -274,12 +425,28 @@ window.Modernizr = (function( window, document, undefined ) {
274
425
  return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
275
426
  };
276
427
 
428
+ // webk.it/70117 is tracking a legit WebGL feature detect proposal
277
429
 
430
+ // We do a soft detect which may false positive in order to avoid
431
+ // an expensive context creation: bugzil.la/732441
278
432
 
279
433
  tests['webgl'] = function() {
280
434
  return !!window.WebGLRenderingContext;
281
435
  };
282
436
 
437
+ /*
438
+ * The Modernizr.touch test only indicates if the browser supports
439
+ * touch events, which does not necessarily reflect a touchscreen
440
+ * device, as evidenced by tablets running Windows 7 or, alas,
441
+ * the Palm Pre / WebOS (touch) phones.
442
+ *
443
+ * Additionally, Chrome (desktop) used to lie about its support on this,
444
+ * but that has since been rectified: crbug.com/36415
445
+ *
446
+ * We also test for Firefox 4 Multitouch Support.
447
+ *
448
+ * For more info, see: modernizr.github.com/Modernizr/touch.html
449
+ */
283
450
 
284
451
  tests['touch'] = function() {
285
452
  var bool;
@@ -296,6 +463,15 @@ window.Modernizr = (function( window, document, undefined ) {
296
463
  };
297
464
 
298
465
 
466
+ // geolocation is often considered a trivial feature detect...
467
+ // Turns out, it's quite tricky to get right:
468
+ //
469
+ // Using !!navigator.geolocation does two things we don't want. It:
470
+ // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513
471
+ // 2. Disables page caching in WebKit: webk.it/43956
472
+ //
473
+ // Meanwhile, in Firefox < 8, an about:config setting could expose
474
+ // a false positive that would throw an exception: bugzil.la/688158
299
475
 
300
476
  tests['geolocation'] = function() {
301
477
  return 'geolocation' in navigator;
@@ -307,18 +483,31 @@ window.Modernizr = (function( window, document, undefined ) {
307
483
  };
308
484
 
309
485
 
486
+ // Chrome incognito mode used to throw an exception when using openDatabase
487
+ // It doesn't anymore.
310
488
  tests['websqldatabase'] = function() {
311
489
  return !!window.openDatabase;
312
490
  };
313
491
 
492
+ // Vendors had inconsistent prefixing with the experimental Indexed DB:
493
+ // - Webkit's implementation is accessible through webkitIndexedDB
494
+ // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB
495
+ // For speed, we don't test the legacy (and beta-only) indexedDB
314
496
  tests['indexedDB'] = function() {
315
497
  return !!testPropsAll("indexedDB", window);
316
498
  };
317
499
 
500
+ // documentMode logic from YUI to filter out IE8 Compat Mode
501
+ // which false positives.
318
502
  tests['hashchange'] = function() {
319
503
  return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);
320
504
  };
321
505
 
506
+ // Per 1.6:
507
+ // This used to be Modernizr.historymanagement but the longer
508
+ // name has been deprecated in favor of a shorter and property-matching one.
509
+ // The old API is still available in 1.6, but as of 2.0 will throw a warning,
510
+ // and in the first release thereafter disappear entirely.
322
511
  tests['history'] = function() {
323
512
  return !!(window.history && history.pushState);
324
513
  };
@@ -328,28 +517,52 @@ window.Modernizr = (function( window, document, undefined ) {
328
517
  return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
329
518
  };
330
519
 
520
+ // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10
521
+ // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17.
522
+ // FF10 still uses prefixes, so check for it until then.
523
+ // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/
331
524
  tests['websockets'] = function() {
332
525
  return 'WebSocket' in window || 'MozWebSocket' in window;
333
526
  };
334
527
 
335
528
 
529
+ // css-tricks.com/rgba-browser-support/
336
530
  tests['rgba'] = function() {
531
+ // Set an rgba() color and check the returned value
532
+
337
533
  setCss('background-color:rgba(150,255,150,.5)');
338
534
 
339
535
  return contains(mStyle.backgroundColor, 'rgba');
340
536
  };
341
537
 
342
538
  tests['hsla'] = function() {
343
- setCss('background-color:hsla(120,40%,100%,.5)');
539
+ // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally,
540
+ // except IE9 who retains it as hsla
541
+
542
+ setCss('background-color:hsla(120,40%,100%,.5)');
344
543
 
345
544
  return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');
346
545
  };
347
546
 
348
547
  tests['multiplebgs'] = function() {
349
- setCss('background:url(https://),url(https://),red url(https://)');
548
+ // Setting multiple images AND a color on the background shorthand property
549
+ // and then querying the style.background property value for the number of
550
+ // occurrences of "url(" is a reliable method for detecting ACTUAL support for this!
350
551
 
351
- return (/(url\s*\(.*?){3}/).test(mStyle.background);
352
- }; tests['backgroundsize'] = function() {
552
+ setCss('background:url(https://),url(https://),red url(https://)');
553
+
554
+ // If the UA supports multiple backgrounds, there should be three occurrences
555
+ // of the string "url(" in the return value for elemStyle.background
556
+
557
+ return (/(url\s*\(.*?){3}/).test(mStyle.background);
558
+ };
559
+
560
+
561
+
562
+ // this will false positive in Opera Mini
563
+ // github.com/Modernizr/Modernizr/issues/396
564
+
565
+ tests['backgroundsize'] = function() {
353
566
  return testPropsAll('backgroundSize');
354
567
  };
355
568
 
@@ -358,27 +571,41 @@ window.Modernizr = (function( window, document, undefined ) {
358
571
  };
359
572
 
360
573
 
574
+ // Super comprehensive table about all the unique implementations of
575
+ // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance
361
576
 
362
577
  tests['borderradius'] = function() {
363
578
  return testPropsAll('borderRadius');
364
579
  };
365
580
 
581
+ // WebOS unfortunately false positives on this test.
366
582
  tests['boxshadow'] = function() {
367
583
  return testPropsAll('boxShadow');
368
584
  };
369
585
 
586
+ // FF3.0 will false positive on this test
370
587
  tests['textshadow'] = function() {
371
588
  return document.createElement('div').style.textShadow === '';
372
589
  };
373
590
 
374
591
 
375
592
  tests['opacity'] = function() {
376
- setCssAll('opacity:.55');
593
+ // Browsers that actually have CSS Opacity implemented have done so
594
+ // according to spec, which means their return values are within the
595
+ // range of [0.0,1.0] - including the leading zero.
377
596
 
378
- return (/^0.55$/).test(mStyle.opacity);
597
+ setCssAll('opacity:.55');
598
+
599
+ // The non-literal . in this regex is intentional:
600
+ // German Chrome returns this value as 0,55
601
+ // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632
602
+ return (/^0.55$/).test(mStyle.opacity);
379
603
  };
380
604
 
381
605
 
606
+ // Note, Android < 4 will pass this test, but can only animate
607
+ // a single property at a time
608
+ // daneden.me/2011/12/putting-up-with-androids-bullshit/
382
609
  tests['cssanimations'] = function() {
383
610
  return testPropsAll('animationName');
384
611
  };
@@ -390,13 +617,23 @@ window.Modernizr = (function( window, document, undefined ) {
390
617
 
391
618
 
392
619
  tests['cssgradients'] = function() {
620
+ /**
621
+ * For CSS Gradients syntax, please see:
622
+ * webkit.org/blog/175/introducing-css-gradients/
623
+ * developer.mozilla.org/en/CSS/-moz-linear-gradient
624
+ * developer.mozilla.org/en/CSS/-moz-radial-gradient
625
+ * dev.w3.org/csswg/css3-images/#gradients-
626
+ */
627
+
393
628
  var str1 = 'background-image:',
394
629
  str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
395
630
  str3 = 'linear-gradient(left top,#9f9, white);';
396
631
 
397
632
  setCss(
398
- (str1 + '-webkit- '.split(' ').join(str2 + str1) +
399
- prefixes.join(str3 + str1)).slice(0, -str1.length)
633
+ // legacy webkit syntax (FIXME: remove when syntax not in use anymore)
634
+ (str1 + '-webkit- '.split(' ').join(str2 + str1) +
635
+ // standard syntax // trailing 'background-image:'
636
+ prefixes.join(str3 + str1)).slice(0, -str1.length)
400
637
  );
401
638
 
402
639
  return contains(mStyle.backgroundImage, 'gradient');
@@ -417,9 +654,15 @@ window.Modernizr = (function( window, document, undefined ) {
417
654
 
418
655
  var ret = !!testPropsAll('perspective');
419
656
 
420
- if ( ret && 'webkitPerspective' in docElement.style ) {
657
+ // Webkit's 3D transforms are passed off to the browser's own graphics renderer.
658
+ // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in
659
+ // some conditions. As a result, Webkit typically recognizes the syntax but
660
+ // will sometimes throw a false positive, thus we must do a more thorough check:
661
+ if ( ret && 'webkitPerspective' in docElement.style ) {
421
662
 
422
- injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {
663
+ // Webkit allows this media query to succeed only if the feature is enabled.
664
+ // `@media (transform-3d),(-webkit-transform-3d){ ... }`
665
+ injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {
423
666
  ret = node.offsetLeft === 9 && node.offsetHeight === 3;
424
667
  });
425
668
  }
@@ -432,7 +675,13 @@ window.Modernizr = (function( window, document, undefined ) {
432
675
  };
433
676
 
434
677
 
678
+ /*>>fontface*/
679
+ // @font-face detection routine by Diego Perini
680
+ // javascript.nwbox.com/CSSSupport/
435
681
 
682
+ // false positives:
683
+ // WebOS github.com/Modernizr/Modernizr/issues/342
684
+ // WP7 github.com/Modernizr/Modernizr/issues/538
436
685
  tests['fontface'] = function() {
437
686
  var bool;
438
687
 
@@ -446,7 +695,9 @@ window.Modernizr = (function( window, document, undefined ) {
446
695
 
447
696
  return bool;
448
697
  };
698
+ /*>>fontface*/
449
699
 
700
+ // CSS generated content detection
450
701
  tests['generatedcontent'] = function() {
451
702
  var bool;
452
703
 
@@ -456,16 +707,35 @@ window.Modernizr = (function( window, document, undefined ) {
456
707
 
457
708
  return bool;
458
709
  };
710
+
711
+
712
+
713
+ // These tests evaluate support of the video/audio elements, as well as
714
+ // testing what types of content they support.
715
+ //
716
+ // We're using the Boolean constructor here, so that we can extend the value
717
+ // e.g. Modernizr.video // true
718
+ // Modernizr.video.ogg // 'probably'
719
+ //
720
+ // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
721
+ // thx to NielsLeenheer and zcorpan
722
+
723
+ // Note: in some older browsers, "no" was a return value instead of empty string.
724
+ // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
725
+ // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
726
+
459
727
  tests['video'] = function() {
460
728
  var elem = document.createElement('video'),
461
729
  bool = false;
462
730
 
463
- try {
731
+ // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
732
+ try {
464
733
  if ( bool = !!elem.canPlayType ) {
465
734
  bool = new Boolean(bool);
466
735
  bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,'');
467
736
 
468
- bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,'');
737
+ // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546
738
+ bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,'');
469
739
 
470
740
  bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,'');
471
741
  }
@@ -485,7 +755,10 @@ window.Modernizr = (function( window, document, undefined ) {
485
755
  bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
486
756
  bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,'');
487
757
 
488
- bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,'');
758
+ // Mimetypes accepted:
759
+ // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
760
+ // bit.ly/iphoneoscodecs
761
+ bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,'');
489
762
  bool.m4a = ( elem.canPlayType('audio/x-m4a;') ||
490
763
  elem.canPlayType('audio/aac;')) .replace(/^no$/,'');
491
764
  }
@@ -495,6 +768,23 @@ window.Modernizr = (function( window, document, undefined ) {
495
768
  };
496
769
 
497
770
 
771
+ // In FF4, if disabled, window.localStorage should === null.
772
+
773
+ // Normally, we could not test that directly and need to do a
774
+ // `('localStorage' in window) && ` test first because otherwise Firefox will
775
+ // throw bugzil.la/365772 if cookies are disabled
776
+
777
+ // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem
778
+ // will throw the exception:
779
+ // QUOTA_EXCEEDED_ERRROR DOM Exception 22.
780
+ // Peculiarly, getItem and removeItem calls do not throw.
781
+
782
+ // Because we are forced to try/catch this, we'll go aggressive.
783
+
784
+ // Just FWIW: IE8 Compat mode supports these features completely:
785
+ // www.quirksmode.org/dom/html5.html
786
+ // But IE8 doesn't support either with local files
787
+
498
788
  tests['localstorage'] = function() {
499
789
  try {
500
790
  localStorage.setItem(mod, mod);
@@ -526,43 +816,79 @@ window.Modernizr = (function( window, document, undefined ) {
526
816
  };
527
817
 
528
818
 
819
+ // Thanks to Erik Dahlstrom
529
820
  tests['svg'] = function() {
530
821
  return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
531
822
  };
532
823
 
824
+ // specifically for SVG inline in HTML, not within XHTML
825
+ // test page: paulirish.com/demo/inline-svg
533
826
  tests['inlinesvg'] = function() {
534
827
  var div = document.createElement('div');
535
828
  div.innerHTML = '<svg/>';
536
829
  return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
537
830
  };
538
831
 
832
+ // SVG SMIL animation
539
833
  tests['smil'] = function() {
540
834
  return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));
541
835
  };
542
836
 
837
+ // This test is only for clip paths in SVG proper, not clip paths on HTML content
838
+ // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg
543
839
 
840
+ // However read the comments to dig into applying SVG clippaths to HTML content here:
841
+ // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491
544
842
  tests['svgclippaths'] = function() {
545
843
  return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
546
844
  };
547
845
 
846
+ /*>>webforms*/
847
+ // input features and input types go directly onto the ret object, bypassing the tests loop.
848
+ // Hold this guy to execute in a moment.
548
849
  function webforms() {
549
- Modernizr['input'] = (function( props ) {
850
+ /*>>input*/
851
+ // Run through HTML5's new input attributes to see if the UA understands any.
852
+ // We're using f which is the <input> element created early on
853
+ // Mike Taylr has created a comprehensive resource for testing these attributes
854
+ // when applied to all input types:
855
+ // miketaylr.com/code/input-type-attr.html
856
+ // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
857
+
858
+ // Only input placeholder is tested while textarea's placeholder is not.
859
+ // Currently Safari 4 and Opera 11 have support only for the input placeholder
860
+ // Both tests are available in feature-detects/forms-placeholder.js
861
+ Modernizr['input'] = (function( props ) {
550
862
  for ( var i = 0, len = props.length; i < len; i++ ) {
551
863
  attrs[ props[i] ] = !!(props[i] in inputElem);
552
864
  }
553
865
  if (attrs.list){
554
- attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);
866
+ // safari false positive's on datalist: webk.it/74252
867
+ // see also github.com/Modernizr/Modernizr/issues/146
868
+ attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);
555
869
  }
556
870
  return attrs;
557
871
  })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));
558
- Modernizr['inputtypes'] = (function(props) {
872
+ /*>>input*/
873
+
874
+ /*>>inputtypes*/
875
+ // Run through HTML5's new input types to see if the UA understands any.
876
+ // This is put behind the tests runloop because it doesn't return a
877
+ // true/false like all the other tests; instead, it returns an object
878
+ // containing each input type with its corresponding true/false value
879
+
880
+ // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/
881
+ Modernizr['inputtypes'] = (function(props) {
559
882
 
560
883
  for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
561
884
 
562
885
  inputElem.setAttribute('type', inputElemType = props[i]);
563
886
  bool = inputElem.type !== 'text';
564
887
 
565
- if ( bool ) {
888
+ // We first check to see if the type we give it sticks..
889
+ // If the type does, we feed it a textual value, which shouldn't be valid.
890
+ // If the value doesn't stick, we know there's input sanitization which infers a custom UI
891
+ if ( bool ) {
566
892
 
567
893
  inputElem.value = smile;
568
894
  inputElem.style.cssText = 'position:absolute;visibility:hidden;';
@@ -572,18 +898,29 @@ window.Modernizr = (function( window, document, undefined ) {
572
898
  docElement.appendChild(inputElem);
573
899
  defaultView = document.defaultView;
574
900
 
575
- bool = defaultView.getComputedStyle &&
901
+ // Safari 2-4 allows the smiley as a value, despite making a slider
902
+ bool = defaultView.getComputedStyle &&
576
903
  defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
577
- (inputElem.offsetHeight !== 0);
904
+ // Mobile android web browser has false positive, so must
905
+ // check the height to see if the widget is actually there.
906
+ (inputElem.offsetHeight !== 0);
578
907
 
579
908
  docElement.removeChild(inputElem);
580
909
 
581
910
  } else if ( /^(search|tel)$/.test(inputElemType) ){
582
- } else if ( /^(url|email)$/.test(inputElemType) ) {
583
- bool = inputElem.checkValidity && inputElem.checkValidity() === false;
911
+ // Spec doesn't define any special parsing or detectable UI
912
+ // behaviors so we pass these through as true
913
+
914
+ // Interestingly, opera fails the earlier test, so it doesn't
915
+ // even make it here.
916
+
917
+ } else if ( /^(url|email)$/.test(inputElemType) ) {
918
+ // Real url and email support comes with prebaked validation.
919
+ bool = inputElem.checkValidity && inputElem.checkValidity() === false;
584
920
 
585
921
  } else {
586
- bool = inputElem.value != smile;
922
+ // If the upgraded input compontent rejects the :) text, we got a winner
923
+ bool = inputElem.value != smile;
587
924
  }
588
925
  }
589
926
 
@@ -591,19 +928,44 @@ window.Modernizr = (function( window, document, undefined ) {
591
928
  }
592
929
  return inputs;
593
930
  })('search tel url email datetime date month week time datetime-local number range color'.split(' '));
594
- }
931
+ /*>>inputtypes*/
932
+ }
933
+ /*>>webforms*/
934
+
935
+
936
+ // End of test definitions
937
+ // -----------------------
938
+
939
+
940
+
941
+ // Run through all tests and detect their support in the current UA.
942
+ // todo: hypothetically we could be doing an array of tests and use a basic loop here.
595
943
  for ( var feature in tests ) {
596
944
  if ( hasOwnProp(tests, feature) ) {
597
- featureName = feature.toLowerCase();
945
+ // run the test, throw the return value into the Modernizr,
946
+ // then based on that boolean, define an appropriate className
947
+ // and push it into an array of classes we'll join later.
948
+ featureName = feature.toLowerCase();
598
949
  Modernizr[featureName] = tests[feature]();
599
950
 
600
951
  classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
601
952
  }
602
953
  }
603
954
 
955
+ /*>>webforms*/
956
+ // input tests need to run.
604
957
  Modernizr.input || webforms();
958
+ /*>>webforms*/
605
959
 
606
960
 
961
+ /**
962
+ * addTest allows the user to define their own feature tests
963
+ * the result will be added onto the Modernizr object,
964
+ * as well as an appropriate className set on the html element
965
+ *
966
+ * @param feature - String naming the feature
967
+ * @param test - Function returning true if feature is supported, false if not
968
+ */
607
969
  Modernizr.addTest = function ( feature, test ) {
608
970
  if ( typeof feature == 'object' ) {
609
971
  for ( var key in feature ) {
@@ -616,7 +978,12 @@ window.Modernizr = (function( window, document, undefined ) {
616
978
  feature = feature.toLowerCase();
617
979
 
618
980
  if ( Modernizr[feature] !== undefined ) {
619
- return Modernizr;
981
+ // we're going to quit if you're trying to overwrite an existing test
982
+ // if we were to allow it, we'd do this:
983
+ // var re = new RegExp("\\b(no-)?" + feature + "\\b");
984
+ // docElement.className = docElement.className.replace( re, '' );
985
+ // but, no rly, stuff 'em.
986
+ return Modernizr;
620
987
  }
621
988
 
622
989
  test = typeof test == 'function' ? test() : test;
@@ -628,2114 +995,399 @@ window.Modernizr = (function( window, document, undefined ) {
628
995
 
629
996
  }
630
997
 
631
- return Modernizr;
998
+ return Modernizr; // allow chaining.
632
999
  };
633
1000
 
634
1001
 
1002
+ // Reset modElem.cssText to nothing to reduce memory footprint.
635
1003
  setCss('');
636
1004
  modElem = inputElem = null;
637
1005
 
1006
+ /*>>shiv*/
1007
+ /*! HTML5 Shiv v3.6.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */
1008
+ ;(function(window, document) {
1009
+ /*jshint evil:true */
1010
+ /** Preset options */
1011
+ var options = window.html5 || {};
638
1012
 
639
- Modernizr._version = version;
1013
+ /** Used to skip problem elements */
1014
+ var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
640
1015
 
641
- Modernizr._prefixes = prefixes;
642
- Modernizr._domPrefixes = domPrefixes;
643
- Modernizr._cssomPrefixes = cssomPrefixes;
1016
+ /** Not all elements can be cloned in IE **/
1017
+ var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
644
1018
 
645
- Modernizr.mq = testMediaQuery;
1019
+ /** Detect whether the browser supports default html5 styles */
1020
+ var supportsHtml5Styles;
646
1021
 
647
- Modernizr.hasEvent = isEventSupported;
1022
+ /** Name of the expando, to work with multiple documents or to re-shiv one document */
1023
+ var expando = '_html5shiv';
648
1024
 
649
- Modernizr.testProp = function(prop){
650
- return testProps([prop]);
651
- };
1025
+ /** The id for the the documents expando */
1026
+ var expanID = 0;
652
1027
 
653
- Modernizr.testAllProps = testPropsAll;
1028
+ /** Cached data for each document */
1029
+ var expandoData = {};
654
1030
 
1031
+ /** Detect whether the browser supports unknown elements */
1032
+ var supportsUnknownElements;
655
1033
 
656
- Modernizr.testStyles = injectElementWithStyles;
657
- Modernizr.prefixed = function(prop, obj, elem){
658
- if(!obj) {
659
- return testPropsAll(prop, 'pfx');
660
- } else {
661
- return testPropsAll(prop, obj, elem);
662
- }
663
- };
664
-
665
-
666
- docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') +
1034
+ (function() {
1035
+ try {
1036
+ var a = document.createElement('a');
1037
+ a.innerHTML = '<xyz></xyz>';
1038
+ //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
1039
+ supportsHtml5Styles = ('hidden' in a);
1040
+
1041
+ supportsUnknownElements = a.childNodes.length == 1 || (function() {
1042
+ // assign a false positive if unable to shiv
1043
+ (document.createElement)('a');
1044
+ var frag = document.createDocumentFragment();
1045
+ return (
1046
+ typeof frag.cloneNode == 'undefined' ||
1047
+ typeof frag.createDocumentFragment == 'undefined' ||
1048
+ typeof frag.createElement == 'undefined'
1049
+ );
1050
+ }());
1051
+ } catch(e) {
1052
+ supportsHtml5Styles = true;
1053
+ supportsUnknownElements = true;
1054
+ }
667
1055
 
668
- (enableClasses ? ' js ' + classes.join(' ') : '');
1056
+ }());
669
1057
 
670
- return Modernizr;
1058
+ /*--------------------------------------------------------------------------*/
671
1059
 
672
- })(this, this.document);
673
- /*! HTML5 Shiv v3.6 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */
674
- ;(function(window, document) {
675
- /*jshint evil:true */
676
- /** Preset options */
677
- var options = window.html5 || {};
678
-
679
- /** Used to skip problem elements */
680
- var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
681
-
682
- /** Not all elements can be cloned in IE (this list can be shortend) **/
683
- var saveClones = /^<|^(?:a|b|button|code|div|fieldset|form|h1|h2|h3|h4|h5|h6|i|iframe|img|input|label|li|link|ol|option|p|param|q|script|select|span|strong|style|table|tbody|td|textarea|tfoot|th|thead|tr|ul)$/i;
684
-
685
- /** Detect whether the browser supports default html5 styles */
686
- var supportsHtml5Styles;
687
-
688
- /** Name of the expando, to work with multiple documents or to re-shiv one document */
689
- var expando = '_html5shiv';
690
-
691
- /** The id for the the documents expando */
692
- var expanID = 0;
693
-
694
- /** Cached data for each document */
695
- var expandoData = {};
696
-
697
- /** Detect whether the browser supports unknown elements */
698
- var supportsUnknownElements;
699
-
700
- (function() {
701
- try {
702
- var a = document.createElement('a');
703
- a.innerHTML = '<xyz></xyz>';
704
- //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
705
- supportsHtml5Styles = ('hidden' in a);
706
-
707
- supportsUnknownElements = a.childNodes.length == 1 || (function() {
708
- // assign a false positive if unable to shiv
709
- (document.createElement)('a');
710
- var frag = document.createDocumentFragment();
711
- return (
712
- typeof frag.cloneNode == 'undefined' ||
713
- typeof frag.createDocumentFragment == 'undefined' ||
714
- typeof frag.createElement == 'undefined'
715
- );
716
- }());
717
- } catch(e) {
718
- supportsHtml5Styles = true;
719
- supportsUnknownElements = true;
720
- }
1060
+ /**
1061
+ * Creates a style sheet with the given CSS text and adds it to the document.
1062
+ * @private
1063
+ * @param {Document} ownerDocument The document.
1064
+ * @param {String} cssText The CSS text.
1065
+ * @returns {StyleSheet} The style element.
1066
+ */
1067
+ function addStyleSheet(ownerDocument, cssText) {
1068
+ var p = ownerDocument.createElement('p'),
1069
+ parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
721
1070
 
722
- }());
723
-
724
- /*--------------------------------------------------------------------------*/
725
-
726
- /**
727
- * Creates a style sheet with the given CSS text and adds it to the document.
728
- * @private
729
- * @param {Document} ownerDocument The document.
730
- * @param {String} cssText The CSS text.
731
- * @returns {StyleSheet} The style element.
732
- */
733
- function addStyleSheet(ownerDocument, cssText) {
734
- var p = ownerDocument.createElement('p'),
735
- parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
736
-
737
- p.innerHTML = 'x<style>' + cssText + '</style>';
738
- return parent.insertBefore(p.lastChild, parent.firstChild);
739
- }
740
-
741
- /**
742
- * Returns the value of `html5.elements` as an array.
743
- * @private
744
- * @returns {Array} An array of shived element node names.
745
- */
746
- function getElements() {
747
- var elements = html5.elements;
748
- return typeof elements == 'string' ? elements.split(' ') : elements;
749
- }
750
-
751
- /**
752
- * Returns the data associated to the given document
753
- * @private
754
- * @param {Document} ownerDocument The document.
755
- * @returns {Object} An object of data.
756
- */
757
- function getExpandoData(ownerDocument) {
758
- var data = expandoData[ownerDocument[expando]];
759
- if (!data) {
760
- data = {};
761
- expanID++;
762
- ownerDocument[expando] = expanID;
763
- expandoData[expanID] = data;
764
- }
765
- return data;
766
- }
767
-
768
- /**
769
- * returns a shived element for the given nodeName and document
770
- * @memberOf html5
771
- * @param {String} nodeName name of the element
772
- * @param {Document} ownerDocument The context document.
773
- * @returns {Object} The shived element.
774
- */
775
- function createElement(nodeName, ownerDocument, data){
776
- if (!ownerDocument) {
777
- ownerDocument = document;
778
- }
779
- if(supportsUnknownElements){
780
- return ownerDocument.createElement(nodeName);
781
- }
782
- if (!data) {
783
- data = getExpandoData(ownerDocument);
784
- }
785
- var node;
786
-
787
- if (data.cache[nodeName]) {
788
- node = data.cache[nodeName].cloneNode();
789
- } else if (saveClones.test(nodeName)) {
790
- node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
791
- } else {
792
- node = data.createElem(nodeName);
793
- }
794
-
795
- // Avoid adding some elements to fragments in IE < 9 because
796
- // * Attributes like `name` or `type` cannot be set/changed once an element
797
- // is inserted into a document/fragment
798
- // * Link elements with `src` attributes that are inaccessible, as with
799
- // a 403 response, will cause the tab/window to crash
800
- // * Script elements appended to fragments will execute when their `src`
801
- // or `text` property is set
802
- return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
803
- }
804
-
805
- /**
806
- * returns a shived DocumentFragment for the given document
807
- * @memberOf html5
808
- * @param {Document} ownerDocument The context document.
809
- * @returns {Object} The shived DocumentFragment.
810
- */
811
- function createDocumentFragment(ownerDocument, data){
812
- if (!ownerDocument) {
813
- ownerDocument = document;
814
- }
815
- if(supportsUnknownElements){
816
- return ownerDocument.createDocumentFragment();
817
- }
818
- data = data || getExpandoData(ownerDocument);
819
- var clone = data.frag.cloneNode(),
820
- i = 0,
821
- elems = getElements(),
822
- l = elems.length;
823
- for(;i<l;i++){
824
- clone.createElement(elems[i]);
825
- }
826
- return clone;
827
- }
828
-
829
- /**
830
- * Shivs the `createElement` and `createDocumentFragment` methods of the document.
831
- * @private
832
- * @param {Document|DocumentFragment} ownerDocument The document.
833
- * @param {Object} data of the document.
834
- */
835
- function shivMethods(ownerDocument, data) {
836
- if (!data.cache) {
837
- data.cache = {};
838
- data.createElem = ownerDocument.createElement;
839
- data.createFrag = ownerDocument.createDocumentFragment;
840
- data.frag = data.createFrag();
841
- }
842
-
843
-
844
- ownerDocument.createElement = function(nodeName) {
845
- //abort shiv
846
- if (!html5.shivMethods) {
847
- return data.createElem(nodeName);
1071
+ p.innerHTML = 'x<style>' + cssText + '</style>';
1072
+ return parent.insertBefore(p.lastChild, parent.firstChild);
848
1073
  }
849
- return createElement(nodeName, ownerDocument, data);
850
- };
851
1074
 
852
- ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
853
- 'var n=f.cloneNode(),c=n.createElement;' +
854
- 'h.shivMethods&&(' +
855
- // unroll the `createElement` calls
856
- getElements().join().replace(/\w+/g, function(nodeName) {
857
- data.createElem(nodeName);
858
- data.frag.createElement(nodeName);
859
- return 'c("' + nodeName + '")';
860
- }) +
861
- ');return n}'
862
- )(html5, data.frag);
863
- }
864
-
865
- /*--------------------------------------------------------------------------*/
866
-
867
- /**
868
- * Shivs the given document.
869
- * @memberOf html5
870
- * @param {Document} ownerDocument The document to shiv.
871
- * @returns {Document} The shived document.
872
- */
873
- function shivDocument(ownerDocument) {
874
- if (!ownerDocument) {
875
- ownerDocument = document;
876
- }
877
- var data = getExpandoData(ownerDocument);
878
-
879
- if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
880
- data.hasCSS = !!addStyleSheet(ownerDocument,
881
- // corrects block display not defined in IE6/7/8/9
882
- 'article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}' +
883
- // adds styling not present in IE6/7/8/9
884
- 'mark{background:#FF0;color:#000}'
885
- );
886
- }
887
- if (!supportsUnknownElements) {
888
- shivMethods(ownerDocument, data);
889
- }
890
- return ownerDocument;
891
- }
892
-
893
- /*--------------------------------------------------------------------------*/
894
-
895
- /**
896
- * The `html5` object is exposed so that more elements can be shived and
897
- * existing shiving can be detected on iframes.
898
- * @type Object
899
- * @example
900
- *
901
- * // options can be changed before the script is included
902
- * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
903
- */
904
- var html5 = {
905
-
906
- /**
907
- * An array or space separated string of node names of the elements to shiv.
908
- * @memberOf html5
909
- * @type Array|String
910
- */
911
- 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video',
912
-
913
- /**
914
- * A flag to indicate that the HTML5 style sheet should be inserted.
915
- * @memberOf html5
916
- * @type Boolean
917
- */
918
- 'shivCSS': (options.shivCSS !== false),
919
-
920
- /**
921
- * Is equal to true if a browser supports creating unknown/HTML5 elements
922
- * @memberOf html5
923
- * @type boolean
924
- */
925
- 'supportsUnknownElements': supportsUnknownElements,
926
-
927
- /**
928
- * A flag to indicate that the document's `createElement` and `createDocumentFragment`
929
- * methods should be overwritten.
930
- * @memberOf html5
931
- * @type Boolean
932
- */
933
- 'shivMethods': (options.shivMethods !== false),
934
-
935
- /**
936
- * A string to describe the type of `html5` object ("default" or "default print").
937
- * @memberOf html5
938
- * @type String
939
- */
940
- 'type': 'default',
941
-
942
- // shivs the document according to the specified `html5` object options
943
- 'shivDocument': shivDocument,
944
-
945
- //creates a shived element
946
- createElement: createElement,
947
-
948
- //creates a shived documentFragment
949
- createDocumentFragment: createDocumentFragment
950
- };
951
-
952
- /*--------------------------------------------------------------------------*/
953
-
954
- // expose html5
955
- window.html5 = html5;
956
-
957
- // shiv the document
958
- shivDocument(document);
959
-
960
- /*------------------------------- Print Shiv -------------------------------*/
961
-
962
- /** Used to filter media types */
963
- var reMedia = /^$|\b(?:all|print)\b/;
964
-
965
- /** Used to namespace printable elements */
966
- var shivNamespace = 'html5shiv';
967
-
968
- /** Detect whether the browser supports shivable style sheets */
969
- var supportsShivableSheets = !supportsUnknownElements && (function() {
970
- // assign a false negative if unable to shiv
971
- var docEl = document.documentElement;
972
- return !(
973
- typeof document.namespaces == 'undefined' ||
974
- typeof document.parentWindow == 'undefined' ||
975
- typeof docEl.applyElement == 'undefined' ||
976
- typeof docEl.removeNode == 'undefined' ||
977
- typeof window.attachEvent == 'undefined'
978
- );
979
- }());
980
-
981
- /*--------------------------------------------------------------------------*/
982
-
983
- /**
984
- * Wraps all HTML5 elements in the given document with printable elements.
985
- * (eg. the "header" element is wrapped with the "html5shiv:header" element)
986
- * @private
987
- * @param {Document} ownerDocument The document.
988
- * @returns {Array} An array wrappers added.
989
- */
990
- function addWrappers(ownerDocument) {
991
- var node,
992
- nodes = ownerDocument.getElementsByTagName('*'),
993
- index = nodes.length,
994
- reElements = RegExp('^(?:' + getElements().join('|') + ')$', 'i'),
995
- result = [];
996
-
997
- while (index--) {
998
- node = nodes[index];
999
- if (reElements.test(node.nodeName)) {
1000
- result.push(node.applyElement(createWrapper(node)));
1075
+ /**
1076
+ * Returns the value of `html5.elements` as an array.
1077
+ * @private
1078
+ * @returns {Array} An array of shived element node names.
1079
+ */
1080
+ function getElements() {
1081
+ var elements = html5.elements;
1082
+ return typeof elements == 'string' ? elements.split(' ') : elements;
1001
1083
  }
1002
- }
1003
- return result;
1004
- }
1005
-
1006
- /**
1007
- * Creates a printable wrapper for the given element.
1008
- * @private
1009
- * @param {Element} element The element.
1010
- * @returns {Element} The wrapper.
1011
- */
1012
- function createWrapper(element) {
1013
- var node,
1014
- nodes = element.attributes,
1015
- index = nodes.length,
1016
- wrapper = element.ownerDocument.createElement(shivNamespace + ':' + element.nodeName);
1017
-
1018
- // copy element attributes to the wrapper
1019
- while (index--) {
1020
- node = nodes[index];
1021
- node.specified && wrapper.setAttribute(node.nodeName, node.nodeValue);
1022
- }
1023
- // copy element styles to the wrapper
1024
- wrapper.style.cssText = element.style.cssText;
1025
- return wrapper;
1026
- }
1027
-
1028
- /**
1029
- * Shivs the given CSS text.
1030
- * (eg. header{} becomes html5shiv\:header{})
1031
- * @private
1032
- * @param {String} cssText The CSS text to shiv.
1033
- * @returns {String} The shived CSS text.
1034
- */
1035
- function shivCssText(cssText) {
1036
- var pair,
1037
- parts = cssText.split('{'),
1038
- index = parts.length,
1039
- reElements = RegExp('(^|[\\s,>+~])(' + getElements().join('|') + ')(?=[[\\s,>+~#.:]|$)', 'gi'),
1040
- replacement = '$1' + shivNamespace + '\\:$2';
1041
-
1042
- while (index--) {
1043
- pair = parts[index] = parts[index].split('}');
1044
- pair[pair.length - 1] = pair[pair.length - 1].replace(reElements, replacement);
1045
- parts[index] = pair.join('}');
1046
- }
1047
- return parts.join('{');
1048
- }
1049
-
1050
- /**
1051
- * Removes the given wrappers, leaving the original elements.
1052
- * @private
1053
- * @params {Array} wrappers An array of printable wrappers.
1054
- */
1055
- function removeWrappers(wrappers) {
1056
- var index = wrappers.length;
1057
- while (index--) {
1058
- wrappers[index].removeNode();
1059
- }
1060
- }
1061
-
1062
- /*--------------------------------------------------------------------------*/
1063
-
1064
- /**
1065
- * Shivs the given document for print.
1066
- * @memberOf html5
1067
- * @param {Document} ownerDocument The document to shiv.
1068
- * @returns {Document} The shived document.
1069
- */
1070
- function shivPrint(ownerDocument) {
1071
- var shivedSheet,
1072
- wrappers,
1073
- data = getExpandoData(ownerDocument),
1074
- namespaces = ownerDocument.namespaces,
1075
- ownerWindow = ownerDocument.parentWindow;
1076
-
1077
- if (!supportsShivableSheets || ownerDocument.printShived) {
1078
- return ownerDocument;
1079
- }
1080
- if (typeof namespaces[shivNamespace] == 'undefined') {
1081
- namespaces.add(shivNamespace);
1082
- }
1083
1084
 
1084
- function removeSheet() {
1085
- clearTimeout(data._removeSheetTimer);
1086
- if (shivedSheet) {
1087
- shivedSheet.removeNode(true);
1085
+ /**
1086
+ * Returns the data associated to the given document
1087
+ * @private
1088
+ * @param {Document} ownerDocument The document.
1089
+ * @returns {Object} An object of data.
1090
+ */
1091
+ function getExpandoData(ownerDocument) {
1092
+ var data = expandoData[ownerDocument[expando]];
1093
+ if (!data) {
1094
+ data = {};
1095
+ expanID++;
1096
+ ownerDocument[expando] = expanID;
1097
+ expandoData[expanID] = data;
1098
+ }
1099
+ return data;
1088
1100
  }
1089
- shivedSheet= null;
1090
- }
1091
-
1092
- ownerWindow.attachEvent('onbeforeprint', function() {
1093
1101
 
1094
- removeSheet();
1102
+ /**
1103
+ * returns a shived element for the given nodeName and document
1104
+ * @memberOf html5
1105
+ * @param {String} nodeName name of the element
1106
+ * @param {Document} ownerDocument The context document.
1107
+ * @returns {Object} The shived element.
1108
+ */
1109
+ function createElement(nodeName, ownerDocument, data){
1110
+ if (!ownerDocument) {
1111
+ ownerDocument = document;
1112
+ }
1113
+ if(supportsUnknownElements){
1114
+ return ownerDocument.createElement(nodeName);
1115
+ }
1116
+ if (!data) {
1117
+ data = getExpandoData(ownerDocument);
1118
+ }
1119
+ var node;
1095
1120
 
1096
- var imports,
1097
- length,
1098
- sheet,
1099
- collection = ownerDocument.styleSheets,
1100
- cssText = [],
1101
- index = collection.length,
1102
- sheets = Array(index);
1121
+ if (data.cache[nodeName]) {
1122
+ node = data.cache[nodeName].cloneNode();
1123
+ } else if (saveClones.test(nodeName)) {
1124
+ node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
1125
+ } else {
1126
+ node = data.createElem(nodeName);
1127
+ }
1103
1128
 
1104
- // convert styleSheets collection to an array
1105
- while (index--) {
1106
- sheets[index] = collection[index];
1129
+ // Avoid adding some elements to fragments in IE < 9 because
1130
+ // * Attributes like `name` or `type` cannot be set/changed once an element
1131
+ // is inserted into a document/fragment
1132
+ // * Link elements with `src` attributes that are inaccessible, as with
1133
+ // a 403 response, will cause the tab/window to crash
1134
+ // * Script elements appended to fragments will execute when their `src`
1135
+ // or `text` property is set
1136
+ return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
1107
1137
  }
1108
- // concat all style sheet CSS text
1109
- while ((sheet = sheets.pop())) {
1110
- // IE does not enforce a same origin policy for external style sheets...
1111
- // but has trouble with some dynamically created stylesheets
1112
- if (!sheet.disabled && reMedia.test(sheet.media)) {
1113
-
1114
- try {
1115
- imports = sheet.imports;
1116
- length = imports.length;
1117
- } catch(er){
1118
- length = 0;
1119
- }
1120
-
1121
- for (index = 0; index < length; index++) {
1122
- sheets.push(imports[index]);
1123
- }
1124
1138
 
1125
- try {
1126
- cssText.push(sheet.cssText);
1127
- } catch(er){}
1139
+ /**
1140
+ * returns a shived DocumentFragment for the given document
1141
+ * @memberOf html5
1142
+ * @param {Document} ownerDocument The context document.
1143
+ * @returns {Object} The shived DocumentFragment.
1144
+ */
1145
+ function createDocumentFragment(ownerDocument, data){
1146
+ if (!ownerDocument) {
1147
+ ownerDocument = document;
1128
1148
  }
1149
+ if(supportsUnknownElements){
1150
+ return ownerDocument.createDocumentFragment();
1151
+ }
1152
+ data = data || getExpandoData(ownerDocument);
1153
+ var clone = data.frag.cloneNode(),
1154
+ i = 0,
1155
+ elems = getElements(),
1156
+ l = elems.length;
1157
+ for(;i<l;i++){
1158
+ clone.createElement(elems[i]);
1159
+ }
1160
+ return clone;
1129
1161
  }
1130
1162
 
1131
- // wrap all HTML5 elements with printable elements and add the shived style sheet
1132
- cssText = shivCssText(cssText.reverse().join(''));
1133
- wrappers = addWrappers(ownerDocument);
1134
- shivedSheet = addStyleSheet(ownerDocument, cssText);
1135
-
1136
- });
1137
-
1138
- ownerWindow.attachEvent('onafterprint', function() {
1139
- // remove wrappers, leaving the original elements, and remove the shived style sheet
1140
- removeWrappers(wrappers);
1141
- clearTimeout(data._removeSheetTimer);
1142
- data._removeSheetTimer = setTimeout(removeSheet, 500);
1143
- });
1144
-
1145
- ownerDocument.printShived = true;
1146
- return ownerDocument;
1147
- }
1148
-
1149
- /*--------------------------------------------------------------------------*/
1150
-
1151
- // expose API
1152
- html5.type += ' print';
1153
- html5.shivPrint = shivPrint;
1154
-
1155
- // shiv for print
1156
- shivPrint(document);
1157
-
1158
- }(this, document));/*yepnope1.5.4|WTFPL*/
1159
- (function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}})(this,document);
1160
- Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0));};
1161
-
1162
- // a[download] attribute
1163
- // When used on an <a>, this attribute signifies that the resource it
1164
- // points to should be downloaded by the browser rather than navigating to it.
1165
- // http://developers.whatwg.org/links.html#downloading-resources
1166
- // By Addy Osmani
1167
-
1168
- Modernizr.addTest('adownload', 'download' in document.createElement('a'));
1169
- // Mozilla Audio Data API
1170
- // https://wiki.mozilla.org/Audio_Data_API
1171
- // by Addy Osmani
1172
- Modernizr.addTest('audiodata', !!(window.Audio));
1173
- // Web Audio API
1174
- // https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html
1175
- // By Addy Osmani
1176
- Modernizr.addTest('webaudio', !!(window.webkitAudioContext || window.AudioContext));
1177
- // Blob constructor
1178
- // http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob
1179
-
1180
- Modernizr.addTest('blobconstructor', function () {
1181
- try {
1182
- return !!new Blob();
1183
- } catch (e) {
1184
- return false;
1185
- }
1186
- });
1187
-
1188
- // Low Battery Level
1189
- // Enable a developer to remove CPU intensive CSS/JS when battery is low
1190
- // developer.mozilla.org/en/DOM/window.navigator.mozBattery
1191
- // By: Paul Sayre
1192
-
1193
- Modernizr.addTest('lowbattery', function () {
1194
- var minLevel = 0.20,
1195
- battery = Modernizr.prefixed('battery', navigator);
1196
- return !!(battery && !battery.charging && battery.level <= minLevel);
1197
- });
1198
-
1199
- // Battery API
1200
- // https://developer.mozilla.org/en/DOM/window.navigator.mozBattery
1201
- // By: Paul Sayre
1202
-
1203
- Modernizr.addTest('battery',
1204
- !!Modernizr.prefixed('battery', navigator)
1205
- );// canvas.toDataURL type support
1206
- // http://www.w3.org/TR/html5/the-canvas-element.html#dom-canvas-todataurl
1207
-
1208
- // This test is asynchronous. Watch out.
1209
-
1210
- (function () {
1211
-
1212
- if (!Modernizr.canvas) {
1213
- return false;
1214
- }
1215
-
1216
- var image = new Image(),
1217
- canvas = document.createElement('canvas'),
1218
- ctx = canvas.getContext('2d');
1219
-
1220
- image.onload = function() {
1221
- ctx.drawImage(image, 0, 0);
1222
-
1223
- Modernizr.addTest('todataurljpeg', function() {
1224
- return canvas.toDataURL('image/jpeg').indexOf('data:image/jpeg') === 0;
1225
- });
1226
- Modernizr.addTest('todataurlwebp', function() {
1227
- return canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0;
1228
- });
1229
- };
1230
-
1231
- image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==';
1232
- }());
1233
- // contentEditable
1234
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#contenteditable
1235
-
1236
- // this is known to false positive in some mobile browsers
1237
- // here is a whitelist of verified working browsers:
1238
- // https://github.com/NielsLeenheer/html5test/blob/549f6eac866aa861d9649a0707ff2c0157895706/scripts/engine.js#L2083
1239
-
1240
- Modernizr.addTest('contenteditable',
1241
- 'contentEditable' in document.documentElement);
1242
- // http://www.w3.org/TR/html5/interactive-elements.html#context-menus
1243
- // Demo at http://thewebrocks.com/demos/context-menu/
1244
- Modernizr.addTest(
1245
- 'contextmenu',
1246
- ('contextMenu' in document.documentElement && 'HTMLMenuItemElement' in window)
1247
- );
1248
-
1249
-
1250
-
1251
-
1252
-
1253
- // Test for (experimental) Content Security Policy 1.1 support.
1254
- //
1255
- // This feature is still quite experimental, but is available now in Chrome 22.
1256
- // If the `SecurityPolicy` property is available, you can be sure the browser
1257
- // supports CSP. If it's not available, the browser still might support an
1258
- // earlier version of the CSP spec.
1259
- //
1260
- // Editor's Draft: https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html
1261
-
1262
- Modernizr.addTest('contentsecuritypolicy', 'SecurityPolicy' in document);
1263
-
1264
- // by tauren
1265
- // https://github.com/Modernizr/Modernizr/issues/191
1266
-
1267
- Modernizr.addTest('cookies', function () {
1268
- // Quick test if browser has cookieEnabled host property
1269
- if (navigator.cookieEnabled) return true;
1270
- // Create cookie
1271
- document.cookie = "cookietest=1";
1272
- var ret = document.cookie.indexOf("cookietest=") != -1;
1273
- // Delete cookie
1274
- document.cookie = "cookietest=1; expires=Thu, 01-Jan-1970 00:00:01 GMT";
1275
- return ret;
1276
- });
1277
-
1278
- // cors
1279
- // By Theodoor van Donge
1280
- Modernizr.addTest('cors', !!(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()));/*
1281
- https://developer.mozilla.org/en/CSS/background-position
1282
- http://www.w3.org/TR/css3-background/#background-position
1283
-
1284
- Example: http://jsfiddle.net/Blink/bBXvt/
1285
- */
1286
-
1287
- (function() {
1288
-
1289
- var elem = document.createElement('a'),
1290
- eStyle = elem.style,
1291
- val = "right 10px bottom 10px";
1292
-
1293
- Modernizr.addTest('bgpositionshorthand', function(){
1294
- eStyle.cssText = "background-position: " + val + ";";
1295
- return (eStyle.backgroundPosition === val);
1296
- });
1297
-
1298
- }());
1299
- /*
1300
- Allan Lei https://github.com/allanlei
1301
-
1302
- Check adapted from https://github.com/brandonaaron/jquery-cssHooks/blob/master/bgpos.js
1303
-
1304
- Test: http://jsfiddle.net/allanlei/R8AYS/
1305
- */
1306
- Modernizr.addTest('bgpositionxy', function() {
1307
- return Modernizr.testStyles('#modernizr {background-position: 3px 5px;}', function(elem) {
1308
- var cssStyleDeclaration = window.getComputedStyle ? getComputedStyle(elem, null) : elem.currentStyle;
1309
- var xSupport = (cssStyleDeclaration.backgroundPositionX == '3px') || (cssStyleDeclaration['background-position-x'] == '3px');
1310
- var ySupport = (cssStyleDeclaration.backgroundPositionY == '5px') || (cssStyleDeclaration['background-position-y'] == '5px');
1311
- return xSupport && ySupport;
1312
- });
1313
- });
1314
- // developer.mozilla.org/en/CSS/background-size
1315
-
1316
- Modernizr.testStyles( '#modernizr{background-size:cover}', function( elem ) {
1317
- var style = window.getComputedStyle ?
1318
- window.getComputedStyle( elem, null )
1319
- : elem.currentStyle;
1320
-
1321
- Modernizr.addTest( 'bgsizecover', style.backgroundSize == 'cover' );
1322
- });// developer.mozilla.org/en/CSS/background-repeat
1323
-
1324
- // test page: jsbin.com/uzesun/
1325
- // http://jsfiddle.net/ryanseddon/yMLTQ/6/
1326
-
1327
- (function(){
1328
-
1329
-
1330
- function getBgRepeatValue(elem){
1331
- return (window.getComputedStyle ?
1332
- getComputedStyle(elem, null).getPropertyValue('background') :
1333
- elem.currentStyle['background']);
1334
- }
1335
-
1336
-
1337
- Modernizr.testStyles(' #modernizr { background-repeat: round; } ', function(elem, rule){
1338
-
1339
- Modernizr.addTest('bgrepeatround', getBgRepeatValue(elem) == 'round');
1340
-
1341
- });
1342
-
1343
-
1344
-
1345
- Modernizr.testStyles(' #modernizr { background-repeat: space; } ', function(elem, rule){
1346
-
1347
- Modernizr.addTest('bgrepeatspace', getBgRepeatValue(elem) == 'space');
1348
-
1349
- });
1350
-
1351
-
1352
- })();
1353
-
1354
- // developer.mozilla.org/en/CSS/box-sizing
1355
- // github.com/Modernizr/Modernizr/issues/248
1356
-
1357
- Modernizr.addTest("boxsizing",function(){
1358
- return Modernizr.testAllProps("boxSizing") && (document.documentMode === undefined || document.documentMode > 7);
1359
- });
1360
-
1361
-
1362
- // Method of allowing calculated values for length units, i.e. width: calc(100%-3em) http://caniuse.com/#search=calc
1363
- // By @calvein
1364
-
1365
- Modernizr.addTest('csscalc', function() {
1366
- var prop = 'width:';
1367
- var value = 'calc(10px);';
1368
- var el = document.createElement('div');
1369
-
1370
- el.style.cssText = prop + Modernizr._prefixes.join(value + prop);
1371
-
1372
- return !!el.style.length;
1373
- });
1374
- // cubic-bezier values can't be > 1 for Webkit until bug #45761 (https://bugs.webkit.org/show_bug.cgi?id=45761) is fixed
1375
- // By @calvein
1376
-
1377
- Modernizr.addTest('cubicbezierrange', function() {
1378
- var el = document.createElement('div');
1379
- el.style.cssText = Modernizr._prefixes.join('transition-timing-function' + ':cubic-bezier(1,0,0,1.1); ');
1380
- return !!el.style.length;
1381
- });
1382
-
1383
- // by alanhogan
1384
-
1385
- // https://github.com/Modernizr/Modernizr/issues/198
1386
- // http://css-tricks.com/596-run-in/
1387
-
1388
-
1389
-
1390
- Modernizr.testStyles(' #modernizr { display: run-in; } ', function(elem, rule){
1391
-
1392
- var ret = (window.getComputedStyle ?
1393
- getComputedStyle(elem, null).getPropertyValue('display') :
1394
- elem.currentStyle['display']);
1395
-
1396
- Modernizr.addTest('display-runin', ret == 'run-in');
1397
-
1398
- });
1399
-
1400
- // https://github.com/Modernizr/Modernizr/issues/615
1401
- // documentMode is needed for false positives in oldIE, please see issue above
1402
- Modernizr.addTest('cssfilters', function() {
1403
- var el = document.createElement('div');
1404
- el.style.cssText = Modernizr._prefixes.join('filter' + ':blur(2px); ');
1405
- return !!el.style.length && ((document.documentMode === undefined || document.documentMode > 9));
1406
- });// display: table and table-cell test. (both are tested under one name "table-cell" )
1407
- // By @scottjehl
1408
-
1409
- // all additional table display values are here: http://pastebin.com/Gk9PeVaQ though Scott has seen some IE false positives with that sort of weak detection.
1410
- // more testing neccessary perhaps.
1411
-
1412
- Modernizr.addTest( "display-table",function(){
1413
-
1414
- var doc = window.document,
1415
- docElem = doc.documentElement,
1416
- parent = doc.createElement( "div" ),
1417
- child = doc.createElement( "div" ),
1418
- childb = doc.createElement( "div" ),
1419
- ret;
1420
-
1421
- parent.style.cssText = "display: table";
1422
- child.style.cssText = childb.style.cssText = "display: table-cell; padding: 10px";
1423
-
1424
- parent.appendChild( child );
1425
- parent.appendChild( childb );
1426
- docElem.insertBefore( parent, docElem.firstChild );
1427
-
1428
- ret = child.offsetLeft < childb.offsetLeft;
1429
- docElem.removeChild(parent);
1430
- return ret;
1431
- });
1432
-
1433
- // last-child pseudo selector
1434
- // https://github.com/Modernizr/Modernizr/pull/304
1435
-
1436
-
1437
- Modernizr.addTest('lastchild', function(){
1438
-
1439
- return Modernizr.testStyles("#modernizr div {width:100px} #modernizr :last-child{width:200px;display:block}", function (elem) {
1440
- return elem.lastChild.offsetWidth > elem.firstChild.offsetWidth;
1441
- }, 2);
1442
-
1443
- });
1444
- /* see http://davidnewton.ca/the-current-state-of-hyphenation-on-the-web
1445
- http://davidnewton.ca/demos/hyphenation/test.html
1446
-
1447
-
1448
- There are three tests:
1449
- 1. csshyphens - tests hyphens:auto actually adds hyphens to text
1450
- 2. softhyphens - tests that &shy; does its job
1451
- 3. softhyphensfind - tests that in-browser Find functionality still works correctly with &shy;
1452
-
1453
- These tests currently require document.body to be present
1454
-
1455
- Hyphenation is language specific, sometimes.
1456
- See for more details: http://code.google.com/p/hyphenator/source/diff?spec=svn975&r=975&format=side&path=/trunk/Hyphenator.js#sc_svn975_313
1457
-
1458
- If loading Hyphenator.js via Modernizr.load, be cautious of issue 158: http://code.google.com/p/hyphenator/issues/detail?id=158
1459
-
1460
- More details at https://github.com/Modernizr/Modernizr/issues/312
1461
-
1462
- */
1463
-
1464
- (function() {
1465
-
1466
- if (!document.body){
1467
- window.console && console.warn('document.body doesn\'t exist. Modernizr hyphens test needs it.');
1468
- return;
1469
- }
1470
-
1471
- // functional test of adding hyphens:auto
1472
- function test_hyphens_css() {
1473
- try {
1474
- /* create a div container and a span within that
1475
- * these have to be appended to document.body, otherwise some browsers can give false negative */
1476
- var div = document.createElement('div'),
1477
- span = document.createElement('span'),
1478
- divStyle = div.style,
1479
- spanHeight = 0,
1480
- spanWidth = 0,
1481
- result = false,
1482
- firstChild = document.body.firstElementChild || document.body.firstChild;
1483
-
1484
- div.appendChild(span);
1485
- span.innerHTML = 'Bacon ipsum dolor sit amet jerky velit in culpa hamburger et. Laborum dolor proident, enim dolore duis commodo et strip steak. Salami anim et, veniam consectetur dolore qui tenderloin jowl velit sirloin. Et ad culpa, fatback cillum jowl ball tip ham hock nulla short ribs pariatur aute. Pig pancetta ham bresaola, ut boudin nostrud commodo flank esse cow tongue culpa. Pork belly bresaola enim pig, ea consectetur nisi. Fugiat officia turkey, ea cow jowl pariatur ullamco proident do laborum velit sausage. Magna biltong sint tri-tip commodo sed bacon, esse proident aliquip. Ullamco ham sint fugiat, velit in enim sed mollit nulla cow ut adipisicing nostrud consectetur. Proident dolore beef ribs, laborum nostrud meatball ea laboris rump cupidatat labore culpa. Shankle minim beef, velit sint cupidatat fugiat tenderloin pig et ball tip. Ut cow fatback salami, bacon ball tip et in shank strip steak bresaola. In ut pork belly sed mollit tri-tip magna culpa veniam, short ribs qui in andouille ham consequat. Dolore bacon t-bone, velit short ribs enim strip steak nulla. Voluptate labore ut, biltong swine irure jerky. Cupidatat excepteur aliquip salami dolore. Ball tip strip steak in pork dolor. Ad in esse biltong. Dolore tenderloin exercitation ad pork loin t-bone, dolore in chicken ball tip qui pig. Ut culpa tongue, sint ribeye dolore ex shank voluptate hamburger. Jowl et tempor, boudin pork chop labore ham hock drumstick consectetur tri-tip elit swine meatball chicken ground round. Proident shankle mollit dolore. Shoulder ut duis t-bone quis reprehenderit. Meatloaf dolore minim strip steak, laboris ea aute bacon beef ribs elit shank in veniam drumstick qui. Ex laboris meatball cow tongue pork belly. Ea ball tip reprehenderit pig, sed fatback boudin dolore flank aliquip laboris eu quis. Beef ribs duis beef, cow corned beef adipisicing commodo nisi deserunt exercitation. Cillum dolor t-bone spare ribs, ham hock est sirloin. Brisket irure meatloaf in, boudin pork belly sirloin ball tip. Sirloin sint irure nisi nostrud aliqua. Nostrud nulla aute, enim officia culpa ham hock. Aliqua reprehenderit dolore sunt nostrud sausage, ea boudin pork loin ut t-bone ham tempor. Tri-tip et pancetta drumstick laborum. Ham hock magna do nostrud in proident. Ex ground round fatback, venison non ribeye in.';
1486
-
1487
- document.body.insertBefore(div, firstChild);
1488
-
1489
- /* get size of unhyphenated text */
1490
- divStyle.cssText = 'position:absolute;top:0;left:0;width:5em;text-align:justify;text-justification:newspaper;';
1491
- spanHeight = span.offsetHeight;
1492
- spanWidth = span.offsetWidth;
1493
-
1494
- /* compare size with hyphenated text */
1495
- divStyle.cssText = 'position:absolute;top:0;left:0;width:5em;text-align:justify;'+
1496
- 'text-justification:newspaper;'+
1497
- Modernizr._prefixes.join('hyphens:auto; ');
1498
-
1499
- result = (span.offsetHeight != spanHeight || span.offsetWidth != spanWidth);
1500
-
1501
- /* results and cleanup */
1502
- document.body.removeChild(div);
1503
- div.removeChild(span);
1504
-
1505
- return result;
1506
- } catch(e) {
1507
- return false;
1508
- }
1509
- }
1510
-
1511
- // for the softhyphens test
1512
- function test_hyphens(delimiter, testWidth) {
1513
- try {
1514
- /* create a div container and a span within that
1515
- * these have to be appended to document.body, otherwise some browsers can give false negative */
1516
- var div = document.createElement('div'),
1517
- span = document.createElement('span'),
1518
- divStyle = div.style,
1519
- spanSize = 0,
1520
- result = false,
1521
- result1 = false,
1522
- result2 = false,
1523
- firstChild = document.body.firstElementChild || document.body.firstChild;
1524
-
1525
- divStyle.cssText = 'position:absolute;top:0;left:0;overflow:visible;width:1.25em;';
1526
- div.appendChild(span);
1527
- document.body.insertBefore(div, firstChild);
1528
-
1529
-
1530
- /* get height of unwrapped text */
1531
- span.innerHTML = 'mm';
1532
- spanSize = span.offsetHeight;
1533
-
1534
- /* compare height w/ delimiter, to see if it wraps to new line */
1535
- span.innerHTML = 'm' + delimiter + 'm';
1536
- result1 = (span.offsetHeight > spanSize);
1537
-
1538
- /* if we're testing the width too (i.e. for soft-hyphen, not zws),
1539
- * this is because tested Blackberry devices will wrap the text but not display the hyphen */
1540
- if (testWidth) {
1541
- /* get width of wrapped, non-hyphenated text */
1542
- span.innerHTML = 'm<br />m';
1543
- spanSize = span.offsetWidth;
1544
-
1545
- /* compare width w/ wrapped w/ delimiter to see if hyphen is present */
1546
- span.innerHTML = 'm' + delimiter + 'm';
1547
- result2 = (span.offsetWidth > spanSize);
1548
- } else {
1549
- result2 = true;
1550
- }
1551
-
1552
- /* results and cleanup */
1553
- if (result1 === true && result2 === true) { result = true; }
1554
- document.body.removeChild(div);
1555
- div.removeChild(span);
1556
-
1557
- return result;
1558
- } catch(e) {
1559
- return false;
1560
- }
1561
- }
1562
-
1563
- // testing if in-browser Find functionality will work on hyphenated text
1564
- function test_hyphens_find(delimiter) {
1565
- try {
1566
- /* create a dummy input for resetting selection location, and a div container
1567
- * these have to be appended to document.body, otherwise some browsers can give false negative
1568
- * div container gets the doubled testword, separated by the delimiter
1569
- * Note: giving a width to div gives false positive in iOS Safari */
1570
- var dummy = document.createElement('input'),
1571
- div = document.createElement('div'),
1572
- testword = 'lebowski',
1573
- result = false,
1574
- textrange,
1575
- firstChild = document.body.firstElementChild || document.body.firstChild;
1576
-
1577
- div.innerHTML = testword + delimiter + testword;
1578
-
1579
- document.body.insertBefore(div, firstChild);
1580
- document.body.insertBefore(dummy, div);
1581
-
1582
-
1583
- /* reset the selection to the dummy input element, i.e. BEFORE the div container
1584
- * stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area */
1585
- if (dummy.setSelectionRange) {
1586
- dummy.focus();
1587
- dummy.setSelectionRange(0,0);
1588
- } else if (dummy.createTextRange) {
1589
- textrange = dummy.createTextRange();
1590
- textrange.collapse(true);
1591
- textrange.moveEnd('character', 0);
1592
- textrange.moveStart('character', 0);
1593
- textrange.select();
1594
- }
1595
-
1596
- /* try to find the doubled testword, without the delimiter */
1597
- if (window.find) {
1598
- result = window.find(testword + testword);
1599
- } else {
1600
- try {
1601
- textrange = window.self.document.body.createTextRange();
1602
- result = textrange.findText(testword + testword);
1603
- } catch(e) {
1604
- result = false;
1605
- }
1606
- }
1607
-
1608
- document.body.removeChild(div);
1609
- document.body.removeChild(dummy);
1610
-
1611
- return result;
1612
- } catch(e) {
1613
- return false;
1614
- }
1615
- }
1616
-
1617
- Modernizr.addTest("csshyphens", function() {
1618
-
1619
- if (!Modernizr.testAllProps('hyphens')) return false;
1620
-
1621
- /* Chrome lies about its hyphens support so we need a more robust test
1622
- crbug.com/107111
1623
- */
1624
- try {
1625
- return test_hyphens_css();
1626
- } catch(e) {
1627
- return false;
1628
- }
1629
- });
1630
-
1631
- Modernizr.addTest("softhyphens", function() {
1632
- try {
1633
- // use numeric entity instead of &shy; in case it's XHTML
1634
- return test_hyphens('&#173;', true) && test_hyphens('&#8203;', false);
1635
- } catch(e) {
1636
- return false;
1637
- }
1638
- });
1639
-
1640
- Modernizr.addTest("softhyphensfind", function() {
1641
- try {
1642
- return test_hyphens_find('&#173;') && test_hyphens_find('&#8203;');
1643
- } catch(e) {
1644
- return false;
1645
- }
1646
- });
1647
-
1648
- })();
1649
-
1650
- // this tests passes for webkit's proprietary `-webkit-mask` feature
1651
- // www.webkit.org/blog/181/css-masks/
1652
- // developer.apple.com/library/safari/#documentation/InternetWeb/Conceptual/SafariVisualEffectsProgGuide/Masks/Masks.html
1653
-
1654
- // it does not pass mozilla's implementation of `mask` for SVG
1655
-
1656
- // developer.mozilla.org/en/CSS/mask
1657
- // developer.mozilla.org/En/Applying_SVG_effects_to_HTML_content
1658
-
1659
- // Can combine with clippaths for awesomeness: http://generic.cx/for/webkit/test.html
1660
-
1661
- Modernizr.addTest('cssmask', Modernizr.testAllProps('mask-repeat'));
1662
-
1663
-
1664
- Modernizr.addTest('mediaqueries', Modernizr.mq('only all'));
1665
- // dev.opera.com/articles/view/css3-object-fit-object-position/
1666
-
1667
- Modernizr.addTest('object-fit',
1668
- !!Modernizr.prefixed('objectFit')
1669
- );
1670
- // johanbrook.com/browsers/native-momentum-scrolling-ios-5/
1671
- // introduced in iOS5b2. Possible API may change...
1672
-
1673
- Modernizr.addTest("overflowscrolling",function(){
1674
- return Modernizr.testAllProps("overflowScrolling");
1675
- });
1676
-
1677
-
1678
-
1679
- // developer.mozilla.org/en/CSS/pointer-events
1680
-
1681
- // Test and project pages:
1682
- // ausi.github.com/Feature-detection-technique-for-pointer-events/
1683
- // github.com/ausi/Feature-detection-technique-for-pointer-events/wiki
1684
- // github.com/Modernizr/Modernizr/issues/80
1685
-
1686
-
1687
- Modernizr.addTest('pointerevents', function(){
1688
- var element = document.createElement('x'),
1689
- documentElement = document.documentElement,
1690
- getComputedStyle = window.getComputedStyle,
1691
- supports;
1692
- if(!('pointerEvents' in element.style)){
1693
- return false;
1694
- }
1695
- element.style.pointerEvents = 'auto';
1696
- element.style.pointerEvents = 'x';
1697
- documentElement.appendChild(element);
1698
- supports = getComputedStyle &&
1699
- getComputedStyle(element, '').pointerEvents === 'auto';
1700
- documentElement.removeChild(element);
1701
- return !!supports;
1702
- });
1703
- // Sticky positioning - constrains an element to be positioned inside the
1704
- // intersection of its container box, and the viewport.
1705
- Modernizr.addTest('csspositionsticky', function () {
1706
-
1707
- var prop = 'position:';
1708
- var value = 'sticky';
1709
- var el = document.createElement('modernizr');
1710
- var mStyle = el.style;
1711
-
1712
- mStyle.cssText = prop + Modernizr._prefixes.join(value + ';' + prop).slice(0, -prop.length);
1713
-
1714
- return mStyle.position.indexOf(value) !== -1;
1715
- });
1716
-
1717
- // test by github.com/nsfmc
1718
-
1719
- // "The 'rem' unit ('root em') is relative to the computed
1720
- // value of the 'font-size' value of the root element."
1721
- // http://www.w3.org/TR/css3-values/#relative0
1722
- // you can test by checking if the prop was ditched
1723
-
1724
- // http://snook.ca/archives/html_and_css/font-size-with-rem
1725
-
1726
- Modernizr.addTest('cssremunit', function(){
1727
-
1728
- var div = document.createElement('div');
1729
- try {
1730
- div.style.fontSize = '3rem';
1731
- } catch(er){}
1732
- return (/rem/).test(div.style.fontSize);
1733
-
1734
- });
1735
- // CSS Regions
1736
- // http://www.w3.org/TR/css3-regions/
1737
- // By: Mihai Balan
1738
-
1739
- // We start with a CSS parser test then we check page geometry to see if it's affected by regions
1740
- // Later we might be able to retire the second part, as WebKit builds with the false positives die out
1741
-
1742
- Modernizr.addTest('regions', function() {
1743
-
1744
- /* Get the 'flowFrom' property name available in the browser. Either default or vendor prefixed.
1745
- If the property name can't be found we'll get Boolean 'false' and fail quickly */
1746
- var flowFromProperty = Modernizr.prefixed("flowFrom"),
1747
- flowIntoProperty = Modernizr.prefixed("flowInto");
1748
-
1749
- if (!flowFromProperty || !flowIntoProperty){
1750
- return false;
1751
- }
1752
-
1753
- /* If CSS parsing is there, try to determine if regions actually work. */
1754
- var container = document.createElement('div'),
1755
- content = document.createElement('div'),
1756
- region = document.createElement('div'),
1757
-
1758
- /* we create a random, unlikely to be generated flow number to make sure we don't
1759
- clash with anything more vanilla, like 'flow', or 'article', or 'f1' */
1760
- flowName = 'modernizr_flow_for_regions_check';
1761
-
1762
- /* First create a div with two adjacent divs inside it. The first will be the
1763
- content, the second will be the region. To be able to distinguish between the two,
1764
- we'll give the region a particular padding */
1765
- content.innerText = 'M';
1766
- container.style.cssText = 'top: 150px; left: 150px; padding: 0px;';
1767
- region.style.cssText = 'width: 50px; height: 50px; padding: 42px;';
1768
-
1769
- region.style[flowFromProperty] = flowName;
1770
- container.appendChild(content);
1771
- container.appendChild(region);
1772
- document.documentElement.appendChild(container);
1773
-
1774
- /* Now compute the bounding client rect, before and after attempting to flow the
1775
- content div in the region div. If regions are enabled, the after bounding rect
1776
- should reflect the padding of the region div.*/
1777
- var flowedRect, delta,
1778
- plainRect = content.getBoundingClientRect();
1779
-
1780
-
1781
- content.style[flowIntoProperty] = flowName;
1782
- flowedRect = content.getBoundingClientRect();
1783
-
1784
- delta = flowedRect.left - plainRect.left;
1785
- document.documentElement.removeChild(container);
1786
- content = region = container = undefined;
1787
-
1788
- return (delta == 42);
1789
- });
1790
-
1791
- // Test for CSS 3 UI "resize" property
1792
- // http://www.w3.org/TR/css3-ui/#resize
1793
- // https://developer.mozilla.org/en/CSS/resize
1794
-
1795
- Modernizr.addTest('cssresize', Modernizr.testAllProps('resize'));
1796
-
1797
-
1798
- // Stylable scrollbars detection
1799
- Modernizr.addTest('cssscrollbar', function() {
1800
-
1801
- var bool,
1802
-
1803
- styles = "#modernizr{overflow: scroll; width: 40px }#" +
1804
- Modernizr._prefixes
1805
- .join("scrollbar{width:0px}"+' #modernizr::')
1806
- .split('#')
1807
- .slice(1)
1808
- .join('#') + "scrollbar{width:0px}";
1809
-
1810
- Modernizr.testStyles(styles, function(node) {
1811
- bool = 'scrollWidth' in node && node.scrollWidth == 40;
1812
- });
1813
-
1814
- return bool;
1815
-
1816
- });
1817
- /*
1818
- * Test for SubPixel Font Rendering
1819
- * (to infer if GDI or DirectWrite is used on Windows)
1820
- * Authors: @derSchepp, @gerritvanaaken, @rodneyrehm, @yatil, @ryanseddon
1821
- * Web: https://github.com/gerritvanaaken/subpixeldetect
1822
- */
1823
- Modernizr.addTest('subpixelfont', function() {
1824
- var bool,
1825
- styles = "#modernizr{position: absolute; top: -10em; visibility:hidden; font: normal 10px arial;}#subpixel{float: left; font-size: 33.3333%;}";
1826
-
1827
- // see https://github.com/Modernizr/Modernizr/blob/master/modernizr.js#L97
1828
- Modernizr.testStyles(styles, function(elem) {
1829
- var subpixel = elem.firstChild;
1830
-
1831
- subpixel.innerHTML = 'This is a text written in Arial';
1832
-
1833
- bool = window.getComputedStyle ?
1834
- window.getComputedStyle(subpixel, null).getPropertyValue("width") !== '44px'
1835
- : false;
1836
- }, 1, ['subpixel']);
1837
-
1838
- return bool;
1839
- });
1840
- // http://dev.w3.org/csswg/css3-conditional/#at-supports
1841
- // github.com/Modernizr/Modernizr/issues/648
1842
- // Relies on the fact that a browser vendor should expose the CSSSupportsRule interface
1843
- // http://dev.w3.org/csswg/css3-conditional/#the-csssupportsrule-interface
1844
-
1845
- Modernizr.addTest("supports","CSSSupportsRule" in window);// -moz-user-select:none test.
1846
-
1847
- // by ryan seddon
1848
- //https://github.com/Modernizr/Modernizr/issues/250
1849
-
1850
-
1851
- Modernizr.addTest("userselect",function(){
1852
- return Modernizr.testAllProps("user-select");
1853
- });
1854
-
1855
- // https://github.com/Modernizr/Modernizr/issues/572
1856
- // Similar to http://jsfiddle.net/FWeinb/etnYC/
1857
- Modernizr.addTest('cssvhunit', function() {
1858
- var bool;
1859
- Modernizr.testStyles("#modernizr { height: 50vh; }", function(elem, rule) {
1860
- var height = parseInt(window.innerHeight/2,10),
1861
- compStyle = parseInt((window.getComputedStyle ?
1862
- getComputedStyle(elem, null) :
1863
- elem.currentStyle)["height"],10);
1864
-
1865
- bool= (compStyle == height);
1866
- });
1867
- return bool;
1868
- });// https://github.com/Modernizr/Modernizr/issues/572
1869
- // http://jsfiddle.net/glsee/JDsWQ/4/
1870
- Modernizr.addTest('cssvmaxunit', function(){
1871
- var bool;
1872
- Modernizr.testStyles("#modernizr { width: 50vmax; }", function(elem, rule) {
1873
- var one_vw = window.innerWidth/100,
1874
- one_vh = window.innerHeight/100,
1875
- compWidth = parseInt((window.getComputedStyle ?
1876
- getComputedStyle(elem, null) :
1877
- elem.currentStyle)['width'],10);
1878
- bool = ( parseInt(Math.max(one_vw, one_vh)*50,10) == compWidth );
1879
- });
1880
- return bool;
1881
- });// https://github.com/Modernizr/Modernizr/issues/572
1882
- // http://jsfiddle.net/glsee/JRmdq/8/
1883
- Modernizr.addTest('cssvminunit', function(){
1884
- var bool;
1885
- Modernizr.testStyles("#modernizr { width: 50vmin; }", function(elem, rule) {
1886
- var one_vw = window.innerWidth/100,
1887
- one_vh = window.innerHeight/100,
1888
- compWidth = parseInt((window.getComputedStyle ?
1889
- getComputedStyle(elem, null) :
1890
- elem.currentStyle)['width'],10);
1891
- bool = ( parseInt(Math.min(one_vw, one_vh)*50,10) == compWidth );
1892
- });
1893
- return bool;
1894
- });
1895
- /*
1896
- Custom protocol handler support
1897
- http://developers.whatwg.org/timers.html#custom-handlers
1898
-
1899
- Added by @benschwarz
1900
- */
1901
-
1902
- Modernizr.addTest('customprotocolhandler', function () {
1903
- return !!navigator.registerProtocolHandler;
1904
- });
1905
- // https://github.com/Modernizr/Modernizr/issues/572
1906
- // http://jsfiddle.net/FWeinb/etnYC/
1907
- Modernizr.addTest('cssvwunit', function(){
1908
- var bool;
1909
- Modernizr.testStyles("#modernizr { width: 50vw; }", function(elem, rule) {
1910
- var width = parseInt(window.innerWidth/2,10),
1911
- compStyle = parseInt((window.getComputedStyle ?
1912
- getComputedStyle(elem, null) :
1913
- elem.currentStyle)["width"],10);
1914
-
1915
- bool= (compStyle == width);
1916
- });
1917
- return bool;
1918
- });
1919
- // DataView
1920
- // https://developer.mozilla.org/en/JavaScript_typed_arrays/DataView
1921
- // By Addy Osmani
1922
- Modernizr.addTest('dataview', (typeof DataView !== 'undefined' && 'getFloat64' in DataView.prototype));// classList
1923
- // https://developer.mozilla.org/en/DOM/element.classList
1924
- // By Addy Osmani
1925
- Modernizr.addTest('classlist', 'classList' in document.documentElement);
1926
-
1927
- // dataset API for data-* attributes
1928
- // test by @phiggins42
1929
-
1930
- Modernizr.addTest('dataset', function(){
1931
- var n = document.createElement("div");
1932
- n.setAttribute("data-a-b", "c");
1933
- return !!(n.dataset && n.dataset.aB === "c");
1934
- });
1935
- // by james a rosen.
1936
- // https://github.com/Modernizr/Modernizr/issues/258
1937
-
1938
- Modernizr.addTest('createelement-attrs', function() {
1939
- try {
1940
- return document.createElement("<input name='test' />").getAttribute('name') == 'test';
1941
- } catch(e) {
1942
- return false;
1943
- }
1944
- });
1945
-
1946
-
1947
-
1948
- // lol. we already have a test for datalist built in! silly you.
1949
-
1950
-
1951
- // Helpful links while you're here, though..
1952
-
1953
- // http://css-tricks.com/15346-relevant-dropdowns-polyfill-for-datalist/
1954
- // http://miketaylr.com/test/datalist.html
1955
- // http://miketaylr.com/code/datalist.html
1956
-
1957
- Modernizr.addTest('datalistelem', Modernizr.input.list );
1958
- // Microdata support
1959
- // http://www.w3.org/TR/html5/microdata.html
1960
- // By Addy Osmani
1961
- Modernizr.addTest('microdata', !!(document['getItems']));// By @mathias, based on http://mths.be/axh
1962
- Modernizr.addTest('details', function() {
1963
- var doc = document,
1964
- el = doc.createElement('details'),
1965
- fake,
1966
- root,
1967
- diff;
1968
- if (!('open' in el)) { // return early if possible; thanks @aFarkas!
1969
- return false;
1970
- }
1971
- root = doc.body || (function() {
1972
- var de = doc.documentElement;
1973
- fake = true;
1974
- return de.insertBefore(doc.createElement('body'), de.firstElementChild || de.firstChild);
1975
- }());
1976
- el.innerHTML = '<summary>a</summary>b';
1977
- el.style.display = 'block';
1978
- root.appendChild(el);
1979
- diff = el.offsetHeight;
1980
- el.open = true;
1981
- diff = diff != el.offsetHeight;
1982
- root.removeChild(el);
1983
- fake && root.parentNode.removeChild(root);
1984
- return diff;
1985
- });// Browser support test for the HTML5 <ruby>, <rt> and <rp> elements
1986
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-ruby-element
1987
- //
1988
- // by @alrra
1989
-
1990
- Modernizr.addTest('ruby', function () {
1991
-
1992
- var ruby = document.createElement('ruby'),
1993
- rt = document.createElement('rt'),
1994
- rp = document.createElement('rp'),
1995
- docElement = document.documentElement,
1996
- displayStyleProperty = 'display',
1997
- fontSizeStyleProperty = 'fontSize'; // 'fontSize' - because it`s only used for IE6 and IE7
1998
-
1999
- ruby.appendChild(rp);
2000
- ruby.appendChild(rt);
2001
- docElement.appendChild(ruby);
2002
-
2003
- // browsers that support <ruby> hide the <rp> via "display:none"
2004
- if ( getStyle(rp, displayStyleProperty) == 'none' || // for non-IE browsers
2005
- // but in IE browsers <rp> has "display:inline" so, the test needs other conditions:
2006
- getStyle(ruby, displayStyleProperty) == 'ruby' && getStyle(rt, displayStyleProperty) == 'ruby-text' || // for IE8 & IE9
2007
- getStyle(rp, fontSizeStyleProperty) == '6pt' && getStyle(rt, fontSizeStyleProperty) == '6pt' ) { // for IE6 & IE7
2008
-
2009
- cleanUp();
2010
- return true;
2011
-
2012
- } else {
2013
- cleanUp();
2014
- return false;
2015
- }
2016
-
2017
- function getStyle( element, styleProperty ) {
2018
- var result;
2019
-
2020
- if ( window.getComputedStyle ) { // for non-IE browsers
2021
- result = document.defaultView.getComputedStyle(element,null).getPropertyValue(styleProperty);
2022
- } else if ( element.currentStyle ) { // for IE
2023
- result = element.currentStyle[styleProperty];
1163
+ /**
1164
+ * Shivs the `createElement` and `createDocumentFragment` methods of the document.
1165
+ * @private
1166
+ * @param {Document|DocumentFragment} ownerDocument The document.
1167
+ * @param {Object} data of the document.
1168
+ */
1169
+ function shivMethods(ownerDocument, data) {
1170
+ if (!data.cache) {
1171
+ data.cache = {};
1172
+ data.createElem = ownerDocument.createElement;
1173
+ data.createFrag = ownerDocument.createDocumentFragment;
1174
+ data.frag = data.createFrag();
2024
1175
  }
2025
1176
 
2026
- return result;
2027
- }
2028
-
2029
- function cleanUp() {
2030
- docElement.removeChild(ruby);
2031
- // the removed child node still exists in memory, so ...
2032
- ruby = null;
2033
- rt = null;
2034
- rp = null;
2035
- }
2036
-
2037
- });
2038
- //By Stefan Wallin
2039
-
2040
- //tests for progressbar-support. All browsers that don't support progressbar returns undefined =)
2041
- Modernizr.addTest("progressbar",function(){
2042
- return document.createElement('progress').max !== undefined;
2043
- });
2044
-
2045
- //tests for meter-support. All browsers that don't support meters returns undefined =)
2046
- Modernizr.addTest("meter",function(){
2047
- return document.createElement('meter').max !== undefined;
2048
- });
2049
- // <time> element
2050
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#the-time-element-0
2051
- // by Addy Osmani
2052
- Modernizr.addTest('time', 'valueAsDate' in document.createElement('time'));
2053
- // Track element + Timed Text Track API
2054
- // http://www.w3.org/TR/html5/video.html#the-track-element
2055
- // http://www.w3.org/TR/html5/media-elements.html#text-track-api
2056
- //
2057
- // While IE10 has implemented the track element, IE10 does not expose the underlying APIs to create timed text tracks by JS (really sad)
2058
- // By Addy Osmani
2059
- Modernizr.addTest({
2060
- texttrackapi: (typeof (document.createElement('video').addTextTrack) === 'function'),
2061
- // a more strict test for track including UI support: document.createElement('track').kind === 'subtitles'
2062
- track: ('kind' in document.createElement('track'))
2063
- });
2064
- // <output>
2065
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-output-element
2066
- // by Addy Osmani
2067
- Modernizr.addTest('outputelem', 'value' in document.createElement('output'));
2068
- // Requires a Modernizr build with `canvastext` included
2069
- // http://www.modernizr.com/download/#-canvas-canvastext
2070
- Modernizr.addTest('emoji', function() {
2071
- if (!Modernizr.canvastext) return false;
2072
- var node = document.createElement('canvas'),
2073
- ctx = node.getContext('2d');
2074
- ctx.textBaseline = 'top';
2075
- ctx.font = '32px Arial';
2076
- ctx.fillText('\ud83d\ude03', 0, 0); // "smiling face with open mouth" emoji
2077
- return ctx.getImageData(16, 16, 1, 1).data[0] !== 0;
2078
- });// strict mode
2079
-
2080
- // test by @kangax
2081
-
2082
- Modernizr.addTest('strictmode', function(){
2083
- return (function(){ "use strict"; return !this; })();
2084
- });//By Shi Chuan
2085
- //Part of Device Access aspect of HTML5, same category as geolocation
2086
- //W3C Editor's Draft at http://dev.w3.org/geo/api/spec-source-orientation.html
2087
- //Implementation by iOS Safari at http://goo.gl/fhce3 and http://goo.gl/rLKz8
2088
-
2089
-
2090
- //test for Device Motion Event support, returns boolean value true/false
2091
- Modernizr.addTest('devicemotion', ('DeviceMotionEvent' in window) );
2092
-
2093
- //test for Device Orientation Event support, returns boolean value true/false
2094
- Modernizr.addTest('deviceorientation', ('DeviceOrientationEvent' in window) );
2095
- // EXIF Orientation test
2096
-
2097
- // iOS looks at the EXIF Orientation flag in jpgs and rotates the image
2098
- // accordingly. Looks like most desktop browsers just ignore this data.
2099
-
2100
- // description: www.impulseadventure.com/photo/exif-orientation.html
2101
-
2102
- // Bug trackers:
2103
- // bugzil.la/298619 (unimplemented)
2104
- // crbug.com/56845 (looks incomplete)
2105
- // webk.it/19688 (available upstream but its up all ports to turn on individually)
2106
- //
2107
-
2108
- // detect by Paul Sayre
2109
-
2110
-
2111
- (function(){
2112
-
2113
- var img = new Image();
2114
-
2115
- img.onerror = function() {
2116
- Modernizr.addTest('exif-orientation', function () { return false; });
2117
- };
2118
-
2119
- img.onload = function() {
2120
- Modernizr.addTest('exif-orientation', function () { return img.width !== 2; });
2121
- };
2122
-
2123
- // There may be a way to shrink this more, it's a 1x2 white jpg with the orientation flag set to 6
2124
- img.src = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAABgASAAAAAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAABAAIDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/iiiigD/2Q==";
2125
-
2126
- })();
2127
- /**
2128
- * file tests for the File API specification
2129
- * Tests for objects specific to the File API W3C specification without
2130
- * being redundant (don't bother testing for Blob since it is assumed
2131
- * to be the File object's prototype.
2132
- *
2133
- * Will fail in Safari 5 due to its lack of support for the standards
2134
- * defined FileReader object
2135
- */
2136
- Modernizr.addTest('filereader', function () {
2137
- return !!(window.File && window.FileList && window.FileReader);
2138
- });
2139
-
2140
-
2141
- // Detects whether input type="file" is available on the platform
2142
- // E.g. iOS < 6 and some android version don't support this
2143
-
2144
- // It's useful if you want to hide the upload feature of your app on devices that
2145
- // don't support it (iphone, ipad, etc).
2146
-
2147
- Modernizr.addTest('fileinput', function() {
2148
- var elem = document.createElement('input');
2149
- elem.type = 'file';
2150
- return !elem.disabled;
2151
- });
2152
- // Detects whether input form="form_id" is available on the platform
2153
- // E.g. IE 10 (and below), don't support this
2154
- Modernizr.addTest("formattribute", function() {
2155
- var form = document.createElement("form"),
2156
- input = document.createElement("input"),
2157
- div = document.createElement("div"),
2158
- id = "formtest"+(new Date().getTime()),
2159
- attr,
2160
- bool = false;
2161
-
2162
- form.id = id;
2163
-
2164
- //IE6/7 confuses the form idl attribute and the form content attribute
2165
- if(document.createAttribute){
2166
- attr = document.createAttribute("form");
2167
- attr.nodeValue = id;
2168
- input.setAttributeNode(attr);
2169
- div.appendChild(form);
2170
- div.appendChild(input);
2171
-
2172
- document.documentElement.appendChild(div);
2173
-
2174
- bool = form.elements.length === 1 && input.form == form;
2175
-
2176
- div.parentNode.removeChild(div);
2177
- }
2178
-
2179
- return bool;
2180
- });// Filesystem API
2181
- // dev.w3.org/2009/dap/file-system/file-dir-sys.html
2182
-
2183
- // The API will be present in Chrome incognito, but will throw an exception.
2184
- // See crbug.com/93417
2185
- //
2186
- // By Eric Bidelman (@ebidel)
2187
-
2188
- Modernizr.addTest('filesystem', !!Modernizr.prefixed('requestFileSystem', window));// testing for placeholder attribute in inputs and textareas
2189
- // re-using Modernizr.input if available
2190
-
2191
- Modernizr.addTest('placeholder', function(){
2192
-
2193
- return !!( 'placeholder' in ( Modernizr.input || document.createElement('input') ) &&
2194
- 'placeholder' in ( Modernizr.textarea || document.createElement('textarea') )
2195
- );
2196
-
2197
- });
2198
- // speech input for inputs
2199
- // by @alrra
2200
-
2201
-
2202
- // `webkitSpeech` in elem
2203
- // doesn`t work correctly in all versions of Chromium based browsers.
2204
- // It can return false even if they have support for speech i.imgur.com/2Y40n.png
2205
- // Testing with 'onwebkitspeechchange' seems to fix this problem
2206
1177
 
2207
- // this detect only checks the webkit version because
2208
- // the speech attribute is likely to be deprecated in favor of a JavaScript API.
2209
- // http://lists.w3.org/Archives/Public/public-webapps/2011OctDec/att-1696/speechapi.html
2210
-
2211
- // FIXME: add support for detecting the new spec'd behavior
2212
-
2213
- Modernizr.addTest('speechinput', function(){
2214
- var elem = document.createElement('input');
2215
- return 'speech' in elem || 'onwebkitspeechchange' in elem;
2216
- });// This implementation only tests support for interactive form validation.
2217
- // To check validation for a specific type or a specific other constraint,
2218
- // the test can be combined:
2219
- // - Modernizr.inputtypes.numer && Modernizr.formvalidation (browser supports rangeOverflow, typeMismatch etc. for type=number)
2220
- // - Modernizr.input.required && Modernizr.formvalidation (browser supports valueMissing)
2221
- //
2222
- (function(document, Modernizr){
2223
-
2224
-
2225
- Modernizr.formvalidationapi = false;
2226
- Modernizr.formvalidationmessage = false;
2227
-
2228
- Modernizr.addTest('formvalidation', function(){
2229
- var form = document.createElement('form');
2230
- if ( !('checkValidity' in form) ) {
2231
- return false;
2232
- }
2233
- var body = document.body,
2234
-
2235
- html = document.documentElement,
2236
-
2237
- bodyFaked = false,
2238
-
2239
- invaildFired = false,
2240
-
2241
- input;
1178
+ ownerDocument.createElement = function(nodeName) {
1179
+ //abort shiv
1180
+ if (!html5.shivMethods) {
1181
+ return data.createElem(nodeName);
1182
+ }
1183
+ return createElement(nodeName, ownerDocument, data);
1184
+ };
2242
1185
 
2243
- Modernizr.formvalidationapi = true;
1186
+ ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
1187
+ 'var n=f.cloneNode(),c=n.createElement;' +
1188
+ 'h.shivMethods&&(' +
1189
+ // unroll the `createElement` calls
1190
+ getElements().join().replace(/\w+/g, function(nodeName) {
1191
+ data.createElem(nodeName);
1192
+ data.frag.createElement(nodeName);
1193
+ return 'c("' + nodeName + '")';
1194
+ }) +
1195
+ ');return n}'
1196
+ )(html5, data.frag);
1197
+ }
2244
1198
 
2245
- // Prevent form from being submitted
2246
- form.onsubmit = function(e) {
2247
- //Opera does not validate form, if submit is prevented
2248
- if ( !window.opera ) {
2249
- e.preventDefault();
1199
+ /*--------------------------------------------------------------------------*/
1200
+
1201
+ /**
1202
+ * Shivs the given document.
1203
+ * @memberOf html5
1204
+ * @param {Document} ownerDocument The document to shiv.
1205
+ * @returns {Document} The shived document.
1206
+ */
1207
+ function shivDocument(ownerDocument) {
1208
+ if (!ownerDocument) {
1209
+ ownerDocument = document;
2250
1210
  }
2251
- e.stopPropagation();
2252
- };
2253
-
2254
- // Calling form.submit() doesn't trigger interactive validation,
2255
- // use a submit button instead
2256
- //older opera browsers need a name attribute
2257
- form.innerHTML = '<input name="modTest" required><button></button>';
2258
-
2259
- // FF4 doesn't trigger "invalid" event if form is not in the DOM tree
2260
- // Chrome throws error if invalid input is not visible when submitting
2261
- form.style.position = 'absolute';
2262
- form.style.top = '-99999em';
2263
-
2264
- // We might in <head> in which case we need to create body manually
2265
- if ( !body ) {
2266
- bodyFaked = true;
2267
- body = document.createElement('body');
2268
- //avoid crashing IE8, if background image is used
2269
- body.style.background = "";
2270
- html.appendChild(body);
2271
- }
1211
+ var data = getExpandoData(ownerDocument);
1212
+
1213
+ if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
1214
+ data.hasCSS = !!addStyleSheet(ownerDocument,
1215
+ // corrects block display not defined in IE6/7/8/9
1216
+ 'article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}' +
1217
+ // adds styling not present in IE6/7/8/9
1218
+ 'mark{background:#FF0;color:#000}'
1219
+ );
1220
+ }
1221
+ if (!supportsUnknownElements) {
1222
+ shivMethods(ownerDocument, data);
1223
+ }
1224
+ return ownerDocument;
1225
+ }
2272
1226
 
2273
- body.appendChild(form);
1227
+ /*--------------------------------------------------------------------------*/
1228
+
1229
+ /**
1230
+ * The `html5` object is exposed so that more elements can be shived and
1231
+ * existing shiving can be detected on iframes.
1232
+ * @type Object
1233
+ * @example
1234
+ *
1235
+ * // options can be changed before the script is included
1236
+ * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
1237
+ */
1238
+ var html5 = {
1239
+
1240
+ /**
1241
+ * An array or space separated string of node names of the elements to shiv.
1242
+ * @memberOf html5
1243
+ * @type Array|String
1244
+ */
1245
+ 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video',
1246
+
1247
+ /**
1248
+ * A flag to indicate that the HTML5 style sheet should be inserted.
1249
+ * @memberOf html5
1250
+ * @type Boolean
1251
+ */
1252
+ 'shivCSS': (options.shivCSS !== false),
1253
+
1254
+ /**
1255
+ * Is equal to true if a browser supports creating unknown/HTML5 elements
1256
+ * @memberOf html5
1257
+ * @type boolean
1258
+ */
1259
+ 'supportsUnknownElements': supportsUnknownElements,
1260
+
1261
+ /**
1262
+ * A flag to indicate that the document's `createElement` and `createDocumentFragment`
1263
+ * methods should be overwritten.
1264
+ * @memberOf html5
1265
+ * @type Boolean
1266
+ */
1267
+ 'shivMethods': (options.shivMethods !== false),
1268
+
1269
+ /**
1270
+ * A string to describe the type of `html5` object ("default" or "default print").
1271
+ * @memberOf html5
1272
+ * @type String
1273
+ */
1274
+ 'type': 'default',
1275
+
1276
+ // shivs the document according to the specified `html5` object options
1277
+ 'shivDocument': shivDocument,
1278
+
1279
+ //creates a shived element
1280
+ createElement: createElement,
1281
+
1282
+ //creates a shived documentFragment
1283
+ createDocumentFragment: createDocumentFragment
1284
+ };
2274
1285
 
2275
- input = form.getElementsByTagName('input')[0];
1286
+ /*--------------------------------------------------------------------------*/
2276
1287
 
2277
- // Record whether "invalid" event is fired
2278
- input.oninvalid = function(e) {
2279
- invaildFired = true;
2280
- e.preventDefault();
2281
- e.stopPropagation();
2282
- };
1288
+ // expose html5
1289
+ window.html5 = html5;
2283
1290
 
2284
- //Opera does not fully support the validationMessage property
2285
- Modernizr.formvalidationmessage = !!input.validationMessage;
1291
+ // shiv the document
1292
+ shivDocument(document);
2286
1293
 
2287
- // Submit form by clicking submit button
2288
- form.getElementsByTagName('button')[0].click();
1294
+ }(this, document));
1295
+ /*>>shiv*/
2289
1296
 
2290
- // Don't forget to clean up
2291
- body.removeChild(form);
2292
- bodyFaked && html.removeChild(body);
1297
+ // Assign private properties to the return object with prefix
1298
+ Modernizr._version = version;
2293
1299
 
2294
- return invaildFired;
2295
- });
1300
+ // expose these for the plugin API. Look in the source for how to join() them against your input
1301
+ /*>>prefixes*/
1302
+ Modernizr._prefixes = prefixes;
1303
+ /*>>prefixes*/
1304
+ /*>>domprefixes*/
1305
+ Modernizr._domPrefixes = domPrefixes;
1306
+ Modernizr._cssomPrefixes = cssomPrefixes;
1307
+ /*>>domprefixes*/
1308
+
1309
+ /*>>mq*/
1310
+ // Modernizr.mq tests a given media query, live against the current state of the window
1311
+ // A few important notes:
1312
+ // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false
1313
+ // * A max-width or orientation query will be evaluated against the current state, which may change later.
1314
+ // * You must specify values. Eg. If you are testing support for the min-width media query use:
1315
+ // Modernizr.mq('(min-width:0)')
1316
+ // usage:
1317
+ // Modernizr.mq('only screen and (max-width:768)')
1318
+ Modernizr.mq = testMediaQuery;
1319
+ /*>>mq*/
2296
1320
 
1321
+ /*>>hasevent*/
1322
+ // Modernizr.hasEvent() detects support for a given event, with an optional element to test on
1323
+ // Modernizr.hasEvent('gesturestart', elem)
1324
+ Modernizr.hasEvent = isEventSupported;
1325
+ /*>>hasevent*/
2297
1326
 
2298
- })(document, window.Modernizr);Modernizr.addTest('fullscreen',function(){
2299
- for(var i = 0; i < Modernizr._domPrefixes.length; i++) {
2300
- if( document[Modernizr._domPrefixes[i].toLowerCase() + 'CancelFullScreen'])
2301
- return true;
2302
- }
2303
- return !!document['cancelFullScreen'] || false;
2304
- });
2305
-
2306
- // http://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/ControllingMediaWithJavaScript/ControllingMediaWithJavaScript.html#//apple_ref/doc/uid/TP40009523-CH3-SW20
2307
- // https://developer.mozilla.org/en/API/Fullscreen
2308
- // GamePad API
2309
- // https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html
2310
- // By Eric Bidelman
2311
-
2312
- // FF has Gamepad API support only in special builds, but not in any release (even behind a flag)
2313
- // Their current implementation has no way to feature detect, only events to bind to.
2314
- // http://www.html5rocks.com/en/tutorials/doodles/gamepad/#toc-featuredetect
2315
-
2316
- // but a patch will bring them up to date with the spec when it lands (and they'll pass this test)
2317
- // https://bugzilla.mozilla.org/show_bug.cgi?id=690935
2318
-
2319
- Modernizr.addTest('gamepads', !!Modernizr.prefixed('getGamepads', navigator));
2320
- // getUserMedia
2321
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/video-conferencing-and-peer-to-peer-communication.html
2322
- // By Eric Bidelman
2323
-
2324
- Modernizr.addTest('getusermedia', !!Modernizr.prefixed('getUserMedia', navigator));
2325
- // IE8 compat mode aka Fake IE7
2326
- // by Erich Ocean
2327
-
2328
- // In this case, IE8 will be acting as IE7. You may choose to remove features in this case.
2329
-
2330
- // related:
2331
- // james.padolsey.com/javascript/detect-ie-in-js-using-conditional-comments/
2332
-
2333
- Modernizr.addTest('ie8compat',function(){
2334
- return (!window.addEventListener && document.documentMode && document.documentMode === 7);
2335
- });
2336
- // Test for `seamless` attribute in iframes.
2337
- //
2338
- // Spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-seamless
2339
-
2340
- Modernizr.addTest('seamless', 'seamless' in document.createElement('iframe'));
2341
- // Test for `sandbox` attribute in iframes.
2342
- //
2343
- // Spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-sandbox
2344
-
2345
- Modernizr.addTest('sandbox', 'sandbox' in document.createElement('iframe'));
2346
- // Test for `srcdoc` attribute in iframes.
2347
- //
2348
- // Spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-srcdoc
2349
-
2350
- Modernizr.addTest('srcdoc', 'srcdoc' in document.createElement('iframe'));
2351
- // Animated PNG
2352
- // http://en.wikipedia.org/wiki/APNG
2353
- // By Addy Osmani
2354
- (function () {
2355
-
2356
- if (!Modernizr.canvas) return false;
2357
-
2358
- var image = new Image(),
2359
- canvas = document.createElement('canvas'),
2360
- ctx = canvas.getContext('2d');
2361
-
2362
-
2363
- image.onload = function () {
2364
- Modernizr.addTest('apng', function () {
2365
- if (typeof canvas.getContext == 'undefined') {
2366
- return false;
2367
- } else {
2368
- ctx.drawImage(image, 0, 0);
2369
- return ctx.getImageData(0, 0, 1, 1).data[3] === 0;
2370
- }
2371
- });
1327
+ /*>>testprop*/
1328
+ // Modernizr.testProp() investigates whether a given style property is recognized
1329
+ // Note that the property names must be provided in the camelCase variant.
1330
+ // Modernizr.testProp('pointerEvents')
1331
+ Modernizr.testProp = function(prop){
1332
+ return testProps([prop]);
2372
1333
  };
1334
+ /*>>testprop*/
2373
1335
 
2374
- image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACGFjVEwAAAABAAAAAcMq2TYAAAANSURBVAiZY2BgYPgPAAEEAQB9ssjfAAAAGmZjVEwAAAAAAAAAAQAAAAEAAAAAAAAAAAD6A+gBAbNU+2sAAAARZmRBVAAAAAEImWNgYGBgAAAABQAB6MzFdgAAAABJRU5ErkJggg==";
2375
-
2376
- }());
2377
- // code.google.com/speed/webp/
2378
- // by rich bradshaw, ryan seddon, and paul irish
2379
-
2380
-
2381
- // This test is asynchronous. Watch out.
2382
-
2383
- (function(){
2384
-
2385
- var image = new Image();
2386
-
2387
- image.onerror = function() {
2388
- Modernizr.addTest('webp', false);
2389
- };
2390
- image.onload = function() {
2391
- Modernizr.addTest('webp', function() { return image.width == 1; });
2392
- };
2393
-
2394
- image.src = 'data:image/webp;base64,UklGRiwAAABXRUJQVlA4ICAAAAAUAgCdASoBAAEAL/3+/3+CAB/AAAFzrNsAAP5QAAAAAA==';
2395
-
2396
- }());// native JSON support.
2397
- // developer.mozilla.org/en/JSON
2398
-
2399
- // this will also succeed if you've loaded the JSON2.js polyfill ahead of time
2400
- // ... but that should be obvious. :)
2401
-
2402
- Modernizr.addTest('json', !!window.JSON && !!JSON.parse);
2403
-
2404
- // impressivewebs.com/reverse-ordered-lists-html5
2405
- // polyfill: github.com/impressivewebs/HTML5-Reverse-Ordered-Lists
2406
-
2407
-
2408
- Modernizr.addTest('olreversed', 'reversed' in document.createElement('ol'));
2409
- // determining low-bandwidth via navigator.connection
2410
-
2411
- // There are two iterations of the navigator.connection interface:
2412
-
2413
- // The first is present in Android 2.2+ and only in the Browser (not WebView)
2414
- // : docs.phonegap.com/en/1.2.0/phonegap_connection_connection.md.html#connection.type
2415
- // : davidbcalhoun.com/2010/using-navigator-connection-android
2416
-
2417
- // The second is specced at dev.w3.org/2009/dap/netinfo/ and perhaps landing in WebKit
2418
- // : bugs.webkit.org/show_bug.cgi?id=73528
2419
-
2420
- // unknown devices are assumed as fast
2421
- // for more rigorous network testing, consider boomerang.js: github.com/bluesmoon/boomerang/
2422
-
2423
- Modernizr.addTest('lowbandwidth', function() {
2424
-
2425
- var connection = navigator.connection || { type: 0 }; // polyfill
2426
-
2427
- return connection.type == 3 || // connection.CELL_2G
2428
- connection.type == 4 || // connection.CELL_3G
2429
- /^[23]g$/.test(connection.type); // string value in new spec
2430
- });
2431
- // MathML
2432
- // http://www.w3.org/Math/
2433
- // By Addy Osmani
2434
- // Based on work by Davide (@dpvc) and David (@davidcarlisle)
2435
- // in https://github.com/mathjax/MathJax/issues/182
2436
-
2437
- Modernizr.addTest('mathml', function(){
2438
- var hasMathML = false;
2439
- if ( document.createElementNS ) {
2440
- var ns = "http://www.w3.org/1998/Math/MathML",
2441
- div = document.createElement("div");
2442
- div.style.position = "absolute";
2443
- var mfrac = div.appendChild(document.createElementNS(ns,"math"))
2444
- .appendChild(document.createElementNS(ns,"mfrac"));
2445
- mfrac.appendChild(document.createElementNS(ns,"mi"))
2446
- .appendChild(document.createTextNode("xx"));
2447
- mfrac.appendChild(document.createElementNS(ns,"mi"))
2448
- .appendChild(document.createTextNode("yy"));
2449
- document.body.appendChild(div);
2450
- hasMathML = div.offsetHeight > div.offsetWidth;
2451
- }
2452
- return hasMathML;
2453
- });
2454
- // server sent events aka eventsource
2455
- // dev.w3.org/html5/eventsource/
2456
-
2457
- Modernizr.addTest('eventsource', !!window.EventSource);
2458
-
2459
-
2460
- // XML HTTP Request Level 2
2461
- // www.w3.org/TR/XMLHttpRequest2/
2462
-
2463
- // Much more details at github.com/Modernizr/Modernizr/issues/385
2464
-
2465
- // all three of these details report consistently across all target browsers:
2466
- // !!(window.ProgressEvent);
2467
- // !!(window.FormData);
2468
- // window.XMLHttpRequest && "withCredentials" in new XMLHttpRequest;
2469
-
2470
- Modernizr.addTest('xhr2', 'FormData' in window);
2471
- // https://developer.mozilla.org/en-US/docs/API/Pointer_Lock_API
2472
-
2473
- Modernizr.addTest('pointerlock',!!Modernizr.prefixed('pointerLockElement', document));
2474
-
2475
- // Notifications
2476
- // By Theodoor van Donge
2477
-
2478
- // window.webkitNotifications is only used by Chrome
2479
- // http://www.html5rocks.com/en/tutorials/notifications/quick/
2480
-
2481
- // window.Notification only exist in the draft specs
2482
- // http://dev.w3.org/2006/webapi/WebNotifications/publish/Notifications.html#idl-if-Notification
2483
-
2484
- Modernizr.addTest('notification', !!Modernizr.prefixed('Notifications', window));// Navigation Timing (Performance)
2485
- // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/
2486
- // http://www.html5rocks.com/en/tutorials/webperformance/basics/
2487
- // By Scott Murphy (uxder)
2488
- Modernizr.addTest('performance', !!Modernizr.prefixed('performance', window));// Quota Storage Management API
2489
- // This API can be used to check how much quota an origin is using and request more
2490
-
2491
- // Currently only implemented in Chrome.
2492
- // https://developers.google.com/chrome/whitepapers/storage
2493
- // By Addy Osmani
2494
-
2495
- Modernizr.addTest('quotamanagement', function(){
2496
- var storage = Modernizr.prefixed('StorageInfo', window);
2497
- return !!(storage && 'TEMPORARY' in storage && 'PERSISTENT' in storage);
2498
- });
2499
-
2500
- // requestAnimationFrame
2501
- // Offload animation repainting to browser for optimized performance.
2502
- // http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html
2503
- // By Addy Osmani
2504
-
2505
- Modernizr.addTest('raf', !!Modernizr.prefixed('requestAnimationFrame', window));// async script
2506
- // By Theodoor van Donge
2507
- Modernizr.addTest('scriptasync', 'async' in document.createElement('script'));// defer script
2508
- // By Theodoor van Donge
2509
- Modernizr.addTest('scriptdefer', 'defer' in document.createElement('script'));// Browser support test for <style scoped>
2510
- // http://www.w3.org/TR/html5/the-style-element.html#attr-style-scoped
2511
- //
2512
- // by @alrra
2513
-
2514
- Modernizr.addTest( 'stylescoped', 'scoped' in document.createElement('style') );
2515
- // Detect support for svg filters - http://www.w3.org/TR/SVG11/filters.html.
2516
- // Should fail in Safari: http://stackoverflow.com/questions/9739955/feature-detecting-support-for-svg-filters.
2517
- // detect by erik dahlstrom
2518
-
2519
- Modernizr.addTest('svgfilters', function(){
2520
- var result = false;
2521
- try {
2522
- result = typeof SVGFEColorMatrixElement !== undefined &&
2523
- SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE == 2;
2524
- }
2525
- catch(e) {}
2526
- return result;
2527
- });
2528
- /**
2529
- * Unicode special character support
2530
- *
2531
- * Detection is made by testing missing glyph box rendering against star character
2532
- * If widths are the same, this "probably" means the browser didn't support the star character and rendered a glyph box instead
2533
- * Just need to ensure the font characters have different widths
2534
- *
2535
- * Warning : positive Unicode support doesn't mean you can use it inside <title>, this seams more related to OS & Language packs
2536
- */
2537
- Modernizr.addTest('unicode', function() {
2538
-
2539
-
2540
- var bool,
2541
-
2542
- missingGlyph = document.createElement('span'),
2543
-
2544
- star = document.createElement('span');
2545
-
2546
- Modernizr.testStyles('#modernizr{font-family:Arial,sans;font-size:300em;}', function(node) {
2547
-
2548
- missingGlyph.innerHTML = '&#5987';
2549
- star.innerHTML = '&#9734';
2550
-
2551
- node.appendChild(missingGlyph);
2552
- node.appendChild(star);
2553
-
2554
- bool = 'offsetWidth' in missingGlyph && missingGlyph.offsetWidth !== star.offsetWidth;
2555
- });
2556
-
2557
- return bool;
2558
-
2559
- });// data uri test.
2560
- // https://github.com/Modernizr/Modernizr/issues/14
2561
-
2562
- // This test is asynchronous. Watch out.
2563
-
2564
-
2565
- // in IE7 in HTTPS this can cause a Mixed Content security popup.
2566
- // github.com/Modernizr/Modernizr/issues/362
2567
- // To avoid that you can create a new iframe and inject this.. perhaps..
2568
-
2569
-
2570
- (function(){
2571
-
2572
- var datauri = new Image();
2573
-
2574
-
2575
- datauri.onerror = function() {
2576
- Modernizr.addTest('datauri', function () { return false; });
2577
- };
2578
- datauri.onload = function() {
2579
- Modernizr.addTest('datauri', function () { return (datauri.width == 1 && datauri.height == 1); });
2580
- };
2581
-
2582
- datauri.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
2583
-
2584
- })();
2585
- // test if IE userdata supported
2586
- // msdn.microsoft.com/en-us/library/ms531424(v=vs.85).aspx
2587
- // test by @stereobooster
2588
-
2589
- Modernizr.addTest('userdata', function(){
2590
- return !!document.createElement('div').addBehavior;
2591
- });
2592
- // Vibration API
2593
- // http://www.w3.org/TR/vibration/
2594
- // https://developer.mozilla.org/en/DOM/window.navigator.mozVibrate
2595
- Modernizr.addTest('vibrate', !!Modernizr.prefixed('vibrate', navigator));// Tests for the ability to use Web Intents (http://webintents.org).
2596
- // By Eric Bidelman
2597
-
2598
- Modernizr.addTest('webintents', function() {
2599
- return !!Modernizr.prefixed('startActivity', navigator);
2600
- });
2601
-
2602
- // binaryType is truthy if there is support.. returns "blob" in new-ish chrome.
2603
- // plus.google.com/115535723976198353696/posts/ERN6zYozENV
2604
-
2605
- Modernizr.addTest('websocketsbinary',
2606
- !!(window.WebSocket && (new WebSocket('ws://.')).binaryType)
2607
- );
2608
-
2609
- // Grab the WebGL extensions currently supported and add to the Modernizr.webgl object
2610
- // spec: www.khronos.org/registry/webgl/specs/latest/#5.13.14
2611
-
2612
- // based on code from ilmari heikkinen
2613
- // code.google.com/p/graphics-detect/source/browse/js/detect.js
2614
-
2615
-
2616
- (function(){
2617
-
2618
- if (!Modernizr.webgl) return;
2619
-
2620
- var canvas, ctx, exts;
2621
-
2622
- try {
2623
- canvas = document.createElement('canvas');
2624
- ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
2625
- exts = ctx.getSupportedExtensions();
2626
- }
2627
- catch (e) {
2628
- return;
2629
- }
2630
-
2631
- if (ctx === undefined) {
2632
- Modernizr.webgl = new Boolean(false);
2633
- }
2634
- else {
2635
- Modernizr.webgl = new Boolean(true);
2636
- }
2637
-
2638
-
2639
- for (var i = -1, len = exts.length; ++i < len; ){
2640
- Modernizr.webgl[exts[i]] = true;
2641
- }
2642
-
2643
- // hack for addressing modernizr testsuite failures. sorry.
2644
- if (window.TEST && TEST.audvid){
2645
- TEST.audvid.push('webgl');
2646
- }
2647
-
2648
- canvas = undefined;
2649
- })();
2650
- // tests if page is iframed
2651
-
2652
- // github.com/Modernizr/Modernizr/issues/242
2653
-
2654
- Modernizr.addTest('framed', function(){
2655
- return window.location != top.location;
2656
- });
2657
- // by jussi-kalliokoski
2658
-
2659
-
2660
- // This test is asynchronous. Watch out.
2661
-
2662
- // The test will potentially add garbage to console.
2663
-
2664
- (function(){
2665
- try {
1336
+ /*>>testallprops*/
1337
+ // Modernizr.testAllProps() investigates whether a given style property,
1338
+ // or any of its vendor-prefixed variants, is recognized
1339
+ // Note that the property names must be provided in the camelCase variant.
1340
+ // Modernizr.testAllProps('boxSizing')
1341
+ Modernizr.testAllProps = testPropsAll;
1342
+ /*>>testallprops*/
2666
1343
 
2667
- // we're avoiding using Modernizr._domPrefixes as the prefix capitalization on
2668
- // these guys are notoriously peculiar.
2669
- var BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder || window.OBlobBuilder || window.BlobBuilder,
2670
- URL = window.MozURL || window.webkitURL || window.MSURL || window.OURL || window.URL;
2671
1344
 
2672
- var data = 'Modernizr',
2673
- bb = new BlobBuilder();
1345
+ /*>>teststyles*/
1346
+ // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards
1347
+ // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })
1348
+ Modernizr.testStyles = injectElementWithStyles;
1349
+ /*>>teststyles*/
2674
1350
 
2675
- bb.append('this.onmessage=function(e){postMessage(e.data)}');
2676
1351
 
2677
- var url = URL.createObjectURL(bb.getBlob()),
2678
- worker = new Worker(url);
1352
+ /*>>prefixed*/
1353
+ // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input
1354
+ // Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
2679
1355
 
2680
- bb = null;
1356
+ // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style.
1357
+ // Return values will also be the camelCase variant, if you need to translate that to hypenated style use:
1358
+ //
1359
+ // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
2681
1360
 
2682
- worker.onmessage = function(e) {
2683
- worker.terminate();
2684
- URL.revokeObjectURL(url);
2685
- Modernizr.addTest('blobworkers', data === e.data);
2686
- worker = null;
2687
- };
1361
+ // If you're trying to ascertain which transition end event to bind to, you might do something like...
1362
+ //
1363
+ // var transEndEventNames = {
1364
+ // 'WebkitTransition' : 'webkitTransitionEnd',
1365
+ // 'MozTransition' : 'transitionend',
1366
+ // 'OTransition' : 'oTransitionEnd',
1367
+ // 'msTransition' : 'MSTransitionEnd',
1368
+ // 'transition' : 'transitionend'
1369
+ // },
1370
+ // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
2688
1371
 
2689
- // Just in case...
2690
- worker.onerror = function() {
2691
- Modernizr.addTest('blobworkers', false);
2692
- worker = null;
1372
+ Modernizr.prefixed = function(prop, obj, elem){
1373
+ if(!obj) {
1374
+ return testPropsAll(prop, 'pfx');
1375
+ } else {
1376
+ // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
1377
+ return testPropsAll(prop, obj, elem);
1378
+ }
2693
1379
  };
1380
+ /*>>prefixed*/
2694
1381
 
2695
- setTimeout(function() {
2696
- Modernizr.addTest('blobworkers', false);
2697
- }, 200);
2698
-
2699
- worker.postMessage(data);
2700
-
2701
- } catch (e) {
2702
- Modernizr.addTest('blobworkers', false);
2703
- }
2704
- }());
2705
- // by jussi-kalliokoski
2706
-
2707
-
2708
- // This test is asynchronous. Watch out.
2709
-
2710
- // The test will potentially add garbage to console.
2711
-
2712
- (function(){
2713
- try {
2714
- var data = 'Modernizr',
2715
- worker = new Worker('data:text/javascript;base64,dGhpcy5vbm1lc3NhZ2U9ZnVuY3Rpb24oZSl7cG9zdE1lc3NhZ2UoZS5kYXRhKX0=');
2716
1382
 
2717
- worker.onmessage = function(e) {
2718
- worker.terminate();
2719
- Modernizr.addTest('dataworkers', data === e.data);
2720
- worker = null;
2721
- };
2722
-
2723
- // Just in case...
2724
- worker.onerror = function() {
2725
- Modernizr.addTest('dataworkers', false);
2726
- worker = null;
2727
- };
1383
+ /*>>cssclasses*/
1384
+ // Remove "no-js" class from <html> element, if it exists:
1385
+ docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') +
2728
1386
 
2729
- setTimeout(function() {
2730
- Modernizr.addTest('dataworkers', false);
2731
- }, 200);
1387
+ // Add the new classes to the <html> element.
1388
+ (enableClasses ? ' js ' + classes.join(' ') : '');
1389
+ /*>>cssclasses*/
2732
1390
 
2733
- worker.postMessage(data);
1391
+ return Modernizr;
2734
1392
 
2735
- } catch (e) {
2736
- Modernizr.addTest('dataworkers', false);
2737
- }
2738
- }());
2739
- Modernizr.addTest('sharedworkers', function(){
2740
- return !!window.SharedWorker;
2741
- });;
1393
+ })(this, this.document);