modernizr-rails 2.6.2.1 → 2.6.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  module Modernizr
2
2
  module Rails
3
- VERSION = '2.6.2.1'
3
+ VERSION = '2.6.2.2'
4
4
  end
5
5
  end
@@ -1,26 +1,9 @@
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/
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
7
3
  */
4
+ ;
5
+
8
6
 
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
- */
24
7
 
25
8
  window.Modernizr = (function( window, document, undefined ) {
26
9
 
@@ -28,58 +11,31 @@ window.Modernizr = (function( window, document, undefined ) {
28
11
 
29
12
  Modernizr = {},
30
13
 
31
- /*>>cssclasses*/
32
- // option for enabling the HTML classes to be added
33
14
  enableClasses = true,
34
- /*>>cssclasses*/
35
15
 
36
16
  docElement = document.documentElement,
37
17
 
38
- /**
39
- * Create our "modernizr" element that we do most feature tests on.
40
- */
41
18
  mod = 'modernizr',
42
19
  modElem = document.createElement(mod),
43
20
  mStyle = modElem.style,
44
21
 
45
- /**
46
- * Create the input element for various Web Forms feature tests.
47
- */
48
- inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ ,
22
+ inputElem = document.createElement('input') ,
49
23
 
50
- /*>>smile*/
51
24
  smile = ':)',
52
- /*>>smile*/
53
25
 
54
26
  toString = {}.toString,
55
27
 
56
- // TODO :: make the prefixes more granular
57
- /*>>prefixes*/
58
- // List of property values to set for css tests. See ticket #21
59
28
  prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
60
- /*>>prefixes*/
61
29
 
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
67
30
 
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/
71
31
 
72
- // More here: github.com/Modernizr/Modernizr/issues/issue/21
73
32
  omPrefixes = 'Webkit Moz O ms',
74
33
 
75
34
  cssomPrefixes = omPrefixes.split(' '),
76
35
 
77
36
  domPrefixes = omPrefixes.toLowerCase().split(' '),
78
- /*>>domprefixes*/
79
37
 
80
- /*>>ns*/
81
38
  ns = {'svg': 'http://www.w3.org/2000/svg'},
82
- /*>>ns*/
83
39
 
84
40
  tests = {},
85
41
  inputs = {},
@@ -89,54 +45,38 @@ window.Modernizr = (function( window, document, undefined ) {
89
45
 
90
46
  slice = classes.slice,
91
47
 
92
- featureName, // used in testing loop
48
+ featureName,
93
49
 
94
50
 
95
- /*>>teststyles*/
96
- // Inject element with style element and some CSS rules
97
51
  injectElementWithStyles = function( rule, callback, nodes, testnames ) {
98
52
 
99
53
  var style, ret, node, docOverflow,
100
54
  div = document.createElement('div'),
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');
55
+ body = document.body,
56
+ fakeBody = body || document.createElement('body');
105
57
 
106
58
  if ( parseInt(nodes, 10) ) {
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-- ) {
59
+ while ( nodes-- ) {
110
60
  node = document.createElement('div');
111
61
  node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
112
62
  div.appendChild(node);
113
63
  }
114
64
  }
115
65
 
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('');
66
+ style = ['&#173;','<style id="s', mod, '">', rule, '</style>'].join('');
122
67
  div.id = mod;
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;
68
+ (body ? div : fakeBody).innerHTML += style;
126
69
  fakeBody.appendChild(div);
127
70
  if ( !body ) {
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';
71
+ fakeBody.style.background = '';
72
+ fakeBody.style.overflow = 'hidden';
132
73
  docOverflow = docElement.style.overflow;
133
74
  docElement.style.overflow = 'hidden';
134
75
  docElement.appendChild(fakeBody);
135
76
  }
136
77
 
137
78
  ret = callback(div, rule);
138
- // If this is done after page load we don't want to remove the body so check if body exists
139
- if ( !body ) {
79
+ if ( !body ) {
140
80
  fakeBody.parentNode.removeChild(fakeBody);
141
81
  docElement.style.overflow = docOverflow;
142
82
  } else {
@@ -146,12 +86,7 @@ window.Modernizr = (function( window, document, undefined ) {
146
86
  return !!ret;
147
87
 
148
88
  },
149
- /*>>teststyles*/
150
89
 
151
- /*>>mq*/
152
- // adapted from matchMedia polyfill
153
- // by Scott Jehl and Paul Irish
154
- // gist.github.com/786768
155
90
  testMediaQuery = function( mq ) {
156
91
 
157
92
  var matchMedia = window.matchMedia || window.msMatchMedia;
@@ -170,18 +105,8 @@ window.Modernizr = (function( window, document, undefined ) {
170
105
  return bool;
171
106
 
172
107
  },
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
- // ...
108
+
109
+
185
110
  isEventSupported = (function() {
186
111
 
187
112
  var TAGNAMES = {
@@ -195,20 +120,17 @@ window.Modernizr = (function( window, document, undefined ) {
195
120
  element = element || document.createElement(TAGNAMES[eventName] || 'div');
196
121
  eventName = 'on' + eventName;
197
122
 
198
- // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
199
- var isSupported = eventName in element;
123
+ var isSupported = eventName in element;
200
124
 
201
125
  if ( !isSupported ) {
202
- // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
203
- if ( !element.setAttribute ) {
126
+ if ( !element.setAttribute ) {
204
127
  element = document.createElement('div');
205
128
  }
206
129
  if ( element.setAttribute && element.removeAttribute ) {
207
130
  element.setAttribute(eventName, '');
208
131
  isSupported = is(element[eventName], 'function');
209
132
 
210
- // If property was created, "remove it" (by setting value to `undefined`)
211
- if ( !is(element[eventName], 'undefined') ) {
133
+ if ( !is(element[eventName], 'undefined') ) {
212
134
  element[eventName] = undefined;
213
135
  }
214
136
  element.removeAttribute(eventName);
@@ -220,11 +142,8 @@ window.Modernizr = (function( window, document, undefined ) {
220
142
  }
221
143
  return isEventSupported;
222
144
  })(),
223
- /*>>hasevent*/
224
145
 
225
- // TODO :: Add flag for hasownprop ? didn't last time
226
146
 
227
- // hasOwnProperty shim by kangax needed for Safari 2.0 support
228
147
  _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
229
148
 
230
149
  if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
@@ -233,13 +152,11 @@ window.Modernizr = (function( window, document, undefined ) {
233
152
  };
234
153
  }
235
154
  else {
236
- hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
155
+ hasOwnProp = function (object, property) {
237
156
  return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
238
157
  };
239
158
  }
240
159
 
241
- // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js
242
- // es5.github.com/#x15.3.4.5
243
160
 
244
161
  if (!Function.prototype.bind) {
245
162
  Function.prototype.bind = function bind(that) {
@@ -283,54 +200,22 @@ window.Modernizr = (function( window, document, undefined ) {
283
200
  };
284
201
  }
285
202
 
286
- /**
287
- * setCss applies given styles to the Modernizr DOM node.
288
- */
289
203
  function setCss( str ) {
290
204
  mStyle.cssText = str;
291
205
  }
292
206
 
293
- /**
294
- * setCssAll extrapolates all vendor-specific css strings.
295
- */
296
207
  function setCssAll( str1, str2 ) {
297
208
  return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
298
209
  }
299
210
 
300
- /**
301
- * is returns a boolean for if typeof obj is exactly type.
302
- */
303
211
  function is( obj, type ) {
304
212
  return typeof obj === type;
305
213
  }
306
214
 
307
- /**
308
- * contains returns a boolean for if substr is found within str.
309
- */
310
215
  function contains( str, substr ) {
311
216
  return !!~('' + str).indexOf(substr);
312
217
  }
313
218
 
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
-
334
219
  function testProps( props, prefixed ) {
335
220
  for ( var i in props ) {
336
221
  var prop = props[i];
@@ -340,81 +225,45 @@ window.Modernizr = (function( window, document, undefined ) {
340
225
  }
341
226
  return false;
342
227
  }
343
- /*>>testprop*/
344
228
 
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
- */
350
229
  function testDOMProps( props, obj, elem ) {
351
230
  for ( var i in props ) {
352
231
  var item = obj[props[i]];
353
232
  if ( item !== undefined) {
354
233
 
355
- // return the property name as a string
356
- if (elem === false) return props[i];
234
+ if (elem === false) return props[i];
357
235
 
358
- // let's bind a function
359
- if (is(item, 'function')){
360
- // default to autobind unless override
361
- return item.bind(elem || obj);
236
+ if (is(item, 'function')){
237
+ return item.bind(elem || obj);
362
238
  }
363
239
 
364
- // return the unbound function or obj or value
365
- return item;
240
+ return item;
366
241
  }
367
242
  }
368
243
  return false;
369
244
  }
370
245
 
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
- */
378
246
  function testPropsAll( prop, prefixed, elem ) {
379
247
 
380
248
  var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
381
249
  props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
382
250
 
383
- // did they call .prefixed('boxSizing') or are we just testing a prop?
384
- if(is(prefixed, "string") || is(prefixed, "undefined")) {
251
+ if(is(prefixed, "string") || is(prefixed, "undefined")) {
385
252
  return testProps(props, prefixed);
386
253
 
387
- // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
388
- } else {
254
+ } else {
389
255
  props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
390
256
  return testDOMProps(props, prefixed, elem);
391
257
  }
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() {
258
+ } tests['flexbox'] = function() {
405
259
  return testPropsAll('flexWrap');
406
260
  };
407
261
 
408
- // The *old* flexbox
409
- // www.w3.org/TR/2009/WD-css3-flexbox-20090723/
410
262
 
411
263
  tests['flexboxlegacy'] = function() {
412
264
  return testPropsAll('boxDirection');
413
265
  };
414
266
 
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/
418
267
 
419
268
  tests['canvas'] = function() {
420
269
  var elem = document.createElement('canvas');
@@ -425,28 +274,12 @@ window.Modernizr = (function( window, document, undefined ) {
425
274
  return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
426
275
  };
427
276
 
428
- // webk.it/70117 is tracking a legit WebGL feature detect proposal
429
277
 
430
- // We do a soft detect which may false positive in order to avoid
431
- // an expensive context creation: bugzil.la/732441
432
278
 
433
279
  tests['webgl'] = function() {
434
280
  return !!window.WebGLRenderingContext;
435
281
  };
436
282
 
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
- */
450
283
 
451
284
  tests['touch'] = function() {
452
285
  var bool;
@@ -463,15 +296,6 @@ window.Modernizr = (function( window, document, undefined ) {
463
296
  };
464
297
 
465
298
 
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
475
299
 
476
300
  tests['geolocation'] = function() {
477
301
  return 'geolocation' in navigator;
@@ -483,31 +307,18 @@ window.Modernizr = (function( window, document, undefined ) {
483
307
  };
484
308
 
485
309
 
486
- // Chrome incognito mode used to throw an exception when using openDatabase
487
- // It doesn't anymore.
488
310
  tests['websqldatabase'] = function() {
489
311
  return !!window.openDatabase;
490
312
  };
491
313
 
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
496
314
  tests['indexedDB'] = function() {
497
315
  return !!testPropsAll("indexedDB", window);
498
316
  };
499
317
 
500
- // documentMode logic from YUI to filter out IE8 Compat Mode
501
- // which false positives.
502
318
  tests['hashchange'] = function() {
503
319
  return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);
504
320
  };
505
321
 
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.
511
322
  tests['history'] = function() {
512
323
  return !!(window.history && history.pushState);
513
324
  };
@@ -517,52 +328,28 @@ window.Modernizr = (function( window, document, undefined ) {
517
328
  return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
518
329
  };
519
330
 
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/
524
331
  tests['websockets'] = function() {
525
332
  return 'WebSocket' in window || 'MozWebSocket' in window;
526
333
  };
527
334
 
528
335
 
529
- // css-tricks.com/rgba-browser-support/
530
336
  tests['rgba'] = function() {
531
- // Set an rgba() color and check the returned value
532
-
533
337
  setCss('background-color:rgba(150,255,150,.5)');
534
338
 
535
339
  return contains(mStyle.backgroundColor, 'rgba');
536
340
  };
537
341
 
538
342
  tests['hsla'] = function() {
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)');
343
+ setCss('background-color:hsla(120,40%,100%,.5)');
543
344
 
544
345
  return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');
545
346
  };
546
347
 
547
348
  tests['multiplebgs'] = function() {
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!
349
+ setCss('background:url(https://),url(https://),red url(https://)');
551
350
 
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() {
351
+ return (/(url\s*\(.*?){3}/).test(mStyle.background);
352
+ }; tests['backgroundsize'] = function() {
566
353
  return testPropsAll('backgroundSize');
567
354
  };
568
355
 
@@ -571,41 +358,27 @@ window.Modernizr = (function( window, document, undefined ) {
571
358
  };
572
359
 
573
360
 
574
- // Super comprehensive table about all the unique implementations of
575
- // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance
576
361
 
577
362
  tests['borderradius'] = function() {
578
363
  return testPropsAll('borderRadius');
579
364
  };
580
365
 
581
- // WebOS unfortunately false positives on this test.
582
366
  tests['boxshadow'] = function() {
583
367
  return testPropsAll('boxShadow');
584
368
  };
585
369
 
586
- // FF3.0 will false positive on this test
587
370
  tests['textshadow'] = function() {
588
371
  return document.createElement('div').style.textShadow === '';
589
372
  };
590
373
 
591
374
 
592
375
  tests['opacity'] = function() {
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.
376
+ setCssAll('opacity:.55');
596
377
 
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);
378
+ return (/^0.55$/).test(mStyle.opacity);
603
379
  };
604
380
 
605
381
 
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/
609
382
  tests['cssanimations'] = function() {
610
383
  return testPropsAll('animationName');
611
384
  };
@@ -617,23 +390,13 @@ window.Modernizr = (function( window, document, undefined ) {
617
390
 
618
391
 
619
392
  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
-
628
393
  var str1 = 'background-image:',
629
394
  str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
630
395
  str3 = 'linear-gradient(left top,#9f9, white);';
631
396
 
632
397
  setCss(
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)
398
+ (str1 + '-webkit- '.split(' ').join(str2 + str1) +
399
+ prefixes.join(str3 + str1)).slice(0, -str1.length)
637
400
  );
638
401
 
639
402
  return contains(mStyle.backgroundImage, 'gradient');
@@ -654,15 +417,9 @@ window.Modernizr = (function( window, document, undefined ) {
654
417
 
655
418
  var ret = !!testPropsAll('perspective');
656
419
 
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 ) {
420
+ if ( ret && 'webkitPerspective' in docElement.style ) {
662
421
 
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 ) {
422
+ injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {
666
423
  ret = node.offsetLeft === 9 && node.offsetHeight === 3;
667
424
  });
668
425
  }
@@ -675,13 +432,7 @@ window.Modernizr = (function( window, document, undefined ) {
675
432
  };
676
433
 
677
434
 
678
- /*>>fontface*/
679
- // @font-face detection routine by Diego Perini
680
- // javascript.nwbox.com/CSSSupport/
681
435
 
682
- // false positives:
683
- // WebOS github.com/Modernizr/Modernizr/issues/342
684
- // WP7 github.com/Modernizr/Modernizr/issues/538
685
436
  tests['fontface'] = function() {
686
437
  var bool;
687
438
 
@@ -695,9 +446,7 @@ window.Modernizr = (function( window, document, undefined ) {
695
446
 
696
447
  return bool;
697
448
  };
698
- /*>>fontface*/
699
449
 
700
- // CSS generated content detection
701
450
  tests['generatedcontent'] = function() {
702
451
  var bool;
703
452
 
@@ -707,35 +456,16 @@ window.Modernizr = (function( window, document, undefined ) {
707
456
 
708
457
  return bool;
709
458
  };
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
-
727
459
  tests['video'] = function() {
728
460
  var elem = document.createElement('video'),
729
461
  bool = false;
730
462
 
731
- // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
732
- try {
463
+ try {
733
464
  if ( bool = !!elem.canPlayType ) {
734
465
  bool = new Boolean(bool);
735
466
  bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,'');
736
467
 
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$/,'');
468
+ bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,'');
739
469
 
740
470
  bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,'');
741
471
  }
@@ -755,10 +485,7 @@ window.Modernizr = (function( window, document, undefined ) {
755
485
  bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
756
486
  bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,'');
757
487
 
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$/,'');
488
+ bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,'');
762
489
  bool.m4a = ( elem.canPlayType('audio/x-m4a;') ||
763
490
  elem.canPlayType('audio/aac;')) .replace(/^no$/,'');
764
491
  }
@@ -768,23 +495,6 @@ window.Modernizr = (function( window, document, undefined ) {
768
495
  };
769
496
 
770
497
 
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
-
788
498
  tests['localstorage'] = function() {
789
499
  try {
790
500
  localStorage.setItem(mod, mod);
@@ -816,79 +526,43 @@ window.Modernizr = (function( window, document, undefined ) {
816
526
  };
817
527
 
818
528
 
819
- // Thanks to Erik Dahlstrom
820
529
  tests['svg'] = function() {
821
530
  return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
822
531
  };
823
532
 
824
- // specifically for SVG inline in HTML, not within XHTML
825
- // test page: paulirish.com/demo/inline-svg
826
533
  tests['inlinesvg'] = function() {
827
534
  var div = document.createElement('div');
828
535
  div.innerHTML = '<svg/>';
829
536
  return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
830
537
  };
831
538
 
832
- // SVG SMIL animation
833
539
  tests['smil'] = function() {
834
540
  return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));
835
541
  };
836
542
 
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
839
543
 
840
- // However read the comments to dig into applying SVG clippaths to HTML content here:
841
- // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491
842
544
  tests['svgclippaths'] = function() {
843
545
  return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
844
546
  };
845
547
 
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.
849
548
  function webforms() {
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 ) {
549
+ Modernizr['input'] = (function( props ) {
862
550
  for ( var i = 0, len = props.length; i < len; i++ ) {
863
551
  attrs[ props[i] ] = !!(props[i] in inputElem);
864
552
  }
865
553
  if (attrs.list){
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);
554
+ attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);
869
555
  }
870
556
  return attrs;
871
557
  })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));
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) {
558
+ Modernizr['inputtypes'] = (function(props) {
882
559
 
883
560
  for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
884
561
 
885
562
  inputElem.setAttribute('type', inputElemType = props[i]);
886
563
  bool = inputElem.type !== 'text';
887
564
 
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 ) {
565
+ if ( bool ) {
892
566
 
893
567
  inputElem.value = smile;
894
568
  inputElem.style.cssText = 'position:absolute;visibility:hidden;';
@@ -898,29 +572,18 @@ window.Modernizr = (function( window, document, undefined ) {
898
572
  docElement.appendChild(inputElem);
899
573
  defaultView = document.defaultView;
900
574
 
901
- // Safari 2-4 allows the smiley as a value, despite making a slider
902
- bool = defaultView.getComputedStyle &&
575
+ bool = defaultView.getComputedStyle &&
903
576
  defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
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);
577
+ (inputElem.offsetHeight !== 0);
907
578
 
908
579
  docElement.removeChild(inputElem);
909
580
 
910
581
  } else if ( /^(search|tel)$/.test(inputElemType) ){
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;
582
+ } else if ( /^(url|email)$/.test(inputElemType) ) {
583
+ bool = inputElem.checkValidity && inputElem.checkValidity() === false;
920
584
 
921
585
  } else {
922
- // If the upgraded input compontent rejects the :) text, we got a winner
923
- bool = inputElem.value != smile;
586
+ bool = inputElem.value != smile;
924
587
  }
925
588
  }
926
589
 
@@ -928,44 +591,19 @@ window.Modernizr = (function( window, document, undefined ) {
928
591
  }
929
592
  return inputs;
930
593
  })('search tel url email datetime date month week time datetime-local number range color'.split(' '));
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.
594
+ }
943
595
  for ( var feature in tests ) {
944
596
  if ( hasOwnProp(tests, feature) ) {
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();
597
+ featureName = feature.toLowerCase();
949
598
  Modernizr[featureName] = tests[feature]();
950
599
 
951
600
  classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
952
601
  }
953
602
  }
954
603
 
955
- /*>>webforms*/
956
- // input tests need to run.
957
604
  Modernizr.input || webforms();
958
- /*>>webforms*/
959
605
 
960
606
 
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
- */
969
607
  Modernizr.addTest = function ( feature, test ) {
970
608
  if ( typeof feature == 'object' ) {
971
609
  for ( var key in feature ) {
@@ -978,12 +616,7 @@ window.Modernizr = (function( window, document, undefined ) {
978
616
  feature = feature.toLowerCase();
979
617
 
980
618
  if ( Modernizr[feature] !== undefined ) {
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;
619
+ return Modernizr;
987
620
  }
988
621
 
989
622
  test = typeof test == 'function' ? test() : test;
@@ -995,399 +628,2114 @@ window.Modernizr = (function( window, document, undefined ) {
995
628
 
996
629
  }
997
630
 
998
- return Modernizr; // allow chaining.
631
+ return Modernizr;
999
632
  };
1000
633
 
1001
634
 
1002
- // Reset modElem.cssText to nothing to reduce memory footprint.
1003
635
  setCss('');
1004
636
  modElem = inputElem = null;
1005
637
 
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 || {};
1012
638
 
1013
- /** Used to skip problem elements */
1014
- var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
639
+ Modernizr._version = version;
1015
640
 
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;
641
+ Modernizr._prefixes = prefixes;
642
+ Modernizr._domPrefixes = domPrefixes;
643
+ Modernizr._cssomPrefixes = cssomPrefixes;
1018
644
 
1019
- /** Detect whether the browser supports default html5 styles */
1020
- var supportsHtml5Styles;
645
+ Modernizr.mq = testMediaQuery;
1021
646
 
1022
- /** Name of the expando, to work with multiple documents or to re-shiv one document */
1023
- var expando = '_html5shiv';
647
+ Modernizr.hasEvent = isEventSupported;
1024
648
 
1025
- /** The id for the the documents expando */
1026
- var expanID = 0;
649
+ Modernizr.testProp = function(prop){
650
+ return testProps([prop]);
651
+ };
1027
652
 
1028
- /** Cached data for each document */
1029
- var expandoData = {};
653
+ Modernizr.testAllProps = testPropsAll;
1030
654
 
1031
- /** Detect whether the browser supports unknown elements */
1032
- var supportsUnknownElements;
1033
655
 
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
- }
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
+
1055
665
 
1056
- }());
666
+ docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') +
1057
667
 
1058
- /*--------------------------------------------------------------------------*/
668
+ (enableClasses ? ' js ' + classes.join(' ') : '');
1059
669
 
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;
670
+ return Modernizr;
1070
671
 
1071
- p.innerHTML = 'x<style>' + cssText + '</style>';
1072
- return parent.insertBefore(p.lastChild, parent.firstChild);
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
+ }
721
+
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);
1073
848
  }
849
+ return createElement(nodeName, ownerDocument, data);
850
+ };
1074
851
 
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;
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)));
1083
1001
  }
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
+ }
1084
1083
 
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;
1084
+ function removeSheet() {
1085
+ clearTimeout(data._removeSheetTimer);
1086
+ if (shivedSheet) {
1087
+ shivedSheet.removeNode(true);
1100
1088
  }
1089
+ shivedSheet= null;
1090
+ }
1101
1091
 
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;
1092
+ ownerWindow.attachEvent('onbeforeprint', function() {
1120
1093
 
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
- }
1094
+ removeSheet();
1128
1095
 
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;
1096
+ var imports,
1097
+ length,
1098
+ sheet,
1099
+ collection = ownerDocument.styleSheets,
1100
+ cssText = [],
1101
+ index = collection.length,
1102
+ sheets = Array(index);
1103
+
1104
+ // convert styleSheets collection to an array
1105
+ while (index--) {
1106
+ sheets[index] = collection[index];
1137
1107
  }
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
+ }
1138
1120
 
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;
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]);
1121
+ for (index = 0; index < length; index++) {
1122
+ sheets.push(imports[index]);
1123
+ }
1124
+
1125
+ try {
1126
+ cssText.push(sheet.cssText);
1127
+ } catch(er){}
1159
1128
  }
1160
- return clone;
1161
1129
  }
1162
1130
 
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();
1175
- }
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
+ });
1176
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
1177
1192
 
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
- };
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
+ });
1185
1198
 
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
- }
1199
+ // Battery API
1200
+ // https://developer.mozilla.org/en/DOM/window.navigator.mozBattery
1201
+ // By: Paul Sayre
1198
1202
 
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;
1210
- }
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
- );
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];
1220
2024
  }
1221
- if (!supportsUnknownElements) {
1222
- shivMethods(ownerDocument, data);
2025
+
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
+
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;
2242
+
2243
+ Modernizr.formvalidationapi = true;
2244
+
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();
1223
2250
  }
1224
- return ownerDocument;
1225
- }
2251
+ e.stopPropagation();
2252
+ };
1226
2253
 
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
- };
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
+ }
1285
2272
 
1286
- /*--------------------------------------------------------------------------*/
2273
+ body.appendChild(form);
1287
2274
 
1288
- // expose html5
1289
- window.html5 = html5;
2275
+ input = form.getElementsByTagName('input')[0];
1290
2276
 
1291
- // shiv the document
1292
- shivDocument(document);
2277
+ // Record whether "invalid" event is fired
2278
+ input.oninvalid = function(e) {
2279
+ invaildFired = true;
2280
+ e.preventDefault();
2281
+ e.stopPropagation();
2282
+ };
1293
2283
 
1294
- }(this, document));
1295
- /*>>shiv*/
2284
+ //Opera does not fully support the validationMessage property
2285
+ Modernizr.formvalidationmessage = !!input.validationMessage;
1296
2286
 
1297
- // Assign private properties to the return object with prefix
1298
- Modernizr._version = version;
2287
+ // Submit form by clicking submit button
2288
+ form.getElementsByTagName('button')[0].click();
1299
2289
 
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*/
2290
+ // Don't forget to clean up
2291
+ body.removeChild(form);
2292
+ bodyFaked && html.removeChild(body);
1320
2293
 
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*/
2294
+ return invaildFired;
2295
+ });
1326
2296
 
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]);
2297
+
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
+ });
1333
2372
  };
1334
- /*>>testprop*/
1335
2373
 
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*/
2374
+ image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACGFjVEwAAAABAAAAAcMq2TYAAAANSURBVAiZY2BgYPgPAAEEAQB9ssjfAAAAGmZjVEwAAAAAAAAAAQAAAAEAAAAAAAAAAAD6A+gBAbNU+2sAAAARZmRBVAAAAAEImWNgYGBgAAAABQAB6MzFdgAAAABJRU5ErkJggg==";
1343
2375
 
2376
+ }());
2377
+ // code.google.com/speed/webp/
2378
+ // by rich bradshaw, ryan seddon, and paul irish
1344
2379
 
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*/
1350
2380
 
2381
+ // This test is asynchronous. Watch out.
1351
2382
 
1352
- /*>>prefixed*/
1353
- // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input
1354
- // Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
2383
+ (function(){
1355
2384
 
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-');
2385
+ var image = new Image();
1360
2386
 
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') ];
2387
+ image.onerror = function() {
2388
+ Modernizr.addTest('webp', false);
2389
+ };
2390
+ image.onload = function() {
2391
+ Modernizr.addTest('webp', function() { return image.width == 1; });
2392
+ };
1371
2393
 
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
- }
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 {
2666
+
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
+
2672
+ var data = 'Modernizr',
2673
+ bb = new BlobBuilder();
2674
+
2675
+ bb.append('this.onmessage=function(e){postMessage(e.data)}');
2676
+
2677
+ var url = URL.createObjectURL(bb.getBlob()),
2678
+ worker = new Worker(url);
2679
+
2680
+ bb = null;
2681
+
2682
+ worker.onmessage = function(e) {
2683
+ worker.terminate();
2684
+ URL.revokeObjectURL(url);
2685
+ Modernizr.addTest('blobworkers', data === e.data);
2686
+ worker = null;
2687
+ };
2688
+
2689
+ // Just in case...
2690
+ worker.onerror = function() {
2691
+ Modernizr.addTest('blobworkers', false);
2692
+ worker = null;
1379
2693
  };
1380
- /*>>prefixed*/
1381
2694
 
2695
+ setTimeout(function() {
2696
+ Modernizr.addTest('blobworkers', false);
2697
+ }, 200);
1382
2698
 
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') +
2699
+ worker.postMessage(data);
1386
2700
 
1387
- // Add the new classes to the <html> element.
1388
- (enableClasses ? ' js ' + classes.join(' ') : '');
1389
- /*>>cssclasses*/
2701
+ } catch (e) {
2702
+ Modernizr.addTest('blobworkers', false);
2703
+ }
2704
+ }());
2705
+ // by jussi-kalliokoski
1390
2706
 
1391
- return Modernizr;
1392
2707
 
1393
- })(this, this.document);
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
+
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
+ };
2728
+
2729
+ setTimeout(function() {
2730
+ Modernizr.addTest('dataworkers', false);
2731
+ }, 200);
2732
+
2733
+ worker.postMessage(data);
2734
+
2735
+ } catch (e) {
2736
+ Modernizr.addTest('dataworkers', false);
2737
+ }
2738
+ }());
2739
+ Modernizr.addTest('sharedworkers', function(){
2740
+ return !!window.SharedWorker;
2741
+ });;