Run Grunt build script
|
@ -71,7 +71,7 @@ module.exports = function(grunt) {
|
||||||
files: [
|
files: [
|
||||||
'<%= jshint.all %>'
|
'<%= jshint.all %>'
|
||||||
],
|
],
|
||||||
tasks: ['jshint','uglify']
|
tasks: ['uglify']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
clean: {
|
clean: {
|
||||||
|
|
25
assets/css/main.min.css
vendored
Normal file
|
@ -1,838 +1,3 @@
|
||||||
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
|
|
||||||
/*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
|
|
||||||
|
|
||||||
window.matchMedia = window.matchMedia || (function( doc, undefined ) {
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var bool,
|
|
||||||
docElem = doc.documentElement,
|
|
||||||
refNode = docElem.firstElementChild || docElem.firstChild,
|
|
||||||
// fakeBody required for <FF4 when executed in <head>
|
|
||||||
fakeBody = doc.createElement( "body" ),
|
|
||||||
div = doc.createElement( "div" );
|
|
||||||
|
|
||||||
div.id = "mq-test-1";
|
|
||||||
div.style.cssText = "position:absolute;top:-100em";
|
|
||||||
fakeBody.style.background = "none";
|
|
||||||
fakeBody.appendChild(div);
|
|
||||||
|
|
||||||
return function(q){
|
|
||||||
|
|
||||||
div.innerHTML = "­<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>";
|
|
||||||
|
|
||||||
docElem.insertBefore( fakeBody, refNode );
|
|
||||||
bool = div.offsetWidth === 42;
|
|
||||||
docElem.removeChild( fakeBody );
|
|
||||||
|
|
||||||
return {
|
|
||||||
matches: bool,
|
|
||||||
media: q
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}( document ));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! Respond.js v1.1.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
|
|
||||||
(function( win ){
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
//exposed namespace
|
|
||||||
var respond = {};
|
|
||||||
win.respond = respond;
|
|
||||||
|
|
||||||
//define update even in native-mq-supporting browsers, to avoid errors
|
|
||||||
respond.update = function(){};
|
|
||||||
|
|
||||||
//expose media query support flag for external use
|
|
||||||
respond.mediaQueriesSupported = win.matchMedia && win.matchMedia( "only all" ).matches;
|
|
||||||
|
|
||||||
//if media queries are supported, exit here
|
|
||||||
if( respond.mediaQueriesSupported ){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//define vars
|
|
||||||
var doc = win.document,
|
|
||||||
docElem = doc.documentElement,
|
|
||||||
mediastyles = [],
|
|
||||||
rules = [],
|
|
||||||
appendedEls = [],
|
|
||||||
parsedSheets = {},
|
|
||||||
resizeThrottle = 30,
|
|
||||||
head = doc.getElementsByTagName( "head" )[0] || docElem,
|
|
||||||
base = doc.getElementsByTagName( "base" )[0],
|
|
||||||
links = head.getElementsByTagName( "link" ),
|
|
||||||
requestQueue = [],
|
|
||||||
|
|
||||||
//loop stylesheets, send text content to translate
|
|
||||||
ripCSS = function(){
|
|
||||||
|
|
||||||
for( var i = 0; i < links.length; i++ ){
|
|
||||||
var sheet = links[ i ],
|
|
||||||
href = sheet.href,
|
|
||||||
media = sheet.media,
|
|
||||||
isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
|
|
||||||
|
|
||||||
//only links plz and prevent re-parsing
|
|
||||||
if( !!href && isCSS && !parsedSheets[ href ] ){
|
|
||||||
// selectivizr exposes css through the rawCssText expando
|
|
||||||
if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
|
|
||||||
translate( sheet.styleSheet.rawCssText, href, media );
|
|
||||||
parsedSheets[ href ] = true;
|
|
||||||
} else {
|
|
||||||
if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) ||
|
|
||||||
href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){
|
|
||||||
requestQueue.push( {
|
|
||||||
href: href,
|
|
||||||
media: media
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
makeRequests();
|
|
||||||
},
|
|
||||||
|
|
||||||
//recurse through request queue, get css text
|
|
||||||
makeRequests = function(){
|
|
||||||
if( requestQueue.length ){
|
|
||||||
var thisRequest = requestQueue.shift();
|
|
||||||
|
|
||||||
ajax( thisRequest.href, function( styles ){
|
|
||||||
translate( styles, thisRequest.href, thisRequest.media );
|
|
||||||
parsedSheets[ thisRequest.href ] = true;
|
|
||||||
|
|
||||||
// by wrapping recursive function call in setTimeout
|
|
||||||
// we prevent "Stack overflow" error in IE7
|
|
||||||
win.setTimeout(function(){ makeRequests(); },0);
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//find media blocks in css text, convert to style blocks
|
|
||||||
translate = function( styles, href, media ){
|
|
||||||
var qs = styles.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ),
|
|
||||||
ql = qs && qs.length || 0;
|
|
||||||
|
|
||||||
//try to get CSS path
|
|
||||||
href = href.substring( 0, href.lastIndexOf( "/" ) );
|
|
||||||
|
|
||||||
var repUrls = function( css ){
|
|
||||||
return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" );
|
|
||||||
},
|
|
||||||
useMedia = !ql && media;
|
|
||||||
|
|
||||||
//if path exists, tack on trailing slash
|
|
||||||
if( href.length ){ href += "/"; }
|
|
||||||
|
|
||||||
//if no internal queries exist, but media attr does, use that
|
|
||||||
//note: this currently lacks support for situations where a media attr is specified on a link AND
|
|
||||||
//its associated stylesheet has internal CSS media queries.
|
|
||||||
//In those cases, the media attribute will currently be ignored.
|
|
||||||
if( useMedia ){
|
|
||||||
ql = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( var i = 0; i < ql; i++ ){
|
|
||||||
var fullq, thisq, eachq, eql;
|
|
||||||
|
|
||||||
//media attr
|
|
||||||
if( useMedia ){
|
|
||||||
fullq = media;
|
|
||||||
rules.push( repUrls( styles ) );
|
|
||||||
}
|
|
||||||
//parse for styles
|
|
||||||
else{
|
|
||||||
fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1;
|
|
||||||
rules.push( RegExp.$2 && repUrls( RegExp.$2 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
eachq = fullq.split( "," );
|
|
||||||
eql = eachq.length;
|
|
||||||
|
|
||||||
for( var j = 0; j < eql; j++ ){
|
|
||||||
thisq = eachq[ j ];
|
|
||||||
mediastyles.push( {
|
|
||||||
media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all",
|
|
||||||
rules : rules.length - 1,
|
|
||||||
hasquery : thisq.indexOf("(") > -1,
|
|
||||||
minw : thisq.match( /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
|
|
||||||
maxw : thisq.match( /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" )
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyMedia();
|
|
||||||
},
|
|
||||||
|
|
||||||
lastCall,
|
|
||||||
|
|
||||||
resizeDefer,
|
|
||||||
|
|
||||||
// returns the value of 1em in pixels
|
|
||||||
getEmValue = function() {
|
|
||||||
var ret,
|
|
||||||
div = doc.createElement('div'),
|
|
||||||
body = doc.body,
|
|
||||||
fakeUsed = false;
|
|
||||||
|
|
||||||
div.style.cssText = "position:absolute;font-size:1em;width:1em";
|
|
||||||
|
|
||||||
if( !body ){
|
|
||||||
body = fakeUsed = doc.createElement( "body" );
|
|
||||||
body.style.background = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
body.appendChild( div );
|
|
||||||
|
|
||||||
docElem.insertBefore( body, docElem.firstChild );
|
|
||||||
|
|
||||||
ret = div.offsetWidth;
|
|
||||||
|
|
||||||
if( fakeUsed ){
|
|
||||||
docElem.removeChild( body );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
body.removeChild( div );
|
|
||||||
}
|
|
||||||
|
|
||||||
//also update eminpx before returning
|
|
||||||
ret = eminpx = parseFloat(ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
},
|
|
||||||
|
|
||||||
//cached container for 1em value, populated the first time it's needed
|
|
||||||
eminpx,
|
|
||||||
|
|
||||||
//enable/disable styles
|
|
||||||
applyMedia = function( fromResize ){
|
|
||||||
var name = "clientWidth",
|
|
||||||
docElemProp = docElem[ name ],
|
|
||||||
currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp,
|
|
||||||
styleBlocks = {},
|
|
||||||
lastLink = links[ links.length-1 ],
|
|
||||||
now = (new Date()).getTime();
|
|
||||||
|
|
||||||
//throttle resize calls
|
|
||||||
if( fromResize && lastCall && now - lastCall < resizeThrottle ){
|
|
||||||
win.clearTimeout( resizeDefer );
|
|
||||||
resizeDefer = win.setTimeout( applyMedia, resizeThrottle );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lastCall = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( var i in mediastyles ){
|
|
||||||
if( mediastyles.hasOwnProperty( i ) ){
|
|
||||||
var thisstyle = mediastyles[ i ],
|
|
||||||
min = thisstyle.minw,
|
|
||||||
max = thisstyle.maxw,
|
|
||||||
minnull = min === null,
|
|
||||||
maxnull = max === null,
|
|
||||||
em = "em";
|
|
||||||
|
|
||||||
if( !!min ){
|
|
||||||
min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
|
|
||||||
}
|
|
||||||
if( !!max ){
|
|
||||||
max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true
|
|
||||||
if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){
|
|
||||||
if( !styleBlocks[ thisstyle.media ] ){
|
|
||||||
styleBlocks[ thisstyle.media ] = [];
|
|
||||||
}
|
|
||||||
styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//remove any existing respond style element(s)
|
|
||||||
for( var j in appendedEls ){
|
|
||||||
if( appendedEls.hasOwnProperty( j ) ){
|
|
||||||
if( appendedEls[ j ] && appendedEls[ j ].parentNode === head ){
|
|
||||||
head.removeChild( appendedEls[ j ] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//inject active styles, grouped by media type
|
|
||||||
for( var k in styleBlocks ){
|
|
||||||
if( styleBlocks.hasOwnProperty( k ) ){
|
|
||||||
var ss = doc.createElement( "style" ),
|
|
||||||
css = styleBlocks[ k ].join( "\n" );
|
|
||||||
|
|
||||||
ss.type = "text/css";
|
|
||||||
ss.media = k;
|
|
||||||
|
|
||||||
//originally, ss was appended to a documentFragment and sheets were appended in bulk.
|
|
||||||
//this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one!
|
|
||||||
head.insertBefore( ss, lastLink.nextSibling );
|
|
||||||
|
|
||||||
if ( ss.styleSheet ){
|
|
||||||
ss.styleSheet.cssText = css;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ss.appendChild( doc.createTextNode( css ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//push to appendedEls to track for later removal
|
|
||||||
appendedEls.push( ss );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
//tweaked Ajax functions from Quirksmode
|
|
||||||
ajax = function( url, callback ) {
|
|
||||||
var req = xmlHttp();
|
|
||||||
if (!req){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req.open( "GET", url, true );
|
|
||||||
req.onreadystatechange = function () {
|
|
||||||
if ( req.readyState !== 4 || req.status !== 200 && req.status !== 304 ){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback( req.responseText );
|
|
||||||
};
|
|
||||||
if ( req.readyState === 4 ){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
req.send( null );
|
|
||||||
},
|
|
||||||
//define ajax obj
|
|
||||||
xmlHttp = (function() {
|
|
||||||
var xmlhttpmethod = false;
|
|
||||||
try {
|
|
||||||
xmlhttpmethod = new win.XMLHttpRequest();
|
|
||||||
}
|
|
||||||
catch( e ){
|
|
||||||
xmlhttpmethod = new win.ActiveXObject( "Microsoft.XMLHTTP" );
|
|
||||||
}
|
|
||||||
return function(){
|
|
||||||
return xmlhttpmethod;
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
//translate CSS
|
|
||||||
ripCSS();
|
|
||||||
|
|
||||||
//expose update for re-running respond later on
|
|
||||||
respond.update = ripCSS;
|
|
||||||
|
|
||||||
//adjust on resize
|
|
||||||
function callMedia(){
|
|
||||||
applyMedia( true );
|
|
||||||
}
|
|
||||||
if( win.addEventListener ){
|
|
||||||
win.addEventListener( "resize", callMedia, false );
|
|
||||||
}
|
|
||||||
else if( win.attachEvent ){
|
|
||||||
win.attachEvent( "onresize", callMedia );
|
|
||||||
}
|
|
||||||
})(this);
|
|
||||||
|
|
||||||
/*! responsive-nav.js v1.0.14
|
|
||||||
* https://github.com/viljamis/responsive-nav.js
|
|
||||||
* http://responsive-nav.com
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 @viljamis
|
|
||||||
* Available under the MIT license
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* jshint strict:false, forin:false, noarg:true, noempty:true, eqeqeq:true,
|
|
||||||
boss:true, bitwise:true, browser:true, devel:true, indent:2 */
|
|
||||||
/* exported responsiveNav */
|
|
||||||
|
|
||||||
var responsiveNav = (function (window, document) {
|
|
||||||
|
|
||||||
var computed = !!window.getComputedStyle;
|
|
||||||
|
|
||||||
// getComputedStyle polyfill
|
|
||||||
if (!window.getComputedStyle) {
|
|
||||||
window.getComputedStyle = function(el) {
|
|
||||||
this.el = el;
|
|
||||||
this.getPropertyValue = function(prop) {
|
|
||||||
var re = /(\-([a-z]){1})/g;
|
|
||||||
if (prop === "float") {
|
|
||||||
prop = "styleFloat";
|
|
||||||
}
|
|
||||||
if (re.test(prop)) {
|
|
||||||
prop = prop.replace(re, function () {
|
|
||||||
return arguments[2].toUpperCase();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return el.currentStyle[prop] ? el.currentStyle[prop] : null;
|
|
||||||
};
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var nav,
|
|
||||||
opts,
|
|
||||||
navToggle,
|
|
||||||
docEl = document.documentElement,
|
|
||||||
head = document.getElementsByTagName("head")[0],
|
|
||||||
styleElement = document.createElement("style"),
|
|
||||||
navOpen = false,
|
|
||||||
|
|
||||||
// fn arg can be an object or a function, thanks to handleEvent
|
|
||||||
// read more at: http://www.thecssninja.com/javascript/handleevent
|
|
||||||
addEvent = function (el, evt, fn, bubble) {
|
|
||||||
if ("addEventListener" in el) {
|
|
||||||
// BBOS6 doesn't support handleEvent, catch and polyfill
|
|
||||||
try {
|
|
||||||
el.addEventListener(evt, fn, bubble);
|
|
||||||
} catch (e) {
|
|
||||||
if (typeof fn === "object" && fn.handleEvent) {
|
|
||||||
el.addEventListener(evt, function (e) {
|
|
||||||
// Bind fn as this and set first arg as event object
|
|
||||||
fn.handleEvent.call(fn, e);
|
|
||||||
}, bubble);
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ("attachEvent" in el) {
|
|
||||||
// check if the callback is an object and contains handleEvent
|
|
||||||
if (typeof fn === "object" && fn.handleEvent) {
|
|
||||||
el.attachEvent("on" + evt, function () {
|
|
||||||
// Bind fn as this
|
|
||||||
fn.handleEvent.call(fn);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
el.attachEvent("on" + evt, fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
removeEvent = function (el, evt, fn, bubble) {
|
|
||||||
if ("removeEventListener" in el) {
|
|
||||||
try {
|
|
||||||
el.removeEventListener(evt, fn, bubble);
|
|
||||||
} catch (e) {
|
|
||||||
if (typeof fn === "object" && fn.handleEvent) {
|
|
||||||
el.removeEventListener(evt, function (e) {
|
|
||||||
fn.handleEvent.call(fn, e);
|
|
||||||
}, bubble);
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ("detachEvent" in el) {
|
|
||||||
if (typeof fn === "object" && fn.handleEvent) {
|
|
||||||
el.detachEvent("on" + evt, function () {
|
|
||||||
fn.handleEvent.call(fn);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
el.detachEvent("on" + evt, fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getFirstChild = function (e) {
|
|
||||||
var firstChild = e.firstChild;
|
|
||||||
// skip TextNodes
|
|
||||||
while (firstChild !== null && firstChild.nodeType !== 1) {
|
|
||||||
firstChild = firstChild.nextSibling;
|
|
||||||
}
|
|
||||||
return firstChild;
|
|
||||||
},
|
|
||||||
|
|
||||||
setAttributes = function (el, attrs) {
|
|
||||||
for (var key in attrs) {
|
|
||||||
el.setAttribute(key, attrs[key]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
addClass = function (el, cls) {
|
|
||||||
el.className += " " + cls;
|
|
||||||
el.className = el.className.replace(/(^\s*)|(\s*$)/g,"");
|
|
||||||
},
|
|
||||||
|
|
||||||
removeClass = function (el, cls) {
|
|
||||||
var reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
|
|
||||||
el.className = el.className.replace(reg, " ").replace(/(^\s*)|(\s*$)/g,"");
|
|
||||||
},
|
|
||||||
|
|
||||||
ResponsiveNav = function (el, options) {
|
|
||||||
var i;
|
|
||||||
|
|
||||||
// Default options
|
|
||||||
this.options = {
|
|
||||||
animate: true, // Boolean: Use CSS3 transitions, true or false
|
|
||||||
transition: 400, // Integer: Speed of the transition, in milliseconds
|
|
||||||
label: "Menu", // String: Label for the navigation toggle
|
|
||||||
insert: "after", // String: Insert the toggle before or after the navigation
|
|
||||||
customToggle: "", // Selector: Specify the ID of a custom toggle
|
|
||||||
openPos: "relative", // String: Position of the opened nav, relative or static
|
|
||||||
jsClass: "js", // String: 'JS enabled' class which is added to <html> el
|
|
||||||
init: function(){}, // Function: Init callback
|
|
||||||
open: function(){}, // Function: Open callback
|
|
||||||
close: function(){} // Function: Close callback
|
|
||||||
};
|
|
||||||
|
|
||||||
// User defined options
|
|
||||||
for (i in options) {
|
|
||||||
this.options[i] = options[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds "js" class for <html>
|
|
||||||
addClass(docEl, this.options.jsClass);
|
|
||||||
|
|
||||||
// Wrapper
|
|
||||||
this.wrapperEl = el.replace("#", "");
|
|
||||||
if (document.getElementById(this.wrapperEl)) {
|
|
||||||
this.wrapper = document.getElementById(this.wrapperEl);
|
|
||||||
} else {
|
|
||||||
// If el doesn't exists, stop here.
|
|
||||||
throw new Error("The nav element you are trying to select doesn't exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inner wrapper
|
|
||||||
this.wrapper.inner = getFirstChild(this.wrapper);
|
|
||||||
|
|
||||||
// For minification
|
|
||||||
opts = this.options;
|
|
||||||
nav = this.wrapper;
|
|
||||||
|
|
||||||
// Init
|
|
||||||
this._init(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
ResponsiveNav.prototype = {
|
|
||||||
// Public methods
|
|
||||||
destroy: function () {
|
|
||||||
this._removeStyles();
|
|
||||||
removeClass(nav, "closed");
|
|
||||||
removeClass(nav, "opened");
|
|
||||||
nav.removeAttribute("style");
|
|
||||||
nav.removeAttribute("aria-hidden");
|
|
||||||
nav = null;
|
|
||||||
_instance = null;
|
|
||||||
|
|
||||||
removeEvent(window, "load", this, false);
|
|
||||||
removeEvent(window, "resize", this, false);
|
|
||||||
removeEvent(navToggle, "mousedown", this, false);
|
|
||||||
removeEvent(navToggle, "touchstart", this, false);
|
|
||||||
removeEvent(navToggle, "touchend", this, false);
|
|
||||||
removeEvent(navToggle, "keyup", this, false);
|
|
||||||
removeEvent(navToggle, "click", this, false);
|
|
||||||
|
|
||||||
if (!opts.customToggle) {
|
|
||||||
navToggle.parentNode.removeChild(navToggle);
|
|
||||||
} else {
|
|
||||||
navToggle.removeAttribute("aria-hidden");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
toggle: function () {
|
|
||||||
if (!navOpen) {
|
|
||||||
removeClass(nav, "closed");
|
|
||||||
addClass(nav, "opened");
|
|
||||||
nav.style.position = opts.openPos;
|
|
||||||
setAttributes(nav, {"aria-hidden": "false"});
|
|
||||||
|
|
||||||
navOpen = true;
|
|
||||||
opts.open();
|
|
||||||
} else {
|
|
||||||
removeClass(nav, "opened");
|
|
||||||
addClass(nav, "closed");
|
|
||||||
setAttributes(nav, {"aria-hidden": "true"});
|
|
||||||
|
|
||||||
if (opts.animate) {
|
|
||||||
setTimeout(function () {
|
|
||||||
nav.style.position = "relative";
|
|
||||||
}, opts.transition + 10);
|
|
||||||
} else {
|
|
||||||
nav.style.position = "relative";
|
|
||||||
}
|
|
||||||
|
|
||||||
navOpen = false;
|
|
||||||
opts.close();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleEvent: function (e) {
|
|
||||||
var evt = e || window.event;
|
|
||||||
|
|
||||||
switch (evt.type) {
|
|
||||||
case "mousedown":
|
|
||||||
this._onmousedown(evt);
|
|
||||||
break;
|
|
||||||
case "touchstart":
|
|
||||||
this._ontouchstart(evt);
|
|
||||||
break;
|
|
||||||
case "touchend":
|
|
||||||
this._ontouchend(evt);
|
|
||||||
break;
|
|
||||||
case "keyup":
|
|
||||||
this._onkeyup(evt);
|
|
||||||
break;
|
|
||||||
case "click":
|
|
||||||
this._onclick(evt);
|
|
||||||
break;
|
|
||||||
case "load":
|
|
||||||
this._transitions(evt);
|
|
||||||
this._resize(evt);
|
|
||||||
break;
|
|
||||||
case "resize":
|
|
||||||
this._resize(evt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Private methods
|
|
||||||
_init: function () {
|
|
||||||
addClass(nav, "closed");
|
|
||||||
this._createToggle();
|
|
||||||
|
|
||||||
addEvent(window, "load", this, false);
|
|
||||||
addEvent(window, "resize", this, false);
|
|
||||||
addEvent(navToggle, "mousedown", this, false);
|
|
||||||
addEvent(navToggle, "touchstart", this, false);
|
|
||||||
addEvent(navToggle, "touchend", this, false);
|
|
||||||
addEvent(navToggle, "keyup", this, false);
|
|
||||||
addEvent(navToggle, "click", this, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
_createStyles: function () {
|
|
||||||
if (!styleElement.parentNode) {
|
|
||||||
head.appendChild(styleElement);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_removeStyles: function () {
|
|
||||||
if (styleElement.parentNode) {
|
|
||||||
styleElement.parentNode.removeChild(styleElement);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_createToggle: function () {
|
|
||||||
if (!opts.customToggle) {
|
|
||||||
var toggle = document.createElement("a");
|
|
||||||
toggle.innerHTML = opts.label;
|
|
||||||
setAttributes(toggle, {
|
|
||||||
"href": "#",
|
|
||||||
"id": "nav-toggle"
|
|
||||||
});
|
|
||||||
|
|
||||||
if (opts.insert === "after") {
|
|
||||||
nav.parentNode.insertBefore(toggle, nav.nextSibling);
|
|
||||||
} else {
|
|
||||||
nav.parentNode.insertBefore(toggle, nav);
|
|
||||||
}
|
|
||||||
|
|
||||||
navToggle = document.getElementById("nav-toggle");
|
|
||||||
} else {
|
|
||||||
var toggleEl = opts.customToggle.replace("#", "");
|
|
||||||
|
|
||||||
if (document.getElementById(toggleEl)) {
|
|
||||||
navToggle = document.getElementById(toggleEl);
|
|
||||||
} else {
|
|
||||||
throw new Error("The custom nav toggle you are trying to select doesn't exist");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_preventDefault: function(e) {
|
|
||||||
if (e.preventDefault) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
} else {
|
|
||||||
e.returnValue = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onmousedown: function (e) {
|
|
||||||
var evt = e || window.event;
|
|
||||||
// If the user isn't right clicking:
|
|
||||||
if (!(evt.which === 3 || evt.button === 2)) {
|
|
||||||
this._preventDefault(e);
|
|
||||||
this.toggle(e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_ontouchstart: function (e) {
|
|
||||||
// Touchstart event fires before
|
|
||||||
// the mousedown and can wipe it
|
|
||||||
navToggle.onmousedown = null;
|
|
||||||
this._preventDefault(e);
|
|
||||||
this.toggle(e);
|
|
||||||
},
|
|
||||||
|
|
||||||
_ontouchend: function () {
|
|
||||||
// Prevents ghost click from happening on some Android browsers
|
|
||||||
var that = this;
|
|
||||||
nav.addEventListener("click", that._preventDefault, true);
|
|
||||||
setTimeout(function () {
|
|
||||||
nav.removeEventListener("click", that._preventDefault, true);
|
|
||||||
}, opts.transition);
|
|
||||||
},
|
|
||||||
|
|
||||||
_onkeyup: function (e) {
|
|
||||||
var evt = e || window.event;
|
|
||||||
if (evt.keyCode === 13) {
|
|
||||||
this.toggle(e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_onclick: function (e) {
|
|
||||||
// For older browsers (looking at IE)
|
|
||||||
this._preventDefault(e);
|
|
||||||
},
|
|
||||||
|
|
||||||
_transitions: function () {
|
|
||||||
if (opts.animate) {
|
|
||||||
var objStyle = nav.style,
|
|
||||||
transition = "max-height " + opts.transition + "ms";
|
|
||||||
|
|
||||||
objStyle.WebkitTransition = transition;
|
|
||||||
objStyle.MozTransition = transition;
|
|
||||||
objStyle.OTransition = transition;
|
|
||||||
objStyle.transition = transition;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_calcHeight: function () {
|
|
||||||
var savedHeight = nav.inner.offsetHeight,
|
|
||||||
innerStyles = "#" + this.wrapperEl + ".opened{max-height:" + savedHeight + "px}";
|
|
||||||
|
|
||||||
// Hide from old IE
|
|
||||||
if (computed) {
|
|
||||||
styleElement.innerHTML = innerStyles;
|
|
||||||
innerStyles = "";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_resize: function () {
|
|
||||||
if (window.getComputedStyle(navToggle, null).getPropertyValue("display") !== "none") {
|
|
||||||
setAttributes(navToggle, {"aria-hidden": "false"});
|
|
||||||
|
|
||||||
// If the navigation is hidden
|
|
||||||
if (nav.className.match(/(^|\s)closed(\s|$)/)) {
|
|
||||||
setAttributes(nav, {"aria-hidden": "true"});
|
|
||||||
nav.style.position = "absolute";
|
|
||||||
}
|
|
||||||
|
|
||||||
this._createStyles();
|
|
||||||
this._calcHeight();
|
|
||||||
} else {
|
|
||||||
setAttributes(navToggle, {"aria-hidden": "true"});
|
|
||||||
setAttributes(nav, {"aria-hidden": "false"});
|
|
||||||
nav.style.position = opts.openPos;
|
|
||||||
this._removeStyles();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init callback
|
|
||||||
opts.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var _instance;
|
|
||||||
function rn (el, options) {
|
|
||||||
if (!_instance) {
|
|
||||||
_instance = new ResponsiveNav(el, options);
|
|
||||||
}
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rn;
|
|
||||||
})(window, document);
|
|
||||||
|
|
||||||
|
|
||||||
/*global jQuery */
|
|
||||||
/*jshint multistr:true browser:true */
|
|
||||||
/*!
|
|
||||||
* FitVids 1.0
|
|
||||||
*
|
|
||||||
* Copyright 2011, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com
|
|
||||||
* Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/
|
|
||||||
* Released under the WTFPL license - http://sam.zoy.org/wtfpl/
|
|
||||||
*
|
|
||||||
* Date: Thu Sept 01 18:00:00 2011 -0500
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function( $ ){
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
$.fn.fitVids = function( options ) {
|
|
||||||
var settings = {
|
|
||||||
customSelector: null
|
|
||||||
};
|
|
||||||
|
|
||||||
var div = document.createElement('div'),
|
|
||||||
ref = document.getElementsByTagName('base')[0] || document.getElementsByTagName('script')[0];
|
|
||||||
|
|
||||||
div.className = 'fit-vids-style';
|
|
||||||
div.innerHTML = '­<style> \
|
|
||||||
.fluid-width-video-wrapper { \
|
|
||||||
width: 100%; \
|
|
||||||
position: relative; \
|
|
||||||
padding: 0; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
.fluid-width-video-wrapper iframe, \
|
|
||||||
.fluid-width-video-wrapper object, \
|
|
||||||
.fluid-width-video-wrapper embed { \
|
|
||||||
position: absolute; \
|
|
||||||
top: 0; \
|
|
||||||
left: 0; \
|
|
||||||
width: 100%; \
|
|
||||||
height: 100%; \
|
|
||||||
} \
|
|
||||||
</style>';
|
|
||||||
|
|
||||||
ref.parentNode.insertBefore(div,ref);
|
|
||||||
|
|
||||||
if ( options ) {
|
|
||||||
$.extend( settings, options );
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.each(function(){
|
|
||||||
var selectors = [
|
|
||||||
"iframe[src*='player.vimeo.com']",
|
|
||||||
"iframe[src*='www.youtube.com']",
|
|
||||||
"iframe[src*='www.youtube-nocookie.com']",
|
|
||||||
"iframe[src*='www.kickstarter.com']",
|
|
||||||
"object",
|
|
||||||
"embed"
|
|
||||||
];
|
|
||||||
|
|
||||||
if (settings.customSelector) {
|
|
||||||
selectors.push(settings.customSelector);
|
|
||||||
}
|
|
||||||
|
|
||||||
var $allVideos = $(this).find(selectors.join(','));
|
|
||||||
|
|
||||||
$allVideos.each(function(){
|
|
||||||
var $this = $(this);
|
|
||||||
if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; }
|
|
||||||
var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(),
|
|
||||||
width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(),
|
|
||||||
aspectRatio = height / width;
|
|
||||||
if(!$this.attr('id')){
|
|
||||||
var videoID = 'fitvid' + Math.floor(Math.random()*999999);
|
|
||||||
$this.attr('id', videoID);
|
|
||||||
}
|
|
||||||
$this.wrap('<div class="fluid-width-video-wrapper"></div>').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+"%");
|
|
||||||
$this.removeAttr('height').removeAttr('width');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
})( jQuery );
|
|
||||||
|
|
||||||
/*! Plugin options and other jQuery stuff */
|
/*! Plugin options and other jQuery stuff */
|
||||||
|
|
||||||
// Responsive Nav
|
// Responsive Nav
|
||||||
|
|
408
assets/js/plugins/responsive-nav.js
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
/*! responsive-nav.js v1.0.14
|
||||||
|
* https://github.com/viljamis/responsive-nav.js
|
||||||
|
* http://responsive-nav.com
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 @viljamis
|
||||||
|
* Available under the MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* jshint strict:false, forin:false, noarg:true, noempty:true, eqeqeq:true,
|
||||||
|
boss:true, bitwise:true, browser:true, devel:true, indent:2 */
|
||||||
|
/* exported responsiveNav */
|
||||||
|
|
||||||
|
var responsiveNav = (function (window, document) {
|
||||||
|
|
||||||
|
var computed = !!window.getComputedStyle;
|
||||||
|
|
||||||
|
// getComputedStyle polyfill
|
||||||
|
if (!window.getComputedStyle) {
|
||||||
|
window.getComputedStyle = function(el) {
|
||||||
|
this.el = el;
|
||||||
|
this.getPropertyValue = function(prop) {
|
||||||
|
var re = /(\-([a-z]){1})/g;
|
||||||
|
if (prop === "float") {
|
||||||
|
prop = "styleFloat";
|
||||||
|
}
|
||||||
|
if (re.test(prop)) {
|
||||||
|
prop = prop.replace(re, function () {
|
||||||
|
return arguments[2].toUpperCase();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return el.currentStyle[prop] ? el.currentStyle[prop] : null;
|
||||||
|
};
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var nav,
|
||||||
|
opts,
|
||||||
|
navToggle,
|
||||||
|
docEl = document.documentElement,
|
||||||
|
head = document.getElementsByTagName("head")[0],
|
||||||
|
styleElement = document.createElement("style"),
|
||||||
|
navOpen = false,
|
||||||
|
|
||||||
|
// fn arg can be an object or a function, thanks to handleEvent
|
||||||
|
// read more at: http://www.thecssninja.com/javascript/handleevent
|
||||||
|
addEvent = function (el, evt, fn, bubble) {
|
||||||
|
if ("addEventListener" in el) {
|
||||||
|
// BBOS6 doesn't support handleEvent, catch and polyfill
|
||||||
|
try {
|
||||||
|
el.addEventListener(evt, fn, bubble);
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof fn === "object" && fn.handleEvent) {
|
||||||
|
el.addEventListener(evt, function (e) {
|
||||||
|
// Bind fn as this and set first arg as event object
|
||||||
|
fn.handleEvent.call(fn, e);
|
||||||
|
}, bubble);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ("attachEvent" in el) {
|
||||||
|
// check if the callback is an object and contains handleEvent
|
||||||
|
if (typeof fn === "object" && fn.handleEvent) {
|
||||||
|
el.attachEvent("on" + evt, function () {
|
||||||
|
// Bind fn as this
|
||||||
|
fn.handleEvent.call(fn);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
el.attachEvent("on" + evt, fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
removeEvent = function (el, evt, fn, bubble) {
|
||||||
|
if ("removeEventListener" in el) {
|
||||||
|
try {
|
||||||
|
el.removeEventListener(evt, fn, bubble);
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof fn === "object" && fn.handleEvent) {
|
||||||
|
el.removeEventListener(evt, function (e) {
|
||||||
|
fn.handleEvent.call(fn, e);
|
||||||
|
}, bubble);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ("detachEvent" in el) {
|
||||||
|
if (typeof fn === "object" && fn.handleEvent) {
|
||||||
|
el.detachEvent("on" + evt, function () {
|
||||||
|
fn.handleEvent.call(fn);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
el.detachEvent("on" + evt, fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getFirstChild = function (e) {
|
||||||
|
var firstChild = e.firstChild;
|
||||||
|
// skip TextNodes
|
||||||
|
while (firstChild !== null && firstChild.nodeType !== 1) {
|
||||||
|
firstChild = firstChild.nextSibling;
|
||||||
|
}
|
||||||
|
return firstChild;
|
||||||
|
},
|
||||||
|
|
||||||
|
setAttributes = function (el, attrs) {
|
||||||
|
for (var key in attrs) {
|
||||||
|
el.setAttribute(key, attrs[key]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addClass = function (el, cls) {
|
||||||
|
el.className += " " + cls;
|
||||||
|
el.className = el.className.replace(/(^\s*)|(\s*$)/g,"");
|
||||||
|
},
|
||||||
|
|
||||||
|
removeClass = function (el, cls) {
|
||||||
|
var reg = new RegExp("(\\s|^)" + cls + "(\\s|$)");
|
||||||
|
el.className = el.className.replace(reg, " ").replace(/(^\s*)|(\s*$)/g,"");
|
||||||
|
},
|
||||||
|
|
||||||
|
ResponsiveNav = function (el, options) {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
// Default options
|
||||||
|
this.options = {
|
||||||
|
animate: true, // Boolean: Use CSS3 transitions, true or false
|
||||||
|
transition: 400, // Integer: Speed of the transition, in milliseconds
|
||||||
|
label: "Menu", // String: Label for the navigation toggle
|
||||||
|
insert: "after", // String: Insert the toggle before or after the navigation
|
||||||
|
customToggle: "", // Selector: Specify the ID of a custom toggle
|
||||||
|
openPos: "relative", // String: Position of the opened nav, relative or static
|
||||||
|
jsClass: "js", // String: 'JS enabled' class which is added to <html> el
|
||||||
|
init: function(){}, // Function: Init callback
|
||||||
|
open: function(){}, // Function: Open callback
|
||||||
|
close: function(){} // Function: Close callback
|
||||||
|
};
|
||||||
|
|
||||||
|
// User defined options
|
||||||
|
for (i in options) {
|
||||||
|
this.options[i] = options[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds "js" class for <html>
|
||||||
|
addClass(docEl, this.options.jsClass);
|
||||||
|
|
||||||
|
// Wrapper
|
||||||
|
this.wrapperEl = el.replace("#", "");
|
||||||
|
if (document.getElementById(this.wrapperEl)) {
|
||||||
|
this.wrapper = document.getElementById(this.wrapperEl);
|
||||||
|
} else {
|
||||||
|
// If el doesn't exists, stop here.
|
||||||
|
throw new Error("The nav element you are trying to select doesn't exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner wrapper
|
||||||
|
this.wrapper.inner = getFirstChild(this.wrapper);
|
||||||
|
|
||||||
|
// For minification
|
||||||
|
opts = this.options;
|
||||||
|
nav = this.wrapper;
|
||||||
|
|
||||||
|
// Init
|
||||||
|
this._init(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
ResponsiveNav.prototype = {
|
||||||
|
// Public methods
|
||||||
|
destroy: function () {
|
||||||
|
this._removeStyles();
|
||||||
|
removeClass(nav, "closed");
|
||||||
|
removeClass(nav, "opened");
|
||||||
|
nav.removeAttribute("style");
|
||||||
|
nav.removeAttribute("aria-hidden");
|
||||||
|
nav = null;
|
||||||
|
_instance = null;
|
||||||
|
|
||||||
|
removeEvent(window, "load", this, false);
|
||||||
|
removeEvent(window, "resize", this, false);
|
||||||
|
removeEvent(navToggle, "mousedown", this, false);
|
||||||
|
removeEvent(navToggle, "touchstart", this, false);
|
||||||
|
removeEvent(navToggle, "touchend", this, false);
|
||||||
|
removeEvent(navToggle, "keyup", this, false);
|
||||||
|
removeEvent(navToggle, "click", this, false);
|
||||||
|
|
||||||
|
if (!opts.customToggle) {
|
||||||
|
navToggle.parentNode.removeChild(navToggle);
|
||||||
|
} else {
|
||||||
|
navToggle.removeAttribute("aria-hidden");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
toggle: function () {
|
||||||
|
if (!navOpen) {
|
||||||
|
removeClass(nav, "closed");
|
||||||
|
addClass(nav, "opened");
|
||||||
|
nav.style.position = opts.openPos;
|
||||||
|
setAttributes(nav, {"aria-hidden": "false"});
|
||||||
|
|
||||||
|
navOpen = true;
|
||||||
|
opts.open();
|
||||||
|
} else {
|
||||||
|
removeClass(nav, "opened");
|
||||||
|
addClass(nav, "closed");
|
||||||
|
setAttributes(nav, {"aria-hidden": "true"});
|
||||||
|
|
||||||
|
if (opts.animate) {
|
||||||
|
setTimeout(function () {
|
||||||
|
nav.style.position = "absolute";
|
||||||
|
}, opts.transition + 10);
|
||||||
|
} else {
|
||||||
|
nav.style.position = "absolute";
|
||||||
|
}
|
||||||
|
|
||||||
|
navOpen = false;
|
||||||
|
opts.close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEvent: function (e) {
|
||||||
|
var evt = e || window.event;
|
||||||
|
|
||||||
|
switch (evt.type) {
|
||||||
|
case "mousedown":
|
||||||
|
this._onmousedown(evt);
|
||||||
|
break;
|
||||||
|
case "touchstart":
|
||||||
|
this._ontouchstart(evt);
|
||||||
|
break;
|
||||||
|
case "touchend":
|
||||||
|
this._ontouchend(evt);
|
||||||
|
break;
|
||||||
|
case "keyup":
|
||||||
|
this._onkeyup(evt);
|
||||||
|
break;
|
||||||
|
case "click":
|
||||||
|
this._onclick(evt);
|
||||||
|
break;
|
||||||
|
case "load":
|
||||||
|
this._transitions(evt);
|
||||||
|
this._resize(evt);
|
||||||
|
break;
|
||||||
|
case "resize":
|
||||||
|
this._resize(evt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Private methods
|
||||||
|
_init: function () {
|
||||||
|
addClass(nav, "closed");
|
||||||
|
this._createToggle();
|
||||||
|
|
||||||
|
addEvent(window, "load", this, false);
|
||||||
|
addEvent(window, "resize", this, false);
|
||||||
|
addEvent(navToggle, "mousedown", this, false);
|
||||||
|
addEvent(navToggle, "touchstart", this, false);
|
||||||
|
addEvent(navToggle, "touchend", this, false);
|
||||||
|
addEvent(navToggle, "keyup", this, false);
|
||||||
|
addEvent(navToggle, "click", this, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
_createStyles: function () {
|
||||||
|
if (!styleElement.parentNode) {
|
||||||
|
head.appendChild(styleElement);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_removeStyles: function () {
|
||||||
|
if (styleElement.parentNode) {
|
||||||
|
styleElement.parentNode.removeChild(styleElement);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_createToggle: function () {
|
||||||
|
if (!opts.customToggle) {
|
||||||
|
var toggle = document.createElement("a");
|
||||||
|
toggle.innerHTML = opts.label;
|
||||||
|
setAttributes(toggle, {
|
||||||
|
"href": "#",
|
||||||
|
"id": "nav-toggle"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (opts.insert === "after") {
|
||||||
|
nav.parentNode.insertBefore(toggle, nav.nextSibling);
|
||||||
|
} else {
|
||||||
|
nav.parentNode.insertBefore(toggle, nav);
|
||||||
|
}
|
||||||
|
|
||||||
|
navToggle = document.getElementById("nav-toggle");
|
||||||
|
} else {
|
||||||
|
var toggleEl = opts.customToggle.replace("#", "");
|
||||||
|
|
||||||
|
if (document.getElementById(toggleEl)) {
|
||||||
|
navToggle = document.getElementById(toggleEl);
|
||||||
|
} else {
|
||||||
|
throw new Error("The custom nav toggle you are trying to select doesn't exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_preventDefault: function(e) {
|
||||||
|
if (e.preventDefault) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
} else {
|
||||||
|
e.returnValue = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onmousedown: function (e) {
|
||||||
|
var evt = e || window.event;
|
||||||
|
// If the user isn't right clicking:
|
||||||
|
if (!(evt.which === 3 || evt.button === 2)) {
|
||||||
|
this._preventDefault(e);
|
||||||
|
this.toggle(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_ontouchstart: function (e) {
|
||||||
|
// Touchstart event fires before
|
||||||
|
// the mousedown and can wipe it
|
||||||
|
navToggle.onmousedown = null;
|
||||||
|
this._preventDefault(e);
|
||||||
|
this.toggle(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_ontouchend: function () {
|
||||||
|
// Prevents ghost click from happening on some Android browsers
|
||||||
|
var that = this;
|
||||||
|
nav.addEventListener("click", that._preventDefault, true);
|
||||||
|
setTimeout(function () {
|
||||||
|
nav.removeEventListener("click", that._preventDefault, true);
|
||||||
|
}, opts.transition);
|
||||||
|
},
|
||||||
|
|
||||||
|
_onkeyup: function (e) {
|
||||||
|
var evt = e || window.event;
|
||||||
|
if (evt.keyCode === 13) {
|
||||||
|
this.toggle(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onclick: function (e) {
|
||||||
|
// For older browsers (looking at IE)
|
||||||
|
this._preventDefault(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
_transitions: function () {
|
||||||
|
if (opts.animate) {
|
||||||
|
var objStyle = nav.style,
|
||||||
|
transition = "max-height " + opts.transition + "ms";
|
||||||
|
|
||||||
|
objStyle.WebkitTransition = transition;
|
||||||
|
objStyle.MozTransition = transition;
|
||||||
|
objStyle.OTransition = transition;
|
||||||
|
objStyle.transition = transition;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_calcHeight: function () {
|
||||||
|
var savedHeight = nav.inner.offsetHeight,
|
||||||
|
innerStyles = "#" + this.wrapperEl + ".opened{max-height:" + savedHeight + "px}";
|
||||||
|
|
||||||
|
// Hide from old IE
|
||||||
|
if (computed) {
|
||||||
|
styleElement.innerHTML = innerStyles;
|
||||||
|
innerStyles = "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_resize: function () {
|
||||||
|
if (window.getComputedStyle(navToggle, null).getPropertyValue("display") !== "none") {
|
||||||
|
setAttributes(navToggle, {"aria-hidden": "false"});
|
||||||
|
|
||||||
|
// If the navigation is hidden
|
||||||
|
if (nav.className.match(/(^|\s)closed(\s|$)/)) {
|
||||||
|
setAttributes(nav, {"aria-hidden": "true"});
|
||||||
|
nav.style.position = "absolute";
|
||||||
|
}
|
||||||
|
|
||||||
|
this._createStyles();
|
||||||
|
this._calcHeight();
|
||||||
|
} else {
|
||||||
|
setAttributes(navToggle, {"aria-hidden": "true"});
|
||||||
|
setAttributes(nav, {"aria-hidden": "false"});
|
||||||
|
nav.style.position = opts.openPos;
|
||||||
|
this._removeStyles();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init callback
|
||||||
|
opts.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var _instance;
|
||||||
|
function rn (el, options) {
|
||||||
|
if (!_instance) {
|
||||||
|
_instance = new ResponsiveNav(el, options);
|
||||||
|
}
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rn;
|
||||||
|
})(window, document);
|
1
assets/js/scripts.min.js
vendored
Normal file
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 180 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 179 KiB After Width: | Height: | Size: 173 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 38 KiB |