modernizr_rails 2.5.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in modernizr-rails.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Tse-Ching Ho
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # Modernizr for rails asset pipeline
2
+
3
+ [Modernizr](https://github.com/Modernizr/Modernizr) is a JavaScript library allowing you to use CSS3 & HTML5 while maintaining control over unsupported browsers.
4
+
5
+ The `modernizr_rails` gem integrates the `Modernizr` with the Rails asset pipeline.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'modernizr_rails', :require => 'modernizr-rails'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install modernizr_rails
20
+
21
+ ## Usage
22
+
23
+ Add to your `app/assets/stylesheets/application.js`
24
+
25
+ //= require modernizr
26
+
27
+ ## Contributing
28
+
29
+ 1. Fork it
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create new Pull Request
34
+
35
+ ## Gem maintainance
36
+
37
+ Maintain `modernizr_rails` gem with `Rake` commands.
38
+
39
+ Update origin modernizr source files.
40
+
41
+ rake update-modernizr
42
+
43
+ Publish gem.
44
+
45
+ rake release
46
+
47
+ ## License
48
+
49
+ Modernizr is dual-licensed under the [BSD and MIT licenses](http://www.modernizr.com/license/).
50
+
51
+ Other parts of gem use MIT license.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
3
+ require File.expand_path('../lib/modernizr-rails/source_file', __FILE__)
4
+
5
+ desc 'Update with Modernizr Library'
6
+ task 'update-modernizr' do
7
+ files = SourceFile.new
8
+ files.fetch
9
+ end
@@ -0,0 +1,11 @@
1
+ require 'modernizr-rails/version'
2
+
3
+ module Modernizr
4
+ module Rails
5
+ if ::Rails.version < '3.1'
6
+ require 'modernizr-rails/railtie'
7
+ else
8
+ require 'modernizr-rails/engine'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ module Modernizr
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Modernizr
2
+ module Rails
3
+ class Railtie < ::Rails::Railtie
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,18 @@
1
+ require 'thor'
2
+
3
+ class SourceFile < Thor
4
+ include Thor::Actions
5
+
6
+ desc 'fetch source files', 'fetch source files from GitHub'
7
+ def fetch
8
+ self.destination_root = 'vendor/assets'
9
+ remote = 'https://raw.github.com/Modernizr/Modernizr'
10
+ get "#{remote}/master/modernizr.js", 'javascripts/modernizr.js'
11
+ inside destination_root do
12
+ version = File.read('javascripts/modernizr.js').match(/version\s=\s'([\d|\.]+)'/)[1]
13
+ gsub_file '../../lib/modernizr-rails/version.rb', /VERSION\s=\s'(\d|\.)+'$/ do |match|
14
+ %Q{VERSION = '#{version}'}
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,6 @@
1
+ module Modernizr
2
+ module Rails
3
+ VERSION = '2.5.3'
4
+ MODERNIZR_VERSION = '2.5.3'
5
+ end
6
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/modernizr-rails/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ['Tse-Ching Ho']
6
+ gem.email = ['tsechingho@gmail.com']
7
+ gem.description = %q{Modernizr is a JavaScript library allowing you to use CSS3 & HTML5 while maintaining control over unsupported browsers. This gem integrates Modernizr with Rails asset pipeline for easy of use.}
8
+ gem.summary = %q{Integrate Modernizr javascript library with Rails asset pipeline}
9
+ gem.homepage = 'https://github.com/tsechingho/modernizr-rails'
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = 'modernizr_rails'
15
+ gem.require_paths = ['lib']
16
+ gem.version = Modernizr::Rails::VERSION
17
+
18
+ gem.add_dependency 'railties', '~> 3.0'
19
+ gem.add_dependency 'thor', '~> 0.14'
20
+ gem.add_development_dependency 'bundler', '~> 1.0'
21
+ gem.add_development_dependency 'rails', '~> 3.0'
22
+ gem.add_development_dependency 'sass', '~> 3.1'
23
+ end
@@ -0,0 +1,1313 @@
1
+ /*!
2
+ * Modernizr v2.5.3
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/
7
+ */
8
+
9
+ /*
10
+ * Modernizr tests which native CSS3 and HTML5 features are available in
11
+ * the current UA and makes the results available to you in two ways:
12
+ * as properties on a global Modernizr object, and as classes on the
13
+ * <html> element. This information allows you to progressively enhance
14
+ * your pages with a granular level of control over the experience.
15
+ *
16
+ * Modernizr has an optional (not included) conditional resource loader
17
+ * called Modernizr.load(), based on Yepnope.js (yepnopejs.com).
18
+ * To get a build that includes Modernizr.load(), as well as choosing
19
+ * which tests to include, go to www.modernizr.com/download/
20
+ *
21
+ * Authors Faruk Ates, Paul Irish, Alex Sexton
22
+ * Contributors Ryan Seddon, Ben Alman
23
+ */
24
+
25
+ window.Modernizr = (function( window, document, undefined ) {
26
+
27
+ var version = '2.5.3',
28
+
29
+ Modernizr = {},
30
+
31
+ /*>>cssclasses*/
32
+ // option for enabling the HTML classes to be added
33
+ enableClasses = true,
34
+ /*>>cssclasses*/
35
+
36
+ docElement = document.documentElement,
37
+
38
+ /**
39
+ * Create our "modernizr" element that we do most feature tests on.
40
+ */
41
+ mod = 'modernizr',
42
+ modElem = document.createElement(mod),
43
+ mStyle = modElem.style,
44
+
45
+ /**
46
+ * Create the input element for various Web Forms feature tests.
47
+ */
48
+ inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ ,
49
+
50
+ /*>>smile*/
51
+ smile = ':)',
52
+ /*>>smile*/
53
+
54
+ toString = {}.toString,
55
+
56
+ // TODO :: make the prefixes more granular
57
+ /*>>prefixes*/
58
+ // List of property values to set for css tests. See ticket #21
59
+ prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
60
+ /*>>prefixes*/
61
+
62
+ /*>>domprefixes*/
63
+ // Following spec is to expose vendor-specific style properties as:
64
+ // elem.style.WebkitBorderRadius
65
+ // and the following would be incorrect:
66
+ // elem.style.webkitBorderRadius
67
+
68
+ // Webkit ghosts their properties in lowercase but Opera & Moz do not.
69
+ // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
70
+ // erik.eae.net/archives/2008/03/10/21.48.10/
71
+
72
+ // More here: github.com/Modernizr/Modernizr/issues/issue/21
73
+ omPrefixes = 'Webkit Moz O ms',
74
+
75
+ cssomPrefixes = omPrefixes.split(' '),
76
+
77
+ domPrefixes = omPrefixes.toLowerCase().split(' '),
78
+ /*>>domprefixes*/
79
+
80
+ /*>>ns*/
81
+ ns = {'svg': 'http://www.w3.org/2000/svg'},
82
+ /*>>ns*/
83
+
84
+ tests = {},
85
+ inputs = {},
86
+ attrs = {},
87
+
88
+ classes = [],
89
+
90
+ slice = classes.slice,
91
+
92
+ featureName, // used in testing loop
93
+
94
+
95
+ /*>>teststyles*/
96
+ // Inject element with style element and some CSS rules
97
+ injectElementWithStyles = function( rule, callback, nodes, testnames ) {
98
+
99
+ var style, ret, node,
100
+ 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 ? body : document.createElement('body');
105
+
106
+ 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-- ) {
110
+ node = document.createElement('div');
111
+ node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
112
+ div.appendChild(node);
113
+ }
114
+ }
115
+
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>', rule, '</style>'].join('');
122
+ 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;
126
+ fakeBody.appendChild(div);
127
+ if(!body){
128
+ //avoid crashing IE8, if background image is used
129
+ fakeBody.style.background = "";
130
+ docElement.appendChild(fakeBody);
131
+ }
132
+
133
+ ret = callback(div, rule);
134
+ // If this is done after page load we don't want to remove the body so check if body exists
135
+ !body ? fakeBody.parentNode.removeChild(fakeBody) : div.parentNode.removeChild(div);
136
+
137
+ return !!ret;
138
+
139
+ },
140
+ /*>>teststyles*/
141
+
142
+ /*>>mq*/
143
+ // adapted from matchMedia polyfill
144
+ // by Scott Jehl and Paul Irish
145
+ // gist.github.com/786768
146
+ testMediaQuery = function( mq ) {
147
+
148
+ var matchMedia = window.matchMedia || window.msMatchMedia;
149
+ if ( matchMedia ) {
150
+ return matchMedia(mq).matches;
151
+ }
152
+
153
+ var bool;
154
+
155
+ injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {
156
+ bool = (window.getComputedStyle ?
157
+ getComputedStyle(node, null) :
158
+ node.currentStyle)['position'] == 'absolute';
159
+ });
160
+
161
+ return bool;
162
+
163
+ },
164
+ /*>>mq*/
165
+
166
+
167
+ /*>>hasevent*/
168
+ /**
169
+ * isEventSupported determines if a given element supports the given event
170
+ * function from yura.thinkweb2.com/isEventSupported/
171
+ */
172
+ isEventSupported = (function() {
173
+
174
+ var TAGNAMES = {
175
+ 'select': 'input', 'change': 'input',
176
+ 'submit': 'form', 'reset': 'form',
177
+ 'error': 'img', 'load': 'img', 'abort': 'img'
178
+ };
179
+
180
+ function isEventSupported( eventName, element ) {
181
+
182
+ element = element || document.createElement(TAGNAMES[eventName] || 'div');
183
+ eventName = 'on' + eventName;
184
+
185
+ // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
186
+ var isSupported = eventName in element;
187
+
188
+ if ( !isSupported ) {
189
+ // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
190
+ if ( !element.setAttribute ) {
191
+ element = document.createElement('div');
192
+ }
193
+ if ( element.setAttribute && element.removeAttribute ) {
194
+ element.setAttribute(eventName, '');
195
+ isSupported = is(element[eventName], 'function');
196
+
197
+ // If property was created, "remove it" (by setting value to `undefined`)
198
+ if ( !is(element[eventName], 'undefined') ) {
199
+ element[eventName] = undefined;
200
+ }
201
+ element.removeAttribute(eventName);
202
+ }
203
+ }
204
+
205
+ element = null;
206
+ return isSupported;
207
+ }
208
+ return isEventSupported;
209
+ })(),
210
+ /*>>hasevent*/
211
+
212
+ // TODO :: Add flag for hasownprop ? didn't last time
213
+
214
+ // hasOwnProperty shim by kangax needed for Safari 2.0 support
215
+ _hasOwnProperty = ({}).hasOwnProperty, hasOwnProperty;
216
+
217
+ if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
218
+ hasOwnProperty = function (object, property) {
219
+ return _hasOwnProperty.call(object, property);
220
+ };
221
+ }
222
+ else {
223
+ hasOwnProperty = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
224
+ return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
225
+ };
226
+ }
227
+
228
+ // TODO :: Add function proto bind
229
+ // Taken from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js
230
+ // ES-5 15.3.4.5
231
+ // http://es5.github.com/#x15.3.4.5
232
+
233
+ if (!Function.prototype.bind) {
234
+ Function.prototype.bind = function bind(that) {
235
+
236
+ var target = this;
237
+
238
+ if (typeof target != "function") {
239
+ throw new TypeError();
240
+ }
241
+
242
+ var args = slice.call(arguments, 1),
243
+ bound = function () {
244
+
245
+ if (this instanceof bound) {
246
+
247
+ var F = function(){};
248
+ F.prototype = target.prototype;
249
+ var self = new F;
250
+
251
+ var result = target.apply(
252
+ self,
253
+ args.concat(slice.call(arguments))
254
+ );
255
+ if (Object(result) === result) {
256
+ return result;
257
+ }
258
+ return self;
259
+
260
+ } else {
261
+
262
+ return target.apply(
263
+ that,
264
+ args.concat(slice.call(arguments))
265
+ );
266
+
267
+ }
268
+
269
+ };
270
+
271
+ return bound;
272
+ };
273
+ }
274
+
275
+ /**
276
+ * setCss applies given styles to the Modernizr DOM node.
277
+ */
278
+ function setCss( str ) {
279
+ mStyle.cssText = str;
280
+ }
281
+
282
+ /**
283
+ * setCssAll extrapolates all vendor-specific css strings.
284
+ */
285
+ function setCssAll( str1, str2 ) {
286
+ return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
287
+ }
288
+
289
+ /**
290
+ * is returns a boolean for if typeof obj is exactly type.
291
+ */
292
+ function is( obj, type ) {
293
+ return typeof obj === type;
294
+ }
295
+
296
+ /**
297
+ * contains returns a boolean for if substr is found within str.
298
+ */
299
+ function contains( str, substr ) {
300
+ return !!~('' + str).indexOf(substr);
301
+ }
302
+
303
+ /*>>testprop*/
304
+ /**
305
+ * testProps is a generic CSS / DOM property test; if a browser supports
306
+ * a certain property, it won't return undefined for it.
307
+ * A supported CSS property returns empty string when its not yet set.
308
+ */
309
+ function testProps( props, prefixed ) {
310
+ for ( var i in props ) {
311
+ if ( mStyle[ props[i] ] !== undefined ) {
312
+ return prefixed == 'pfx' ? props[i] : true;
313
+ }
314
+ }
315
+ return false;
316
+ }
317
+ /*>>testprop*/
318
+
319
+ // TODO :: add testDOMProps
320
+ /**
321
+ * testDOMProps is a generic DOM property test; if a browser supports
322
+ * a certain property, it won't return undefined for it.
323
+ */
324
+ function testDOMProps( props, obj, elem ) {
325
+ for ( var i in props ) {
326
+ var item = obj[props[i]];
327
+ if ( item !== undefined) {
328
+
329
+ // return the property name as a string
330
+ if (elem === false) return props[i];
331
+
332
+ // let's bind a function
333
+ if (is(item, 'function')){
334
+ // default to autobind unless override
335
+ return item.bind(elem || obj);
336
+ }
337
+
338
+ // return the unbound function or obj or value
339
+ return item;
340
+ }
341
+ }
342
+ return false;
343
+ }
344
+
345
+ /*>>testallprops*/
346
+ /**
347
+ * testPropsAll tests a list of DOM properties we want to check against.
348
+ * We specify literally ALL possible (known and/or likely) properties on
349
+ * the element including the non-vendor prefixed one, for forward-
350
+ * compatibility.
351
+ */
352
+ function testPropsAll( prop, prefixed, elem ) {
353
+
354
+ var ucProp = prop.charAt(0).toUpperCase() + prop.substr(1),
355
+ props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
356
+
357
+ // did they call .prefixed('boxSizing') or are we just testing a prop?
358
+ if(is(prefixed, "string") || is(prefixed, "undefined")) {
359
+ return testProps(props, prefixed);
360
+
361
+ // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
362
+ } else {
363
+ props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
364
+ return testDOMProps(props, prefixed, elem);
365
+ }
366
+ }
367
+ /*>>testallprops*/
368
+
369
+ /*>>testBundle*/
370
+ /**
371
+ * testBundle tests a list of CSS features that require element and style injection.
372
+ * By bundling them together we can reduce the need to touch the DOM multiple times.
373
+ */
374
+ var testBundle = (function( styles, tests ) {
375
+ var style = styles.join(''),
376
+ len = tests.length;
377
+
378
+ injectElementWithStyles(style, function( node, rule ) {
379
+ var style = document.styleSheets[document.styleSheets.length - 1],
380
+ // IE8 will bork if you create a custom build that excludes both fontface and generatedcontent tests.
381
+ // So we check for cssRules and that there is a rule available
382
+ // More here: github.com/Modernizr/Modernizr/issues/288 & github.com/Modernizr/Modernizr/issues/293
383
+ cssText = style ? (style.cssRules && style.cssRules[0] ? style.cssRules[0].cssText : style.cssText || '') : '',
384
+ children = node.childNodes, hash = {};
385
+
386
+ while ( len-- ) {
387
+ hash[children[len].id] = children[len];
388
+ }
389
+
390
+ /*>>touch*/ Modernizr['touch'] = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch || (hash['touch'] && hash['touch'].offsetTop) === 9; /*>>touch*/
391
+ /*>>csstransforms3d*/ Modernizr['csstransforms3d'] = (hash['csstransforms3d'] && hash['csstransforms3d'].offsetLeft) === 9 && hash['csstransforms3d'].offsetHeight === 3; /*>>csstransforms3d*/
392
+ /*>>generatedcontent*/Modernizr['generatedcontent'] = (hash['generatedcontent'] && hash['generatedcontent'].offsetHeight) >= 1; /*>>generatedcontent*/
393
+ /*>>fontface*/ Modernizr['fontface'] = /src/i.test(cssText) &&
394
+ cssText.indexOf(rule.split(' ')[0]) === 0; /*>>fontface*/
395
+ }, len, tests);
396
+
397
+ })([
398
+ // Pass in styles to be injected into document
399
+ /*>>fontface*/ '@font-face {font-family:"font";src:url("https://")}' /*>>fontface*/
400
+
401
+ /*>>touch*/ ,['@media (',prefixes.join('touch-enabled),('),mod,')',
402
+ '{#touch{top:9px;position:absolute}}'].join('') /*>>touch*/
403
+
404
+ /*>>csstransforms3d*/ ,['@media (',prefixes.join('transform-3d),('),mod,')',
405
+ '{#csstransforms3d{left:9px;position:absolute;height:3px;}}'].join('')/*>>csstransforms3d*/
406
+
407
+ /*>>generatedcontent*/,['#generatedcontent:after{content:"',smile,'";visibility:hidden}'].join('') /*>>generatedcontent*/
408
+ ],
409
+ [
410
+ /*>>fontface*/ 'fontface' /*>>fontface*/
411
+ /*>>touch*/ ,'touch' /*>>touch*/
412
+ /*>>csstransforms3d*/ ,'csstransforms3d' /*>>csstransforms3d*/
413
+ /*>>generatedcontent*/,'generatedcontent' /*>>generatedcontent*/
414
+
415
+ ]);/*>>testBundle*/
416
+
417
+
418
+ /**
419
+ * Tests
420
+ * -----
421
+ */
422
+
423
+ // The *new* flexbox
424
+ // dev.w3.org/csswg/css3-flexbox
425
+
426
+ tests['flexbox'] = function() {
427
+ return testPropsAll('flexOrder');
428
+ };
429
+
430
+ // The *old* flexbox
431
+ // www.w3.org/TR/2009/WD-css3-flexbox-20090723/
432
+
433
+ tests['flexbox-legacy'] = function() {
434
+ return testPropsAll('boxDirection');
435
+ };
436
+
437
+ // On the S60 and BB Storm, getContext exists, but always returns undefined
438
+ // so we actually have to call getContext() to verify
439
+ // github.com/Modernizr/Modernizr/issues/issue/97/
440
+
441
+ tests['canvas'] = function() {
442
+ var elem = document.createElement('canvas');
443
+ return !!(elem.getContext && elem.getContext('2d'));
444
+ };
445
+
446
+ tests['canvastext'] = function() {
447
+ return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
448
+ };
449
+
450
+ // this test initiates a new webgl context.
451
+ // webk.it/70117 is tracking a legit feature detect proposal
452
+
453
+ tests['webgl'] = function() {
454
+ try {
455
+ var canvas = document.createElement('canvas'),
456
+ ret;
457
+ ret = !!(window.WebGLRenderingContext && (canvas.getContext('experimental-webgl') || canvas.getContext('webgl')));
458
+ canvas = undefined;
459
+ } catch (e){
460
+ ret = false;
461
+ }
462
+ return ret;
463
+ };
464
+
465
+ /*
466
+ * The Modernizr.touch test only indicates if the browser supports
467
+ * touch events, which does not necessarily reflect a touchscreen
468
+ * device, as evidenced by tablets running Windows 7 or, alas,
469
+ * the Palm Pre / WebOS (touch) phones.
470
+ *
471
+ * Additionally, Chrome (desktop) used to lie about its support on this,
472
+ * but that has since been rectified: crbug.com/36415
473
+ *
474
+ * We also test for Firefox 4 Multitouch Support.
475
+ *
476
+ * For more info, see: modernizr.github.com/Modernizr/touch.html
477
+ */
478
+
479
+ tests['touch'] = function() {
480
+ return Modernizr['touch'];
481
+ };
482
+
483
+ /**
484
+ * geolocation tests for the new Geolocation API specification.
485
+ * This test is a standards compliant-only test; for more complete
486
+ * testing, including a Google Gears fallback, please see:
487
+ * code.google.com/p/geo-location-javascript/
488
+ * or view a fallback solution using google's geo API:
489
+ * gist.github.com/366184
490
+ */
491
+ tests['geolocation'] = function() {
492
+ return !!navigator.geolocation;
493
+ };
494
+
495
+ // Per 1.6:
496
+ // This used to be Modernizr.crosswindowmessaging but the longer
497
+ // name has been deprecated in favor of a shorter and property-matching one.
498
+ // The old API is still available in 1.6, but as of 2.0 will throw a warning,
499
+ // and in the first release thereafter disappear entirely.
500
+ tests['postmessage'] = function() {
501
+ return !!window.postMessage;
502
+ };
503
+
504
+
505
+ // Chrome incognito mode used to throw an exception when using openDatabase
506
+ // It doesn't anymore.
507
+ tests['websqldatabase'] = function() {
508
+ return !!window.openDatabase;
509
+ };
510
+
511
+ // Vendors had inconsistent prefixing with the experimental Indexed DB:
512
+ // - Webkit's implementation is accessible through webkitIndexedDB
513
+ // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB
514
+ // For speed, we don't test the legacy (and beta-only) indexedDB
515
+ tests['indexedDB'] = function() {
516
+ return !!testPropsAll("indexedDB",window);
517
+ };
518
+
519
+ // documentMode logic from YUI to filter out IE8 Compat Mode
520
+ // which false positives.
521
+ tests['hashchange'] = function() {
522
+ return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);
523
+ };
524
+
525
+ // Per 1.6:
526
+ // This used to be Modernizr.historymanagement but the longer
527
+ // name has been deprecated in favor of a shorter and property-matching one.
528
+ // The old API is still available in 1.6, but as of 2.0 will throw a warning,
529
+ // and in the first release thereafter disappear entirely.
530
+ tests['history'] = function() {
531
+ return !!(window.history && history.pushState);
532
+ };
533
+
534
+ tests['draganddrop'] = function() {
535
+ var div = document.createElement('div');
536
+ return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
537
+ };
538
+
539
+ // FIXME: Once FF10 is sunsetted, we can drop prefixed MozWebSocket
540
+ // bugzil.la/695635
541
+ tests['websockets'] = function() {
542
+ for ( var i = -1, len = cssomPrefixes.length; ++i < len; ){
543
+ if ( window[cssomPrefixes[i] + 'WebSocket'] ){
544
+ return true;
545
+ }
546
+ }
547
+ return 'WebSocket' in window;
548
+ };
549
+
550
+
551
+ // css-tricks.com/rgba-browser-support/
552
+ tests['rgba'] = function() {
553
+ // Set an rgba() color and check the returned value
554
+
555
+ setCss('background-color:rgba(150,255,150,.5)');
556
+
557
+ return contains(mStyle.backgroundColor, 'rgba');
558
+ };
559
+
560
+ tests['hsla'] = function() {
561
+ // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally,
562
+ // except IE9 who retains it as hsla
563
+
564
+ setCss('background-color:hsla(120,40%,100%,.5)');
565
+
566
+ return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');
567
+ };
568
+
569
+ tests['multiplebgs'] = function() {
570
+ // Setting multiple images AND a color on the background shorthand property
571
+ // and then querying the style.background property value for the number of
572
+ // occurrences of "url(" is a reliable method for detecting ACTUAL support for this!
573
+
574
+ setCss('background:url(https://),url(https://),red url(https://)');
575
+
576
+ // If the UA supports multiple backgrounds, there should be three occurrences
577
+ // of the string "url(" in the return value for elemStyle.background
578
+
579
+ return /(url\s*\(.*?){3}/.test(mStyle.background);
580
+ };
581
+
582
+
583
+ // In testing support for a given CSS property, it's legit to test:
584
+ // `elem.style[styleName] !== undefined`
585
+ // If the property is supported it will return an empty string,
586
+ // if unsupported it will return undefined.
587
+
588
+ // We'll take advantage of this quick test and skip setting a style
589
+ // on our modernizr element, but instead just testing undefined vs
590
+ // empty string.
591
+
592
+
593
+ tests['backgroundsize'] = function() {
594
+ return testPropsAll('backgroundSize');
595
+ };
596
+
597
+ tests['borderimage'] = function() {
598
+ return testPropsAll('borderImage');
599
+ };
600
+
601
+
602
+ // Super comprehensive table about all the unique implementations of
603
+ // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance
604
+
605
+ tests['borderradius'] = function() {
606
+ return testPropsAll('borderRadius');
607
+ };
608
+
609
+ // WebOS unfortunately false positives on this test.
610
+ tests['boxshadow'] = function() {
611
+ return testPropsAll('boxShadow');
612
+ };
613
+
614
+ // FF3.0 will false positive on this test
615
+ tests['textshadow'] = function() {
616
+ return document.createElement('div').style.textShadow === '';
617
+ };
618
+
619
+
620
+ tests['opacity'] = function() {
621
+ // Browsers that actually have CSS Opacity implemented have done so
622
+ // according to spec, which means their return values are within the
623
+ // range of [0.0,1.0] - including the leading zero.
624
+
625
+ setCssAll('opacity:.55');
626
+
627
+ // The non-literal . in this regex is intentional:
628
+ // German Chrome returns this value as 0,55
629
+ // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632
630
+ return /^0.55$/.test(mStyle.opacity);
631
+ };
632
+
633
+
634
+ // Note, Android < 4 will pass this test, but can only animate
635
+ // a single property at a time
636
+ // daneden.me/2011/12/putting-up-with-androids-bullshit/
637
+ tests['cssanimations'] = function() {
638
+ return testPropsAll('animationName');
639
+ };
640
+
641
+
642
+ tests['csscolumns'] = function() {
643
+ return testPropsAll('columnCount');
644
+ };
645
+
646
+
647
+ tests['cssgradients'] = function() {
648
+ /**
649
+ * For CSS Gradients syntax, please see:
650
+ * webkit.org/blog/175/introducing-css-gradients/
651
+ * developer.mozilla.org/en/CSS/-moz-linear-gradient
652
+ * developer.mozilla.org/en/CSS/-moz-radial-gradient
653
+ * dev.w3.org/csswg/css3-images/#gradients-
654
+ */
655
+
656
+ var str1 = 'background-image:',
657
+ str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
658
+ str3 = 'linear-gradient(left top,#9f9, white);';
659
+
660
+ setCss(
661
+ // legacy webkit syntax (FIXME: remove when syntax not in use anymore)
662
+ (str1 + '-webkit- '.split(' ').join(str2 + str1)
663
+ // standard syntax // trailing 'background-image:'
664
+ + prefixes.join(str3 + str1)).slice(0, -str1.length)
665
+ );
666
+
667
+ return contains(mStyle.backgroundImage, 'gradient');
668
+ };
669
+
670
+
671
+ tests['cssreflections'] = function() {
672
+ return testPropsAll('boxReflect');
673
+ };
674
+
675
+
676
+ tests['csstransforms'] = function() {
677
+ return !!testPropsAll('transform');
678
+ };
679
+
680
+
681
+ tests['csstransforms3d'] = function() {
682
+
683
+ var ret = !!testPropsAll('perspective');
684
+
685
+ // Webkit's 3D transforms are passed off to the browser's own graphics renderer.
686
+ // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in
687
+ // some conditions. As a result, Webkit typically recognizes the syntax but
688
+ // will sometimes throw a false positive, thus we must do a more thorough check:
689
+ if ( ret && 'webkitPerspective' in docElement.style ) {
690
+
691
+ // Webkit allows this media query to succeed only if the feature is enabled.
692
+ // `@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-ms-transform-3d),(-webkit-transform-3d),(modernizr){ ... }`
693
+ ret = Modernizr['csstransforms3d'];
694
+ }
695
+ return ret;
696
+ };
697
+
698
+
699
+ tests['csstransitions'] = function() {
700
+ return testPropsAll('transition');
701
+ };
702
+
703
+
704
+ /*>>fontface*/
705
+ // @font-face detection routine by Diego Perini
706
+ // javascript.nwbox.com/CSSSupport/
707
+
708
+ // false positives in WebOS: github.com/Modernizr/Modernizr/issues/342
709
+ tests['fontface'] = function() {
710
+ return Modernizr['fontface'];
711
+ };
712
+ /*>>fontface*/
713
+
714
+ // CSS generated content detection
715
+ tests['generatedcontent'] = function() {
716
+ return Modernizr['generatedcontent'];
717
+ };
718
+
719
+
720
+
721
+ // These tests evaluate support of the video/audio elements, as well as
722
+ // testing what types of content they support.
723
+ //
724
+ // We're using the Boolean constructor here, so that we can extend the value
725
+ // e.g. Modernizr.video // true
726
+ // Modernizr.video.ogg // 'probably'
727
+ //
728
+ // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
729
+ // thx to NielsLeenheer and zcorpan
730
+
731
+ // Note: in some older browsers, "no" was a return value instead of empty string.
732
+ // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
733
+ // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
734
+
735
+ tests['video'] = function() {
736
+ var elem = document.createElement('video'),
737
+ bool = false;
738
+
739
+ // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
740
+ try {
741
+ if ( bool = !!elem.canPlayType ) {
742
+ bool = new Boolean(bool);
743
+ bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,'');
744
+
745
+ bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,'');
746
+
747
+ bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,'');
748
+ }
749
+
750
+ } catch(e) { }
751
+
752
+ return bool;
753
+ };
754
+
755
+ tests['audio'] = function() {
756
+ var elem = document.createElement('audio'),
757
+ bool = false;
758
+
759
+ try {
760
+ if ( bool = !!elem.canPlayType ) {
761
+ bool = new Boolean(bool);
762
+ bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
763
+ bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,'');
764
+
765
+ // Mimetypes accepted:
766
+ // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
767
+ // bit.ly/iphoneoscodecs
768
+ bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,'');
769
+ bool.m4a = ( elem.canPlayType('audio/x-m4a;') ||
770
+ elem.canPlayType('audio/aac;')) .replace(/^no$/,'');
771
+ }
772
+ } catch(e) { }
773
+
774
+ return bool;
775
+ };
776
+
777
+
778
+ // In FF4, if disabled, window.localStorage should === null.
779
+
780
+ // Normally, we could not test that directly and need to do a
781
+ // `('localStorage' in window) && ` test first because otherwise Firefox will
782
+ // throw bugzil.la/365772 if cookies are disabled
783
+
784
+ // Also in iOS5 Private Browsing mode, attepting to use localStorage.setItem
785
+ // will throw the exception:
786
+ // QUOTA_EXCEEDED_ERRROR DOM Exception 22.
787
+ // Peculiarly, getItem and removeItem calls do not throw.
788
+
789
+ // Because we are forced to try/catch this, we'll go aggressive.
790
+
791
+ // Just FWIW: IE8 Compat mode supports these features completely:
792
+ // www.quirksmode.org/dom/html5.html
793
+ // But IE8 doesn't support either with local files
794
+
795
+ tests['localstorage'] = function() {
796
+ try {
797
+ localStorage.setItem(mod, mod);
798
+ localStorage.removeItem(mod);
799
+ return true;
800
+ } catch(e) {
801
+ return false;
802
+ }
803
+ };
804
+
805
+ tests['sessionstorage'] = function() {
806
+ try {
807
+ sessionStorage.setItem(mod, mod);
808
+ sessionStorage.removeItem(mod);
809
+ return true;
810
+ } catch(e) {
811
+ return false;
812
+ }
813
+ };
814
+
815
+
816
+ tests['webworkers'] = function() {
817
+ return !!window.Worker;
818
+ };
819
+
820
+
821
+ tests['applicationcache'] = function() {
822
+ return !!window.applicationCache;
823
+ };
824
+
825
+
826
+ // Thanks to Erik Dahlstrom
827
+ tests['svg'] = function() {
828
+ return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
829
+ };
830
+
831
+ // specifically for SVG inline in HTML, not within XHTML
832
+ // test page: paulirish.com/demo/inline-svg
833
+ tests['inlinesvg'] = function() {
834
+ var div = document.createElement('div');
835
+ div.innerHTML = '<svg/>';
836
+ return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
837
+ };
838
+
839
+ // SVG SMIL animation
840
+ tests['smil'] = function() {
841
+ return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));
842
+ };
843
+
844
+ // This test is only for clip paths in SVG proper, not clip paths on HTML content
845
+ // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg
846
+
847
+ // However read the comments to dig into applying SVG clippaths to HTML content here:
848
+ // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491
849
+ tests['svgclippaths'] = function() {
850
+ return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
851
+ };
852
+
853
+ /*>>webforms*/
854
+ // input features and input types go directly onto the ret object, bypassing the tests loop.
855
+ // Hold this guy to execute in a moment.
856
+ function webforms() {
857
+ /*>>input*/
858
+ // Run through HTML5's new input attributes to see if the UA understands any.
859
+ // We're using f which is the <input> element created early on
860
+ // Mike Taylr has created a comprehensive resource for testing these attributes
861
+ // when applied to all input types:
862
+ // miketaylr.com/code/input-type-attr.html
863
+ // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
864
+
865
+ // Only input placeholder is tested while textarea's placeholder is not.
866
+ // Currently Safari 4 and Opera 11 have support only for the input placeholder
867
+ // Both tests are available in feature-detects/forms-placeholder.js
868
+ Modernizr['input'] = (function( props ) {
869
+ for ( var i = 0, len = props.length; i < len; i++ ) {
870
+ attrs[ props[i] ] = !!(props[i] in inputElem);
871
+ }
872
+ if (attrs.list){
873
+ // safari false positive's on datalist: webk.it/74252
874
+ // see also github.com/Modernizr/Modernizr/issues/146
875
+ attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);
876
+ }
877
+ return attrs;
878
+ })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));
879
+ /*>>input*/
880
+
881
+ /*>>inputtypes*/
882
+ // Run through HTML5's new input types to see if the UA understands any.
883
+ // This is put behind the tests runloop because it doesn't return a
884
+ // true/false like all the other tests; instead, it returns an object
885
+ // containing each input type with its corresponding true/false value
886
+
887
+ // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/
888
+ Modernizr['inputtypes'] = (function(props) {
889
+
890
+ for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
891
+
892
+ inputElem.setAttribute('type', inputElemType = props[i]);
893
+ bool = inputElem.type !== 'text';
894
+
895
+ // We first check to see if the type we give it sticks..
896
+ // If the type does, we feed it a textual value, which shouldn't be valid.
897
+ // If the value doesn't stick, we know there's input sanitization which infers a custom UI
898
+ if ( bool ) {
899
+
900
+ inputElem.value = smile;
901
+ inputElem.style.cssText = 'position:absolute;visibility:hidden;';
902
+
903
+ if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {
904
+
905
+ docElement.appendChild(inputElem);
906
+ defaultView = document.defaultView;
907
+
908
+ // Safari 2-4 allows the smiley as a value, despite making a slider
909
+ bool = defaultView.getComputedStyle &&
910
+ defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
911
+ // Mobile android web browser has false positive, so must
912
+ // check the height to see if the widget is actually there.
913
+ (inputElem.offsetHeight !== 0);
914
+
915
+ docElement.removeChild(inputElem);
916
+
917
+ } else if ( /^(search|tel)$/.test(inputElemType) ){
918
+ // Spec doesnt define any special parsing or detectable UI
919
+ // behaviors so we pass these through as true
920
+
921
+ // Interestingly, opera fails the earlier test, so it doesn't
922
+ // even make it here.
923
+
924
+ } else if ( /^(url|email)$/.test(inputElemType) ) {
925
+ // Real url and email support comes with prebaked validation.
926
+ bool = inputElem.checkValidity && inputElem.checkValidity() === false;
927
+
928
+ } else if ( /^color$/.test(inputElemType) ) {
929
+ // chuck into DOM and force reflow for Opera bug in 11.00
930
+ // github.com/Modernizr/Modernizr/issues#issue/159
931
+ docElement.appendChild(inputElem);
932
+ docElement.offsetWidth;
933
+ bool = inputElem.value != smile;
934
+ docElement.removeChild(inputElem);
935
+
936
+ } else {
937
+ // If the upgraded input compontent rejects the :) text, we got a winner
938
+ bool = inputElem.value != smile;
939
+ }
940
+ }
941
+
942
+ inputs[ props[i] ] = !!bool;
943
+ }
944
+ return inputs;
945
+ })('search tel url email datetime date month week time datetime-local number range color'.split(' '));
946
+ /*>>inputtypes*/
947
+ }
948
+ /*>>webforms*/
949
+
950
+
951
+ // End of test definitions
952
+ // -----------------------
953
+
954
+
955
+
956
+ // Run through all tests and detect their support in the current UA.
957
+ // todo: hypothetically we could be doing an array of tests and use a basic loop here.
958
+ for ( var feature in tests ) {
959
+ if ( hasOwnProperty(tests, feature) ) {
960
+ // run the test, throw the return value into the Modernizr,
961
+ // then based on that boolean, define an appropriate className
962
+ // and push it into an array of classes we'll join later.
963
+ featureName = feature.toLowerCase();
964
+ Modernizr[featureName] = tests[feature]();
965
+
966
+ classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
967
+ }
968
+ }
969
+
970
+ /*>>webforms*/
971
+ // input tests need to run.
972
+ Modernizr.input || webforms();
973
+ /*>>webforms*/
974
+
975
+
976
+ /*>>addtest*/
977
+ /**
978
+ * addTest allows the user to define their own feature tests
979
+ * the result will be added onto the Modernizr object,
980
+ * as well as an appropriate className set on the html element
981
+ *
982
+ * @param feature - String naming the feature
983
+ * @param test - Function returning true if feature is supported, false if not
984
+ */
985
+ Modernizr.addTest = function ( feature, test ) {
986
+ if ( typeof feature == 'object' ) {
987
+ for ( var key in feature ) {
988
+ if ( hasOwnProperty( feature, key ) ) {
989
+ Modernizr.addTest( key, feature[ key ] );
990
+ }
991
+ }
992
+ } else {
993
+
994
+ feature = feature.toLowerCase();
995
+
996
+ if ( Modernizr[feature] !== undefined ) {
997
+ // we're going to quit if you're trying to overwrite an existing test
998
+ // if we were to allow it, we'd do this:
999
+ // var re = new RegExp("\\b(no-)?" + feature + "\\b");
1000
+ // docElement.className = docElement.className.replace( re, '' );
1001
+ // but, no rly, stuff 'em.
1002
+ return Modernizr;
1003
+ }
1004
+
1005
+ test = typeof test == 'function' ? test() : test;
1006
+
1007
+ docElement.className += ' ' + (test ? '' : 'no-') + feature;
1008
+ Modernizr[feature] = test;
1009
+
1010
+ }
1011
+
1012
+ return Modernizr; // allow chaining.
1013
+ };
1014
+ /*>>addtest*/
1015
+
1016
+
1017
+ // Reset modElem.cssText to nothing to reduce memory footprint.
1018
+ setCss('');
1019
+ modElem = inputElem = null;
1020
+
1021
+ /*>>shiv*/
1022
+ /*! HTML5 Shiv v3.4 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */
1023
+ ;(function(window, document) {
1024
+
1025
+ /** Preset options */
1026
+ var options = window.html5 || {};
1027
+
1028
+ /** Used to skip problem elements */
1029
+ var reSkip = /^<|^(?:button|form|map|select|textarea)$/i;
1030
+
1031
+ /** Detect whether the browser supports default html5 styles */
1032
+ var supportsHtml5Styles;
1033
+
1034
+ /** Detect whether the browser supports unknown elements */
1035
+ var supportsUnknownElements;
1036
+
1037
+ (function() {
1038
+ var a = document.createElement('a');
1039
+
1040
+ a.innerHTML = '<xyz></xyz>';
1041
+
1042
+ //if the hidden property is implemented we can assume, that the browser supports HTML5 Styles
1043
+ supportsHtml5Styles = ('hidden' in a);
1044
+ supportsUnknownElements = a.childNodes.length == 1 || (function() {
1045
+ // assign a false positive if unable to shiv
1046
+ try {
1047
+ (document.createElement)('a');
1048
+ } catch(e) {
1049
+ return true;
1050
+ }
1051
+ var frag = document.createDocumentFragment();
1052
+ return (
1053
+ typeof frag.cloneNode == 'undefined' ||
1054
+ typeof frag.createDocumentFragment == 'undefined' ||
1055
+ typeof frag.createElement == 'undefined'
1056
+ );
1057
+ }());
1058
+
1059
+ }());
1060
+
1061
+ /*--------------------------------------------------------------------------*/
1062
+
1063
+ /**
1064
+ * Creates a style sheet with the given CSS text and adds it to the document.
1065
+ * @private
1066
+ * @param {Document} ownerDocument The document.
1067
+ * @param {String} cssText The CSS text.
1068
+ * @returns {StyleSheet} The style element.
1069
+ */
1070
+ function addStyleSheet(ownerDocument, cssText) {
1071
+ var p = ownerDocument.createElement('p'),
1072
+ parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
1073
+
1074
+ p.innerHTML = 'x<style>' + cssText + '</style>';
1075
+ return parent.insertBefore(p.lastChild, parent.firstChild);
1076
+ }
1077
+
1078
+ /**
1079
+ * Returns the value of `html5.elements` as an array.
1080
+ * @private
1081
+ * @returns {Array} An array of shived element node names.
1082
+ */
1083
+ function getElements() {
1084
+ var elements = html5.elements;
1085
+ return typeof elements == 'string' ? elements.split(' ') : elements;
1086
+ }
1087
+
1088
+ /**
1089
+ * Shivs the `createElement` and `createDocumentFragment` methods of the document.
1090
+ * @private
1091
+ * @param {Document|DocumentFragment} ownerDocument The document.
1092
+ */
1093
+ function shivMethods(ownerDocument) {
1094
+ var cache = {},
1095
+ docCreateElement = ownerDocument.createElement,
1096
+ docCreateFragment = ownerDocument.createDocumentFragment,
1097
+ frag = docCreateFragment();
1098
+
1099
+
1100
+ ownerDocument.createElement = function(nodeName) {
1101
+ // Avoid adding some elements to fragments in IE < 9 because
1102
+ // * Attributes like `name` or `type` cannot be set/changed once an element
1103
+ // is inserted into a document/fragment
1104
+ // * Link elements with `src` attributes that are inaccessible, as with
1105
+ // a 403 response, will cause the tab/window to crash
1106
+ // * Script elements appended to fragments will execute when their `src`
1107
+ // or `text` property is set
1108
+ var node = (cache[nodeName] || (cache[nodeName] = docCreateElement(nodeName))).cloneNode();
1109
+ return html5.shivMethods && node.canHaveChildren && !reSkip.test(nodeName) ? frag.appendChild(node) : node;
1110
+ };
1111
+
1112
+ ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
1113
+ 'var n=f.cloneNode(),c=n.createElement;' +
1114
+ 'h.shivMethods&&(' +
1115
+ // unroll the `createElement` calls
1116
+ getElements().join().replace(/\w+/g, function(nodeName) {
1117
+ cache[nodeName] = docCreateElement(nodeName);
1118
+ frag.createElement(nodeName);
1119
+ return 'c("' + nodeName + '")';
1120
+ }) +
1121
+ ');return n}'
1122
+ )(html5, frag);
1123
+ }
1124
+
1125
+ /*--------------------------------------------------------------------------*/
1126
+
1127
+ /**
1128
+ * Shivs the given document.
1129
+ * @memberOf html5
1130
+ * @param {Document} ownerDocument The document to shiv.
1131
+ * @returns {Document} The shived document.
1132
+ */
1133
+ function shivDocument(ownerDocument) {
1134
+ var shived;
1135
+ if (ownerDocument.documentShived) {
1136
+ return ownerDocument;
1137
+ }
1138
+ if (html5.shivCSS && !supportsHtml5Styles) {
1139
+ shived = !!addStyleSheet(ownerDocument,
1140
+ // corrects block display not defined in IE6/7/8/9
1141
+ 'article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}' +
1142
+ // corrects audio display not defined in IE6/7/8/9
1143
+ 'audio{display:none}' +
1144
+ // corrects canvas and video display not defined in IE6/7/8/9
1145
+ 'canvas,video{display:inline-block;*display:inline;*zoom:1}' +
1146
+ // corrects 'hidden' attribute and audio[controls] display not present in IE7/8/9
1147
+ '[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}' +
1148
+ // adds styling not present in IE6/7/8/9
1149
+ 'mark{background:#FF0;color:#000}'
1150
+ );
1151
+ }
1152
+ if (!supportsUnknownElements) {
1153
+ shived = !shivMethods(ownerDocument);
1154
+ }
1155
+ if (shived) {
1156
+ ownerDocument.documentShived = shived;
1157
+ }
1158
+ return ownerDocument;
1159
+ }
1160
+
1161
+ /*--------------------------------------------------------------------------*/
1162
+
1163
+ /**
1164
+ * The `html5` object is exposed so that more elements can be shived and
1165
+ * existing shiving can be detected on iframes.
1166
+ * @type Object
1167
+ * @example
1168
+ *
1169
+ * // options can be changed before the script is included
1170
+ * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
1171
+ */
1172
+ var html5 = {
1173
+
1174
+ /**
1175
+ * An array or space separated string of node names of the elements to shiv.
1176
+ * @memberOf html5
1177
+ * @type Array|String
1178
+ */
1179
+ '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',
1180
+
1181
+ /**
1182
+ * A flag to indicate that the HTML5 style sheet should be inserted.
1183
+ * @memberOf html5
1184
+ * @type Boolean
1185
+ */
1186
+ 'shivCSS': !(options.shivCSS === false),
1187
+
1188
+ /**
1189
+ * A flag to indicate that the document's `createElement` and `createDocumentFragment`
1190
+ * methods should be overwritten.
1191
+ * @memberOf html5
1192
+ * @type Boolean
1193
+ */
1194
+ 'shivMethods': !(options.shivMethods === false),
1195
+
1196
+ /**
1197
+ * A string to describe the type of `html5` object ("default" or "default print").
1198
+ * @memberOf html5
1199
+ * @type String
1200
+ */
1201
+ 'type': 'default',
1202
+ // shivs the document according to the specified `html5` object options
1203
+ 'shivDocument': shivDocument
1204
+ };
1205
+
1206
+ /*--------------------------------------------------------------------------*/
1207
+
1208
+ // expose html5
1209
+ window.html5 = html5;
1210
+
1211
+ // shiv the document
1212
+ shivDocument(document);
1213
+
1214
+ }(this, document));
1215
+ /*>>shiv*/
1216
+
1217
+ // Assign private properties to the return object with prefix
1218
+ Modernizr._version = version;
1219
+
1220
+ // expose these for the plugin API. Look in the source for how to join() them against your input
1221
+ /*>>prefixes*/
1222
+ Modernizr._prefixes = prefixes;
1223
+ /*>>prefixes*/
1224
+ /*>>domprefixes*/
1225
+ Modernizr._domPrefixes = domPrefixes;
1226
+ Modernizr._cssomPrefixes = cssomPrefixes;
1227
+ /*>>domprefixes*/
1228
+
1229
+ /*>>mq*/
1230
+ // Modernizr.mq tests a given media query, live against the current state of the window
1231
+ // A few important notes:
1232
+ // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false
1233
+ // * A max-width or orientation query will be evaluated against the current state, which may change later.
1234
+ // * You must specify values. Eg. If you are testing support for the min-width media query use:
1235
+ // Modernizr.mq('(min-width:0)')
1236
+ // usage:
1237
+ // Modernizr.mq('only screen and (max-width:768)')
1238
+ Modernizr.mq = testMediaQuery;
1239
+ /*>>mq*/
1240
+
1241
+ /*>>hasevent*/
1242
+ // Modernizr.hasEvent() detects support for a given event, with an optional element to test on
1243
+ // Modernizr.hasEvent('gesturestart', elem)
1244
+ Modernizr.hasEvent = isEventSupported;
1245
+ /*>>hasevent*/
1246
+
1247
+ /*>>testprop*/
1248
+ // Modernizr.testProp() investigates whether a given style property is recognized
1249
+ // Note that the property names must be provided in the camelCase variant.
1250
+ // Modernizr.testProp('pointerEvents')
1251
+ Modernizr.testProp = function(prop){
1252
+ return testProps([prop]);
1253
+ };
1254
+ /*>>testprop*/
1255
+
1256
+ /*>>testallprops*/
1257
+ // Modernizr.testAllProps() investigates whether a given style property,
1258
+ // or any of its vendor-prefixed variants, is recognized
1259
+ // Note that the property names must be provided in the camelCase variant.
1260
+ // Modernizr.testAllProps('boxSizing')
1261
+ Modernizr.testAllProps = testPropsAll;
1262
+ /*>>testallprops*/
1263
+
1264
+
1265
+ /*>>teststyles*/
1266
+ // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards
1267
+ // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })
1268
+ Modernizr.testStyles = injectElementWithStyles;
1269
+ /*>>teststyles*/
1270
+
1271
+
1272
+ /*>>prefixed*/
1273
+ // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input
1274
+ // Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
1275
+
1276
+ // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style.
1277
+ // Return values will also be the camelCase variant, if you need to translate that to hypenated style use:
1278
+ //
1279
+ // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
1280
+
1281
+ // If you're trying to ascertain which transition end event to bind to, you might do something like...
1282
+ //
1283
+ // var transEndEventNames = {
1284
+ // 'WebkitTransition' : 'webkitTransitionEnd',
1285
+ // 'MozTransition' : 'transitionend',
1286
+ // 'OTransition' : 'oTransitionEnd',
1287
+ // 'msTransition' : 'MsTransitionEnd',
1288
+ // 'transition' : 'transitionend'
1289
+ // },
1290
+ // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
1291
+
1292
+ Modernizr.prefixed = function(prop, obj, elem){
1293
+ if(!obj) {
1294
+ return testPropsAll(prop, 'pfx');
1295
+ } else {
1296
+ // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
1297
+ return testPropsAll(prop, obj, elem);
1298
+ }
1299
+ };
1300
+ /*>>prefixed*/
1301
+
1302
+
1303
+ /*>>cssclasses*/
1304
+ // Remove "no-js" class from <html> element, if it exists:
1305
+ docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') +
1306
+
1307
+ // Add the new classes to the <html> element.
1308
+ (enableClasses ? ' js ' + classes.join(' ') : '');
1309
+ /*>>cssclasses*/
1310
+
1311
+ return Modernizr;
1312
+
1313
+ })(this, this.document);