61 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolore, quos, voluptate, sunt, in suscipit quibusdam quis dignissimos eligendi repellendus ipsam exercitationem adipisci nostrum fugit accusamus quae cum nisi accusantium eaque.
62 |
63 |
64 |
65 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur, dolore, impedit eveniet necessitatibus voluptate distinctio quam repellendus voluptates voluptatum inventore rem sapiente minus esse saepe iste harum architecto numquam quis vero dignissimos beatae est id libero adipisci enim odio natus commodi explicabo modi similique nesciunt deserunt vel consectetur velit omnis quaerat corrupti. Cumque, perspiciatis, culpa, reprehenderit laboriosam obcaecati deleniti soluta tempora ipsum ipsam iure temporibus dolore modi quidem cum doloribus ex vel suscipit sapiente ut esse optio voluptates molestias natus nostrum illo nihil quisquam facilis hic atque voluptas quae pariatur placeat officia doloremque quia ea recusandae rem iste asperiores iusto debitis quod incidunt id nemo repellendus itaque. Iure, vel, expedita quam repellendus aliquam fugit autem obcaecati libero reiciendis excepturi officia voluptate molestiae quis itaque consequatur nulla ea sunt facilis cupiditate tempora sequi nam in asperiores! Sunt, maxime at id eaque debitis quasi a possimus eveniet eum velit tempore quidem voluptates expedita quibusdam officiis. Ipsum, quaerat, vero, adipisci enim autem inventore eum maiores consectetur culpa molestiae cumque sed qui dolorem. Placeat, quae deleniti molestiae minima cupiditate quaerat sit est perspiciatis error iste. Ratione, minus, commodi, magni laborum doloribus libero ullam quos tenetur quis molestias ipsam consequuntur harum asperiores culpa nostrum omnis.
66 |
67 |
68 |
69 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur, dolore, impedit eveniet necessitatibus voluptate distinctio quam repellendus voluptates voluptatum inventore rem sapiente minus esse saepe iste harum architecto numquam quis vero dignissimos beatae est id libero adipisci enim odio natus commodi explicabo modi similique nesciunt deserunt vel consectetur velit omnis quaerat corrupti. Cumque, perspiciatis, culpa, reprehenderit laboriosam obcaecati deleniti soluta tempora ipsum ipsam iure temporibus dolore modi quidem cum doloribus ex vel suscipit sapiente ut esse optio voluptates molestias natus nostrum illo nihil quisquam facilis hic atque voluptas quae pariatur placeat officia doloremque quia ea recusandae rem iste asperiores iusto debitis quod incidunt id nemo repellendus itaque. Iure, vel, expedita quam repellendus aliquam fugit autem obcaecati libero reiciendis excepturi officia voluptate molestiae quis itaque consequatur nulla ea sunt facilis cupiditate tempora sequi nam in asperiores! Sunt, maxime at id eaque debitis quasi a possimus eveniet eum velit tempore quidem voluptates expedita quibusdam officiis. Ipsum, quaerat, vero, adipisci enim autem inventore eum maiores consectetur culpa molestiae cumque sed qui dolorem. Placeat, quae deleniti molestiae minima cupiditate quaerat sit est perspiciatis error iste. Ratione, minus, commodi, magni laborum doloribus libero ullam quos tenetur quis molestias ipsam consequuntur harum asperiores culpa nostrum omnis.
70 |
71 |
72 |
73 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolore, quos, voluptate, sunt, in suscipit quibusdam quis dignissimos eligendi repellendus ipsam exercitationem adipisci nostrum fugit accusamus quae cum nisi accusantium eaque.
74 |
75 |
76 |
77 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur, dolore, impedit eveniet necessitatibus voluptate distinctio quam repellendus voluptates voluptatum inventore rem sapiente minus esse saepe iste harum architecto numquam quis vero dignissimos beatae est id libero adipisci enim odio natus commodi explicabo modi similique nesciunt deserunt vel consectetur velit omnis quaerat corrupti. Cumque, perspiciatis, culpa, reprehenderit laboriosam obcaecati deleniti soluta tempora ipsum ipsam iure temporibus dolore modi quidem cum doloribus ex vel suscipit sapiente ut esse optio voluptates molestias natus nostrum illo nihil quisquam facilis hic atque voluptas quae pariatur placeat officia doloremque quia ea recusandae rem iste asperiores iusto debitis quod incidunt id nemo repellendus itaque. Iure, vel, expedita quam repellendus aliquam fugit autem obcaecati libero reiciendis excepturi officia voluptate molestiae quis itaque consequatur nulla ea sunt facilis cupiditate tempora sequi nam in asperiores! Sunt, maxime at id eaque debitis quasi a possimus eveniet eum velit tempore quidem voluptates expedita quibusdam officiis. Ipsum, quaerat, vero, adipisci enim autem inventore eum maiores consectetur culpa molestiae cumque sed qui dolorem. Placeat, quae deleniti molestiae minima cupiditate quaerat sit est perspiciatis error iste. Ratione, minus, commodi, magni laborum doloribus libero ullam quos tenetur quis molestias ipsam consequuntur harum asperiores culpa nostrum omnis.
78 |
79 |
80 |
81 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur, dolore, impedit eveniet necessitatibus voluptate distinctio quam repellendus voluptates voluptatum inventore rem sapiente minus esse saepe iste harum architecto numquam quis vero dignissimos beatae est id libero adipisci enim odio natus commodi explicabo modi similique nesciunt deserunt vel consectetur velit omnis quaerat corrupti. Cumque, perspiciatis, culpa, reprehenderit laboriosam obcaecati deleniti soluta tempora ipsum ipsam iure temporibus dolore modi quidem cum doloribus ex vel suscipit sapiente ut esse optio voluptates molestias natus nostrum illo nihil quisquam facilis hic atque voluptas quae pariatur placeat officia doloremque quia ea recusandae rem iste asperiores iusto debitis quod incidunt id nemo repellendus itaque. Iure, vel, expedita quam repellendus aliquam fugit autem obcaecati libero reiciendis excepturi officia voluptate molestiae quis itaque consequatur nulla ea sunt facilis cupiditate tempora sequi nam in asperiores! Sunt, maxime at id eaque debitis quasi a possimus eveniet eum velit tempore quidem voluptates expedita quibusdam officiis. Ipsum, quaerat, vero, adipisci enim autem inventore eum maiores consectetur culpa molestiae cumque sed qui dolorem. Placeat, quae deleniti molestiae minima cupiditate quaerat sit est perspiciatis error iste. Ratione, minus, commodi, magni laborum doloribus libero ullam quos tenetur quis molestias ipsam consequuntur harum asperiores culpa nostrum omnis.
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/js/main.js:
--------------------------------------------------------------------------------
1 | jQuery(document).ready(function($){
2 | //if you change this breakpoint in the style.css file (or _layout.scss if you use SASS), don't forget to update this value as well
3 | var MQL = 1170;
4 |
5 | //primary navigation slide-in effect
6 | if($(window).width() > MQL) {
7 | var headerHeight = $('.cd-header').height();
8 | $(window).on('scroll',
9 | {
10 | previousTop: 0
11 | },
12 | function () {
13 | var currentTop = $(window).scrollTop();
14 | //check if user is scrolling up
15 | if (currentTop < this.previousTop ) {
16 | //if scrolling up...
17 | if (currentTop > 0 && $('.cd-header').hasClass('is-fixed')) {
18 | $('.cd-header').addClass('is-visible');
19 | } else {
20 | $('.cd-header').removeClass('is-visible is-fixed');
21 | }
22 | } else {
23 | //if scrolling down...
24 | $('.cd-header').removeClass('is-visible');
25 | if( currentTop > headerHeight && !$('.cd-header').hasClass('is-fixed')) $('.cd-header').addClass('is-fixed');
26 | }
27 | this.previousTop = currentTop;
28 | });
29 | }
30 |
31 | //open/close primary navigation
32 | $('.cd-primary-nav-trigger').on('click', function(){
33 | $('.cd-menu-icon').toggleClass('is-clicked');
34 | $('.cd-header').toggleClass('menu-is-open');
35 |
36 | //in firefox transitions break when parent overflow is changed, so we need to wait for the end of the trasition to give the body an overflow hidden
37 | if( $('.cd-primary-nav').hasClass('is-visible') ) {
38 | $('.cd-primary-nav').removeClass('is-visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend',function(){
39 | $('body').removeClass('overflow-hidden');
40 | });
41 | } else {
42 | $('.cd-primary-nav').addClass('is-visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend',function(){
43 | $('body').addClass('overflow-hidden');
44 | });
45 | }
46 | });
47 | });
--------------------------------------------------------------------------------
/js/modernizr.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Modernizr v2.8.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 | * 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.8.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, docOverflow,
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 || 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 | // '].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 | //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
131 | fakeBody.style.overflow = 'hidden';
132 | docOverflow = docElement.style.overflow;
133 | docElement.style.overflow = 'hidden';
134 | docElement.appendChild(fakeBody);
135 | }
136 |
137 | 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 ) {
140 | fakeBody.parentNode.removeChild(fakeBody);
141 | docElement.style.overflow = docOverflow;
142 | } else {
143 | div.parentNode.removeChild(div);
144 | }
145 |
146 | return !!ret;
147 |
148 | },
149 | /*>>teststyles*/
150 |
151 | /*>>mq*/
152 | // adapted from matchMedia polyfill
153 | // by Scott Jehl and Paul Irish
154 | // gist.github.com/786768
155 | testMediaQuery = function( mq ) {
156 |
157 | var matchMedia = window.matchMedia || window.msMatchMedia;
158 | if ( matchMedia ) {
159 | return matchMedia(mq) && matchMedia(mq).matches || false;
160 | }
161 |
162 | var bool;
163 |
164 | injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {
165 | bool = (window.getComputedStyle ?
166 | getComputedStyle(node, null) :
167 | node.currentStyle)['position'] == 'absolute';
168 | });
169 |
170 | return bool;
171 |
172 | },
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 | // ...
185 | isEventSupported = (function() {
186 |
187 | var TAGNAMES = {
188 | 'select': 'input', 'change': 'input',
189 | 'submit': 'form', 'reset': 'form',
190 | 'error': 'img', 'load': 'img', 'abort': 'img'
191 | };
192 |
193 | function isEventSupported( eventName, element ) {
194 |
195 | element = element || document.createElement(TAGNAMES[eventName] || 'div');
196 | eventName = 'on' + eventName;
197 |
198 | // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
199 | var isSupported = eventName in element;
200 |
201 | if ( !isSupported ) {
202 | // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
203 | if ( !element.setAttribute ) {
204 | element = document.createElement('div');
205 | }
206 | if ( element.setAttribute && element.removeAttribute ) {
207 | element.setAttribute(eventName, '');
208 | isSupported = is(element[eventName], 'function');
209 |
210 | // If property was created, "remove it" (by setting value to `undefined`)
211 | if ( !is(element[eventName], 'undefined') ) {
212 | element[eventName] = undefined;
213 | }
214 | element.removeAttribute(eventName);
215 | }
216 | }
217 |
218 | element = null;
219 | return isSupported;
220 | }
221 | return isEventSupported;
222 | })(),
223 | /*>>hasevent*/
224 |
225 | // TODO :: Add flag for hasownprop ? didn't last time
226 |
227 | // hasOwnProperty shim by kangax needed for Safari 2.0 support
228 | _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
229 |
230 | if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
231 | hasOwnProp = function (object, property) {
232 | return _hasOwnProperty.call(object, property);
233 | };
234 | }
235 | else {
236 | hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
237 | return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
238 | };
239 | }
240 |
241 | // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js
242 | // es5.github.com/#x15.3.4.5
243 |
244 | if (!Function.prototype.bind) {
245 | Function.prototype.bind = function bind(that) {
246 |
247 | var target = this;
248 |
249 | if (typeof target != "function") {
250 | throw new TypeError();
251 | }
252 |
253 | var args = slice.call(arguments, 1),
254 | bound = function () {
255 |
256 | if (this instanceof bound) {
257 |
258 | var F = function(){};
259 | F.prototype = target.prototype;
260 | var self = new F();
261 |
262 | var result = target.apply(
263 | self,
264 | args.concat(slice.call(arguments))
265 | );
266 | if (Object(result) === result) {
267 | return result;
268 | }
269 | return self;
270 |
271 | } else {
272 |
273 | return target.apply(
274 | that,
275 | args.concat(slice.call(arguments))
276 | );
277 |
278 | }
279 |
280 | };
281 |
282 | return bound;
283 | };
284 | }
285 |
286 | /**
287 | * setCss applies given styles to the Modernizr DOM node.
288 | */
289 | function setCss( str ) {
290 | mStyle.cssText = str;
291 | }
292 |
293 | /**
294 | * setCssAll extrapolates all vendor-specific css strings.
295 | */
296 | function setCssAll( str1, str2 ) {
297 | return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
298 | }
299 |
300 | /**
301 | * is returns a boolean for if typeof obj is exactly type.
302 | */
303 | function is( obj, type ) {
304 | return typeof obj === type;
305 | }
306 |
307 | /**
308 | * contains returns a boolean for if substr is found within str.
309 | */
310 | function contains( str, substr ) {
311 | return !!~('' + str).indexOf(substr);
312 | }
313 |
314 | /*>>testprop*/
315 |
316 | // testProps is a generic CSS / DOM property test.
317 |
318 | // In testing support for a given CSS property, it's legit to test:
319 | // `elem.style[styleName] !== undefined`
320 | // If the property is supported it will return an empty string,
321 | // if unsupported it will return undefined.
322 |
323 | // We'll take advantage of this quick test and skip setting a style
324 | // on our modernizr element, but instead just testing undefined vs
325 | // empty string.
326 |
327 | // Because the testing of the CSS property names (with "-", as
328 | // opposed to the camelCase DOM properties) is non-portable and
329 | // non-standard but works in WebKit and IE (but not Gecko or Opera),
330 | // we explicitly reject properties with dashes so that authors
331 | // developing in WebKit or IE first don't end up with
332 | // browser-specific content by accident.
333 |
334 | function testProps( props, prefixed ) {
335 | for ( var i in props ) {
336 | var prop = props[i];
337 | if ( !contains(prop, "-") && mStyle[prop] !== undefined ) {
338 | return prefixed == 'pfx' ? prop : true;
339 | }
340 | }
341 | return false;
342 | }
343 | /*>>testprop*/
344 |
345 | // TODO :: add testDOMProps
346 | /**
347 | * testDOMProps is a generic DOM property test; if a browser supports
348 | * a certain property, it won't return undefined for it.
349 | */
350 | function testDOMProps( props, obj, elem ) {
351 | for ( var i in props ) {
352 | var item = obj[props[i]];
353 | if ( item !== undefined) {
354 |
355 | // return the property name as a string
356 | if (elem === false) return props[i];
357 |
358 | // let's bind a function
359 | if (is(item, 'function')){
360 | // default to autobind unless override
361 | return item.bind(elem || obj);
362 | }
363 |
364 | // return the unbound function or obj or value
365 | return item;
366 | }
367 | }
368 | return false;
369 | }
370 |
371 | /*>>testallprops*/
372 | /**
373 | * testPropsAll tests a list of DOM properties we want to check against.
374 | * We specify literally ALL possible (known and/or likely) properties on
375 | * the element including the non-vendor prefixed one, for forward-
376 | * compatibility.
377 | */
378 | function testPropsAll( prop, prefixed, elem ) {
379 |
380 | var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
381 | props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
382 |
383 | // did they call .prefixed('boxSizing') or are we just testing a prop?
384 | if(is(prefixed, "string") || is(prefixed, "undefined")) {
385 | return testProps(props, prefixed);
386 |
387 | // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
388 | } else {
389 | props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
390 | return testDOMProps(props, prefixed, elem);
391 | }
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() {
405 | return testPropsAll('flexWrap');
406 | };
407 |
408 | // The *old* flexbox
409 | // www.w3.org/TR/2009/WD-css3-flexbox-20090723/
410 |
411 | tests['flexboxlegacy'] = function() {
412 | return testPropsAll('boxDirection');
413 | };
414 |
415 | // On the S60 and BB Storm, getContext exists, but always returns undefined
416 | // so we actually have to call getContext() to verify
417 | // github.com/Modernizr/Modernizr/issues/issue/97/
418 |
419 | tests['canvas'] = function() {
420 | var elem = document.createElement('canvas');
421 | return !!(elem.getContext && elem.getContext('2d'));
422 | };
423 |
424 | tests['canvastext'] = function() {
425 | return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
426 | };
427 |
428 | // webk.it/70117 is tracking a legit WebGL feature detect proposal
429 |
430 | // We do a soft detect which may false positive in order to avoid
431 | // an expensive context creation: bugzil.la/732441
432 |
433 | tests['webgl'] = function() {
434 | return !!window.WebGLRenderingContext;
435 | };
436 |
437 | /*
438 | * The Modernizr.touch test only indicates if the browser supports
439 | * touch events, which does not necessarily reflect a touchscreen
440 | * device, as evidenced by tablets running Windows 7 or, alas,
441 | * the Palm Pre / WebOS (touch) phones.
442 | *
443 | * Additionally, Chrome (desktop) used to lie about its support on this,
444 | * but that has since been rectified: crbug.com/36415
445 | *
446 | * We also test for Firefox 4 Multitouch Support.
447 | *
448 | * For more info, see: modernizr.github.com/Modernizr/touch.html
449 | */
450 |
451 | tests['touch'] = function() {
452 | var bool;
453 |
454 | if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
455 | bool = true;
456 | } else {
457 | injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) {
458 | bool = node.offsetTop === 9;
459 | });
460 | }
461 |
462 | return bool;
463 | };
464 |
465 |
466 | // geolocation is often considered a trivial feature detect...
467 | // Turns out, it's quite tricky to get right:
468 | //
469 | // Using !!navigator.geolocation does two things we don't want. It:
470 | // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513
471 | // 2. Disables page caching in WebKit: webk.it/43956
472 | //
473 | // Meanwhile, in Firefox < 8, an about:config setting could expose
474 | // a false positive that would throw an exception: bugzil.la/688158
475 |
476 | tests['geolocation'] = function() {
477 | return 'geolocation' in navigator;
478 | };
479 |
480 |
481 | tests['postmessage'] = function() {
482 | return !!window.postMessage;
483 | };
484 |
485 |
486 | // Chrome incognito mode used to throw an exception when using openDatabase
487 | // It doesn't anymore.
488 | tests['websqldatabase'] = function() {
489 | return !!window.openDatabase;
490 | };
491 |
492 | // Vendors had inconsistent prefixing with the experimental Indexed DB:
493 | // - Webkit's implementation is accessible through webkitIndexedDB
494 | // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB
495 | // For speed, we don't test the legacy (and beta-only) indexedDB
496 | tests['indexedDB'] = function() {
497 | return !!testPropsAll("indexedDB", window);
498 | };
499 |
500 | // documentMode logic from YUI to filter out IE8 Compat Mode
501 | // which false positives.
502 | tests['hashchange'] = function() {
503 | return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);
504 | };
505 |
506 | // Per 1.6:
507 | // This used to be Modernizr.historymanagement but the longer
508 | // name has been deprecated in favor of a shorter and property-matching one.
509 | // The old API is still available in 1.6, but as of 2.0 will throw a warning,
510 | // and in the first release thereafter disappear entirely.
511 | tests['history'] = function() {
512 | return !!(window.history && history.pushState);
513 | };
514 |
515 | tests['draganddrop'] = function() {
516 | var div = document.createElement('div');
517 | return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
518 | };
519 |
520 | // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10
521 | // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17.
522 | // FF10 still uses prefixes, so check for it until then.
523 | // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/
524 | tests['websockets'] = function() {
525 | return 'WebSocket' in window || 'MozWebSocket' in window;
526 | };
527 |
528 |
529 | // css-tricks.com/rgba-browser-support/
530 | tests['rgba'] = function() {
531 | // Set an rgba() color and check the returned value
532 |
533 | setCss('background-color:rgba(150,255,150,.5)');
534 |
535 | return contains(mStyle.backgroundColor, 'rgba');
536 | };
537 |
538 | 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)');
543 |
544 | return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');
545 | };
546 |
547 | 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!
551 |
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() {
566 | return testPropsAll('backgroundSize');
567 | };
568 |
569 | tests['borderimage'] = function() {
570 | return testPropsAll('borderImage');
571 | };
572 |
573 |
574 | // Super comprehensive table about all the unique implementations of
575 | // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance
576 |
577 | tests['borderradius'] = function() {
578 | return testPropsAll('borderRadius');
579 | };
580 |
581 | // WebOS unfortunately false positives on this test.
582 | tests['boxshadow'] = function() {
583 | return testPropsAll('boxShadow');
584 | };
585 |
586 | // FF3.0 will false positive on this test
587 | tests['textshadow'] = function() {
588 | return document.createElement('div').style.textShadow === '';
589 | };
590 |
591 |
592 | 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.
596 |
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);
603 | };
604 |
605 |
606 | // Note, Android < 4 will pass this test, but can only animate
607 | // a single property at a time
608 | // goo.gl/v3V4Gp
609 | tests['cssanimations'] = function() {
610 | return testPropsAll('animationName');
611 | };
612 |
613 |
614 | tests['csscolumns'] = function() {
615 | return testPropsAll('columnCount');
616 | };
617 |
618 |
619 | tests['cssgradients'] = function() {
620 | /**
621 | * For CSS Gradients syntax, please see:
622 | * webkit.org/blog/175/introducing-css-gradients/
623 | * developer.mozilla.org/en/CSS/-moz-linear-gradient
624 | * developer.mozilla.org/en/CSS/-moz-radial-gradient
625 | * dev.w3.org/csswg/css3-images/#gradients-
626 | */
627 |
628 | var str1 = 'background-image:',
629 | str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
630 | str3 = 'linear-gradient(left top,#9f9, white);';
631 |
632 | 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)
637 | );
638 |
639 | return contains(mStyle.backgroundImage, 'gradient');
640 | };
641 |
642 |
643 | tests['cssreflections'] = function() {
644 | return testPropsAll('boxReflect');
645 | };
646 |
647 |
648 | tests['csstransforms'] = function() {
649 | return !!testPropsAll('transform');
650 | };
651 |
652 |
653 | tests['csstransforms3d'] = function() {
654 |
655 | var ret = !!testPropsAll('perspective');
656 |
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 ) {
662 |
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 ) {
666 | ret = node.offsetLeft === 9 && node.offsetHeight === 3;
667 | });
668 | }
669 | return ret;
670 | };
671 |
672 |
673 | tests['csstransitions'] = function() {
674 | return testPropsAll('transition');
675 | };
676 |
677 |
678 | /*>>fontface*/
679 | // @font-face detection routine by Diego Perini
680 | // javascript.nwbox.com/CSSSupport/
681 |
682 | // false positives:
683 | // WebOS github.com/Modernizr/Modernizr/issues/342
684 | // WP7 github.com/Modernizr/Modernizr/issues/538
685 | tests['fontface'] = function() {
686 | var bool;
687 |
688 | injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) {
689 | var style = document.getElementById('smodernizr'),
690 | sheet = style.sheet || style.styleSheet,
691 | cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';
692 |
693 | bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;
694 | });
695 |
696 | return bool;
697 | };
698 | /*>>fontface*/
699 |
700 | // CSS generated content detection
701 | tests['generatedcontent'] = function() {
702 | var bool;
703 |
704 | injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) {
705 | bool = node.offsetHeight >= 3;
706 | });
707 |
708 | return bool;
709 | };
710 |
711 |
712 |
713 | // These tests evaluate support of the video/audio elements, as well as
714 | // testing what types of content they support.
715 | //
716 | // We're using the Boolean constructor here, so that we can extend the value
717 | // e.g. Modernizr.video // true
718 | // Modernizr.video.ogg // 'probably'
719 | //
720 | // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
721 | // thx to NielsLeenheer and zcorpan
722 |
723 | // Note: in some older browsers, "no" was a return value instead of empty string.
724 | // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
725 | // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
726 |
727 | tests['video'] = function() {
728 | var elem = document.createElement('video'),
729 | bool = false;
730 |
731 | // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
732 | try {
733 | if ( bool = !!elem.canPlayType ) {
734 | bool = new Boolean(bool);
735 | bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,'');
736 |
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$/,'');
739 |
740 | bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,'');
741 | }
742 |
743 | } catch(e) { }
744 |
745 | return bool;
746 | };
747 |
748 | tests['audio'] = function() {
749 | var elem = document.createElement('audio'),
750 | bool = false;
751 |
752 | try {
753 | if ( bool = !!elem.canPlayType ) {
754 | bool = new Boolean(bool);
755 | bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
756 | bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,'');
757 |
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$/,'');
762 | bool.m4a = ( elem.canPlayType('audio/x-m4a;') ||
763 | elem.canPlayType('audio/aac;')) .replace(/^no$/,'');
764 | }
765 | } catch(e) { }
766 |
767 | return bool;
768 | };
769 |
770 |
771 | // In FF4, if disabled, window.localStorage should === null.
772 |
773 | // Normally, we could not test that directly and need to do a
774 | // `('localStorage' in window) && ` test first because otherwise Firefox will
775 | // throw bugzil.la/365772 if cookies are disabled
776 |
777 | // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem
778 | // will throw the exception:
779 | // QUOTA_EXCEEDED_ERRROR DOM Exception 22.
780 | // Peculiarly, getItem and removeItem calls do not throw.
781 |
782 | // Because we are forced to try/catch this, we'll go aggressive.
783 |
784 | // Just FWIW: IE8 Compat mode supports these features completely:
785 | // www.quirksmode.org/dom/html5.html
786 | // But IE8 doesn't support either with local files
787 |
788 | tests['localstorage'] = function() {
789 | try {
790 | localStorage.setItem(mod, mod);
791 | localStorage.removeItem(mod);
792 | return true;
793 | } catch(e) {
794 | return false;
795 | }
796 | };
797 |
798 | tests['sessionstorage'] = function() {
799 | try {
800 | sessionStorage.setItem(mod, mod);
801 | sessionStorage.removeItem(mod);
802 | return true;
803 | } catch(e) {
804 | return false;
805 | }
806 | };
807 |
808 |
809 | tests['webworkers'] = function() {
810 | return !!window.Worker;
811 | };
812 |
813 |
814 | tests['applicationcache'] = function() {
815 | return !!window.applicationCache;
816 | };
817 |
818 |
819 | // Thanks to Erik Dahlstrom
820 | tests['svg'] = function() {
821 | return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
822 | };
823 |
824 | // specifically for SVG inline in HTML, not within XHTML
825 | // test page: paulirish.com/demo/inline-svg
826 | tests['inlinesvg'] = function() {
827 | var div = document.createElement('div');
828 | div.innerHTML = '';
829 | return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
830 | };
831 |
832 | // SVG SMIL animation
833 | tests['smil'] = function() {
834 | return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));
835 | };
836 |
837 | // This test is only for clip paths in SVG proper, not clip paths on HTML content
838 | // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg
839 |
840 | // However read the comments to dig into applying SVG clippaths to HTML content here:
841 | // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491
842 | tests['svgclippaths'] = function() {
843 | return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
844 | };
845 |
846 | /*>>webforms*/
847 | // input features and input types go directly onto the ret object, bypassing the tests loop.
848 | // Hold this guy to execute in a moment.
849 | 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 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 ) {
862 | for ( var i = 0, len = props.length; i < len; i++ ) {
863 | attrs[ props[i] ] = !!(props[i] in inputElem);
864 | }
865 | 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);
869 | }
870 | return attrs;
871 | })('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) {
882 |
883 | for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
884 |
885 | inputElem.setAttribute('type', inputElemType = props[i]);
886 | bool = inputElem.type !== 'text';
887 |
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 ) {
892 |
893 | inputElem.value = smile;
894 | inputElem.style.cssText = 'position:absolute;visibility:hidden;';
895 |
896 | if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {
897 |
898 | docElement.appendChild(inputElem);
899 | defaultView = document.defaultView;
900 |
901 | // Safari 2-4 allows the smiley as a value, despite making a slider
902 | bool = defaultView.getComputedStyle &&
903 | 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);
907 |
908 | docElement.removeChild(inputElem);
909 |
910 | } 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;
920 |
921 | } else {
922 | // If the upgraded input compontent rejects the :) text, we got a winner
923 | bool = inputElem.value != smile;
924 | }
925 | }
926 |
927 | inputs[ props[i] ] = !!bool;
928 | }
929 | return inputs;
930 | })('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.
943 | for ( var feature in tests ) {
944 | 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();
949 | Modernizr[featureName] = tests[feature]();
950 |
951 | classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
952 | }
953 | }
954 |
955 | /*>>webforms*/
956 | // input tests need to run.
957 | Modernizr.input || webforms();
958 | /*>>webforms*/
959 |
960 |
961 | /**
962 | * addTest allows the user to define their own feature tests
963 | * the result will be added onto the Modernizr object,
964 | * as well as an appropriate className set on the html element
965 | *
966 | * @param feature - String naming the feature
967 | * @param test - Function returning true if feature is supported, false if not
968 | */
969 | Modernizr.addTest = function ( feature, test ) {
970 | if ( typeof feature == 'object' ) {
971 | for ( var key in feature ) {
972 | if ( hasOwnProp( feature, key ) ) {
973 | Modernizr.addTest( key, feature[ key ] );
974 | }
975 | }
976 | } else {
977 |
978 | feature = feature.toLowerCase();
979 |
980 | 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;
987 | }
988 |
989 | test = typeof test == 'function' ? test() : test;
990 |
991 | if (typeof enableClasses !== "undefined" && enableClasses) {
992 | docElement.className += ' ' + (test ? '' : 'no-') + feature;
993 | }
994 | Modernizr[feature] = test;
995 |
996 | }
997 |
998 | return Modernizr; // allow chaining.
999 | };
1000 |
1001 |
1002 | // Reset modElem.cssText to nothing to reduce memory footprint.
1003 | setCss('');
1004 | modElem = inputElem = null;
1005 |
1006 | /*>>shiv*/
1007 | /**
1008 | * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
1009 | */
1010 | ;(function(window, document) {
1011 | /*jshint evil:true */
1012 | /** version */
1013 | var version = '3.7.0';
1014 |
1015 | /** Preset options */
1016 | var options = window.html5 || {};
1017 |
1018 | /** Used to skip problem elements */
1019 | var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
1020 |
1021 | /** Not all elements can be cloned in IE **/
1022 | 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;
1023 |
1024 | /** Detect whether the browser supports default html5 styles */
1025 | var supportsHtml5Styles;
1026 |
1027 | /** Name of the expando, to work with multiple documents or to re-shiv one document */
1028 | var expando = '_html5shiv';
1029 |
1030 | /** The id for the the documents expando */
1031 | var expanID = 0;
1032 |
1033 | /** Cached data for each document */
1034 | var expandoData = {};
1035 |
1036 | /** Detect whether the browser supports unknown elements */
1037 | var supportsUnknownElements;
1038 |
1039 | (function() {
1040 | try {
1041 | var a = document.createElement('a');
1042 | a.innerHTML = '';
1043 | //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
1044 | supportsHtml5Styles = ('hidden' in a);
1045 |
1046 | supportsUnknownElements = a.childNodes.length == 1 || (function() {
1047 | // assign a false positive if unable to shiv
1048 | (document.createElement)('a');
1049 | var frag = document.createDocumentFragment();
1050 | return (
1051 | typeof frag.cloneNode == 'undefined' ||
1052 | typeof frag.createDocumentFragment == 'undefined' ||
1053 | typeof frag.createElement == 'undefined'
1054 | );
1055 | }());
1056 | } catch(e) {
1057 | // assign a false positive if detection fails => unable to shiv
1058 | supportsHtml5Styles = true;
1059 | supportsUnknownElements = true;
1060 | }
1061 |
1062 | }());
1063 |
1064 | /*--------------------------------------------------------------------------*/
1065 |
1066 | /**
1067 | * Creates a style sheet with the given CSS text and adds it to the document.
1068 | * @private
1069 | * @param {Document} ownerDocument The document.
1070 | * @param {String} cssText The CSS text.
1071 | * @returns {StyleSheet} The style element.
1072 | */
1073 | function addStyleSheet(ownerDocument, cssText) {
1074 | var p = ownerDocument.createElement('p'),
1075 | parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
1076 |
1077 | p.innerHTML = 'x';
1078 | return parent.insertBefore(p.lastChild, parent.firstChild);
1079 | }
1080 |
1081 | /**
1082 | * Returns the value of `html5.elements` as an array.
1083 | * @private
1084 | * @returns {Array} An array of shived element node names.
1085 | */
1086 | function getElements() {
1087 | var elements = html5.elements;
1088 | return typeof elements == 'string' ? elements.split(' ') : elements;
1089 | }
1090 |
1091 | /**
1092 | * Returns the data associated to the given document
1093 | * @private
1094 | * @param {Document} ownerDocument The document.
1095 | * @returns {Object} An object of data.
1096 | */
1097 | function getExpandoData(ownerDocument) {
1098 | var data = expandoData[ownerDocument[expando]];
1099 | if (!data) {
1100 | data = {};
1101 | expanID++;
1102 | ownerDocument[expando] = expanID;
1103 | expandoData[expanID] = data;
1104 | }
1105 | return data;
1106 | }
1107 |
1108 | /**
1109 | * returns a shived element for the given nodeName and document
1110 | * @memberOf html5
1111 | * @param {String} nodeName name of the element
1112 | * @param {Document} ownerDocument The context document.
1113 | * @returns {Object} The shived element.
1114 | */
1115 | function createElement(nodeName, ownerDocument, data){
1116 | if (!ownerDocument) {
1117 | ownerDocument = document;
1118 | }
1119 | if(supportsUnknownElements){
1120 | return ownerDocument.createElement(nodeName);
1121 | }
1122 | if (!data) {
1123 | data = getExpandoData(ownerDocument);
1124 | }
1125 | var node;
1126 |
1127 | if (data.cache[nodeName]) {
1128 | node = data.cache[nodeName].cloneNode();
1129 | } else if (saveClones.test(nodeName)) {
1130 | node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
1131 | } else {
1132 | node = data.createElem(nodeName);
1133 | }
1134 |
1135 | // Avoid adding some elements to fragments in IE < 9 because
1136 | // * Attributes like `name` or `type` cannot be set/changed once an element
1137 | // is inserted into a document/fragment
1138 | // * Link elements with `src` attributes that are inaccessible, as with
1139 | // a 403 response, will cause the tab/window to crash
1140 | // * Script elements appended to fragments will execute when their `src`
1141 | // or `text` property is set
1142 | return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
1143 | }
1144 |
1145 | /**
1146 | * returns a shived DocumentFragment for the given document
1147 | * @memberOf html5
1148 | * @param {Document} ownerDocument The context document.
1149 | * @returns {Object} The shived DocumentFragment.
1150 | */
1151 | function createDocumentFragment(ownerDocument, data){
1152 | if (!ownerDocument) {
1153 | ownerDocument = document;
1154 | }
1155 | if(supportsUnknownElements){
1156 | return ownerDocument.createDocumentFragment();
1157 | }
1158 | data = data || getExpandoData(ownerDocument);
1159 | var clone = data.frag.cloneNode(),
1160 | i = 0,
1161 | elems = getElements(),
1162 | l = elems.length;
1163 | for(;i>shiv*/
1309 |
1310 | // Assign private properties to the return object with prefix
1311 | Modernizr._version = version;
1312 |
1313 | // expose these for the plugin API. Look in the source for how to join() them against your input
1314 | /*>>prefixes*/
1315 | Modernizr._prefixes = prefixes;
1316 | /*>>prefixes*/
1317 | /*>>domprefixes*/
1318 | Modernizr._domPrefixes = domPrefixes;
1319 | Modernizr._cssomPrefixes = cssomPrefixes;
1320 | /*>>domprefixes*/
1321 |
1322 | /*>>mq*/
1323 | // Modernizr.mq tests a given media query, live against the current state of the window
1324 | // A few important notes:
1325 | // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false
1326 | // * A max-width or orientation query will be evaluated against the current state, which may change later.
1327 | // * You must specify values. Eg. If you are testing support for the min-width media query use:
1328 | // Modernizr.mq('(min-width:0)')
1329 | // usage:
1330 | // Modernizr.mq('only screen and (max-width:768)')
1331 | Modernizr.mq = testMediaQuery;
1332 | /*>>mq*/
1333 |
1334 | /*>>hasevent*/
1335 | // Modernizr.hasEvent() detects support for a given event, with an optional element to test on
1336 | // Modernizr.hasEvent('gesturestart', elem)
1337 | Modernizr.hasEvent = isEventSupported;
1338 | /*>>hasevent*/
1339 |
1340 | /*>>testprop*/
1341 | // Modernizr.testProp() investigates whether a given style property is recognized
1342 | // Note that the property names must be provided in the camelCase variant.
1343 | // Modernizr.testProp('pointerEvents')
1344 | Modernizr.testProp = function(prop){
1345 | return testProps([prop]);
1346 | };
1347 | /*>>testprop*/
1348 |
1349 | /*>>testallprops*/
1350 | // Modernizr.testAllProps() investigates whether a given style property,
1351 | // or any of its vendor-prefixed variants, is recognized
1352 | // Note that the property names must be provided in the camelCase variant.
1353 | // Modernizr.testAllProps('boxSizing')
1354 | Modernizr.testAllProps = testPropsAll;
1355 | /*>>testallprops*/
1356 |
1357 |
1358 | /*>>teststyles*/
1359 | // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards
1360 | // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })
1361 | Modernizr.testStyles = injectElementWithStyles;
1362 | /*>>teststyles*/
1363 |
1364 |
1365 | /*>>prefixed*/
1366 | // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input
1367 | // Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
1368 |
1369 | // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style.
1370 | // Return values will also be the camelCase variant, if you need to translate that to hypenated style use:
1371 | //
1372 | // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
1373 |
1374 | // If you're trying to ascertain which transition end event to bind to, you might do something like...
1375 | //
1376 | // var transEndEventNames = {
1377 | // 'WebkitTransition' : 'webkitTransitionEnd',
1378 | // 'MozTransition' : 'transitionend',
1379 | // 'OTransition' : 'oTransitionEnd',
1380 | // 'msTransition' : 'MSTransitionEnd',
1381 | // 'transition' : 'transitionend'
1382 | // },
1383 | // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
1384 |
1385 | Modernizr.prefixed = function(prop, obj, elem){
1386 | if(!obj) {
1387 | return testPropsAll(prop, 'pfx');
1388 | } else {
1389 | // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
1390 | return testPropsAll(prop, obj, elem);
1391 | }
1392 | };
1393 | /*>>prefixed*/
1394 |
1395 |
1396 | /*>>cssclasses*/
1397 | // Remove "no-js" class from element, if it exists:
1398 | docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') +
1399 |
1400 | // Add the new classes to the element.
1401 | (enableClasses ? ' js ' + classes.join(' ') : '');
1402 | /*>>cssclasses*/
1403 |
1404 | return Modernizr;
1405 |
1406 | })(this, this.document);
1407 |
--------------------------------------------------------------------------------
/partials/_layout.scss:
--------------------------------------------------------------------------------
1 | // breakpoints
2 |
3 | $S: 320px;
4 | $M: 768px;
5 | $L: 1170px;
6 |
7 | // media queries
8 |
9 | @mixin MQ($canvas) {
10 | @if $canvas == S {
11 | @media only screen and (min-width: $S) { @content; }
12 | }
13 | @else if $canvas == M {
14 | @media only screen and (min-width: $M) { @content; }
15 | }
16 | @else if $canvas == L {
17 | @media only screen and (min-width: $L) { @content; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/partials/_mixins.scss:
--------------------------------------------------------------------------------
1 | // rem fallback - credits: http://zerosixthree.se/
2 |
3 | @function calculateRem($size) {
4 | $remSize: $size / 16px;
5 | @return $remSize * 1rem;
6 | }
7 |
8 | @mixin font-size($size) {
9 | font-size: $size;
10 | font-size: calculateRem($size);
11 | }
12 |
13 | // center vertically and/or horizontally an absolute positioned element
14 |
15 | @mixin center($xy:xy) {
16 | @if $xy == xy {
17 | left: 50%;
18 | top: 50%;
19 | bottom: auto;
20 | right: auto;
21 | @include transform(translateX(-50%) translateY(-50%));
22 | }
23 | @else if $xy == x {
24 | left: 50%;
25 | right: auto;
26 | @include transform(translateX(-50%));
27 | }
28 | @else if $xy == y {
29 | top: 50%;
30 | bottom: auto;
31 | @include transform(translateY(-50%));
32 | }
33 | }
34 |
35 | // border radius
36 |
37 | @mixin border-radius($radius:.25em) {
38 | border-radius: $radius;
39 | }
40 |
41 | // antialiasing mode font rendering
42 |
43 | @mixin font-smoothing {
44 | -webkit-font-smoothing: antialiased;
45 | -moz-osx-font-smoothing: grayscale;
46 | }
47 |
--------------------------------------------------------------------------------
/partials/_variables.scss:
--------------------------------------------------------------------------------
1 | // colors
2 |
3 | $color-1: #021725; // blue
4 | $color-2: #e36767; // red
5 | $color-3: #fff; // white
6 |
7 | // fonts
8 |
9 | $primary-font: 'Source Sans Pro', sans-serif;
10 |
11 | //header height
12 |
13 | $header-height-S: 50px;
14 | $header-height-M: 80px;
15 |
16 | // z-index
17 |
18 | $content-zindex: 1;
19 | $nav-zindex: 2;
20 | $header-zindex: 3;
21 |
--------------------------------------------------------------------------------
/scss/style.scss:
--------------------------------------------------------------------------------
1 | @import 'bourbon'; // http://bourbon.io/
2 |
3 | @import '../partials/variables'; // colors, fonts etc...
4 |
5 | @import '../partials/mixins'; // custom mixins
6 |
7 | @import '../partials/layout'; // responsive grid and media queries
8 |
9 | /* --------------------------------
10 |
11 | Primary style
12 |
13 | -------------------------------- */
14 |
15 | *, *:after, *:before {
16 | @include box-sizing(border-box);
17 | }
18 |
19 | body {
20 | font: {
21 | size: 100%;
22 | family: $primary-font; // variables inside partials > _variables.scss
23 | }
24 | color: rgba($color-1, .7);
25 | background-color: $color-3;
26 |
27 | &.overflow-hidden {
28 | /* when primary navigation is visible, the content in the background won't scroll */
29 | overflow: hidden;
30 | }
31 | }
32 |
33 | a {
34 | color: $color-3;
35 | text-decoration: none;
36 | }
37 |
38 | /* --------------------------------
39 |
40 | Modules - reusable parts of our design
41 |
42 | -------------------------------- */
43 |
44 | .cd-container { /* this class is used to give a max-width to the element it is applied to, and center it horizontally when it reaches that max-width */
45 | width: 90%;
46 | max-width: $M; // breakpoints inside partials > _layout.scss
47 | margin: 0 auto;
48 | @include clearfix;
49 | }
50 |
51 | /* --------------------------------
52 |
53 | Main components
54 |
55 | -------------------------------- */
56 |
57 | html, body {
58 | height: 100%;
59 | }
60 |
61 | .cd-header {
62 | position: absolute;
63 | top: 0;
64 | left: 0;
65 | background: rgba($color-1, .95);
66 | height: $header-height-S;
67 | width: 100%;
68 | z-index: $header-zindex;
69 | box-shadow: 0 1px 2px rgba(#000, .3);
70 | @include font-smoothing;
71 |
72 | @include MQ(M) {
73 | height: $header-height-M;
74 | background: transparent;
75 | box-shadow: none;
76 | }
77 |
78 | @include MQ(L) {
79 | @include transition(background-color .3s);
80 |
81 | /* Force Hardware Acceleration in WebKit */
82 | @include transform(translate3d(0,0,0));
83 | -webkit-backface-visibility: hidden;
84 | backface-visibility: hidden;
85 |
86 | &.is-fixed {
87 | /* when the user scrolls down, we hide the header right above the viewport */
88 | position: fixed;
89 | top: -$header-height-M;
90 | background-color: rgba($color-1, .96);
91 | -webkit-transition: -webkit-transform 0.3s;
92 | -moz-transition: -moz-transform 0.3s;
93 | transition: transform 0.3s;
94 | }
95 |
96 | &.is-visible {
97 | /* if the user changes the scrolling direction, we show the header */
98 | @include transform(translate3d(0,100%,0));
99 | }
100 |
101 | &.menu-is-open {
102 | /* add a background color to the header when the navigation is open */
103 | background-color: rgba($color-1, .96);
104 | }
105 | }
106 | }
107 |
108 | .cd-logo {
109 | display: block;
110 | position: absolute;
111 | @include center(y);
112 | left: .875em;
113 |
114 | img {
115 | display: block;
116 | }
117 |
118 | @include MQ(M) {
119 | left: 2.6em;
120 | }
121 | }
122 |
123 | .cd-secondary-nav {
124 | position: absolute;
125 | @include center(y);
126 | right: 10em;
127 | /* hidden on small devices */
128 | display: none;
129 |
130 | li {
131 | display: inline-block;
132 | margin-left: 2.2em;
133 | }
134 |
135 | a {
136 | display: inline-block;
137 | color: $color-3;
138 | text-transform: uppercase;
139 | font-weight: 700;
140 | }
141 |
142 | @include MQ(M) {
143 | display: block;
144 | }
145 | }
146 |
147 | .cd-primary-nav-trigger {
148 | position: absolute;
149 | right: 0;
150 | top: 0;
151 | height: 100%;
152 | width: 50px;
153 | background-color: lighten($color-1, 5%);
154 |
155 | .cd-menu-text {
156 | color: $color-3;
157 | text-transform: uppercase;
158 | font-weight: 700;
159 | /* hide the text on small devices */
160 | display: none;
161 | }
162 |
163 | .cd-menu-icon {
164 | /* this span is the central line of the menu icon */
165 | display: inline-block;
166 | position: absolute;
167 | @include center; // mixin inside partials > _mixins.scss
168 | width: 18px;
169 | height: 2px;
170 | background-color: $color-3;
171 | @include transition(background-color .3s);
172 |
173 | /* these are the upper and lower lines in the menu icon */
174 | &::before, &:after {
175 | content: '';
176 | width: 100%;
177 | height: 100%;
178 | position: absolute;
179 | background-color: $color-3;
180 | right: 0;
181 |
182 | -webkit-transition: -webkit-transform .3s, top .3s, background-color 0s;
183 | -moz-transition: -moz-transform .3s, top .3s, background-color 0s;
184 | transition: transform .3s, top .3s, background-color 0s;
185 | }
186 |
187 | &::before {
188 | top: -5px;
189 | }
190 |
191 | &::after {
192 | top: 5px;
193 | }
194 |
195 | &.is-clicked {
196 | background-color: rgba($color-3, 0);
197 |
198 | &::before, &::after {
199 | background-color: rgba($color-3, 1);
200 | }
201 |
202 | &::before {
203 | top: 0;
204 | @include transform(rotate(135deg));
205 | }
206 |
207 | &::after {
208 | top: 0;
209 | @include transform(rotate(225deg));
210 | }
211 | }
212 | }
213 |
214 | @include MQ(M) {
215 | width: 100px;
216 | padding-left: 1em;
217 | background-color: transparent;
218 | height: 30px;
219 | line-height: 30px;
220 | right: 2.2em;
221 | @include center(y);
222 |
223 | .cd-menu-text {
224 | display: inline-block;
225 | }
226 |
227 | .cd-menu-icon {
228 | left: auto;
229 | right: 1em;
230 | @include transform(translateX(0) translateY(-50%));
231 | }
232 | }
233 | }
234 |
235 | .cd-primary-nav {
236 | /* by default it's hidden - on top of the viewport */
237 | position: fixed;
238 | left: 0;
239 | top: 0;
240 | height: 100%;
241 | width: 100%;
242 | background: rgba($color-1, .96);
243 | z-index: $nav-zindex;
244 | text-align: center;
245 | padding: $header-height-S 0;
246 | -webkit-backface-visibility: hidden;
247 | backface-visibility: hidden;
248 |
249 | overflow: auto;
250 | /* this fixes the buggy scrolling on webkit browsers - mobile devices only - when overflow property is applied */
251 | -webkit-overflow-scrolling: touch;
252 |
253 | @include transform(translateY(-100%));
254 | @include transition-property(transform);
255 | @include transition-duration(.4s);
256 |
257 | li {
258 | @include font-size(22px);
259 | font-weight: 300;
260 | @include font-smoothing;
261 | margin: .2em 0;
262 | text-transform: capitalize;
263 | }
264 |
265 | a {
266 | display: inline-block;
267 | padding: .4em 1em;
268 | @include border-radius;
269 | @include transition(background .2s);
270 |
271 | .no-touch &:hover {
272 | background-color: $color-2;
273 | }
274 | }
275 |
276 | .cd-label {
277 | color: lighten($color-1, 15%);
278 | text-transform: uppercase;
279 | font-weight: 700;
280 | @include font-size(14px);
281 | margin: 2.4em 0 .8em;
282 | }
283 |
284 | .cd-social {
285 | display: inline-block;
286 | margin: 0 .4em;
287 |
288 | a {
289 | width: 44px;
290 | height: 44px;
291 | padding: 0;
292 | background-image: url('../img/cd-socials.svg');
293 | background-repeat: no-repeat;
294 |
295 | /* image replacement */
296 | overflow: hidden;
297 | text-indent: 100%;
298 | white-space: nowrap;
299 | }
300 | }
301 |
302 | .cd-facebook a {
303 | background-position: 0 0;
304 | }
305 |
306 | .cd-instagram a {
307 | background-position: -44px 0;
308 | }
309 |
310 | .cd-dribbble a {
311 | background-position: -88px 0;
312 | }
313 |
314 | .cd-twitter a {
315 | background-position: -132px 0;
316 | }
317 |
318 | &.is-visible {
319 | @include transform(translateY(0));
320 | }
321 |
322 | @include MQ(M) {
323 | padding: $header-height-M 0;
324 | }
325 |
326 | @include MQ(L) {
327 | li {
328 | @include font-size(30px);
329 | }
330 |
331 | .cd-label {
332 | @include font-size(16px);
333 | }
334 | }
335 | }
336 |
337 | .cd-intro {
338 | position: relative;
339 | height: 100%;
340 | background: url('../img/cd-background-img.jpg') no-repeat center center;
341 | background-size: cover;
342 | z-index: $content-zindex;
343 | @include font-smoothing;
344 |
345 | h1 {
346 | position: absolute;
347 | width: 90%;
348 | max-width: $L;
349 | @include center;
350 |
351 | color: $color-3;
352 | @include font-size(20px);
353 | font-weight: 300;
354 | text-align: center;
355 | }
356 |
357 | @include MQ(M) {
358 | h1 {
359 | @include font-size(30px);
360 | }
361 | }
362 |
363 | @include MQ(L) {
364 | height: 700px;
365 | }
366 | }
367 |
368 | .cd-main-content {
369 | position: relative;
370 | z-index: $content-zindex;
371 |
372 | p {
373 | line-height: 1.6;
374 | margin: 2em 0;
375 | }
376 |
377 | @include MQ(L) {
378 | p {
379 | @include font-size(20px);
380 | }
381 | }
382 | }
383 |
384 |
--------------------------------------------------------------------------------