mirror of
https://github.com/MinimalBible/MinimalBible.github.io
synced 2024-12-22 06:38:27 -05:00
1114 lines
33 KiB
JavaScript
1114 lines
33 KiB
JavaScript
|
/*! 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 );
|
||
|
|
||
|
/**
|
||
|
* jquery.dlmenu.js v1.0.1
|
||
|
* http://www.codrops.com
|
||
|
*
|
||
|
* Licensed under the MIT license.
|
||
|
* http://www.opensource.org/licenses/mit-license.php
|
||
|
*
|
||
|
* Copyright 2013, Codrops
|
||
|
* http://www.codrops.com
|
||
|
*/
|
||
|
;( function( $, window, undefined ) {
|
||
|
|
||
|
'use strict';
|
||
|
|
||
|
// global
|
||
|
var Modernizr = window.Modernizr, $body = $( 'body' );
|
||
|
|
||
|
$.DLMenu = function( options, element ) {
|
||
|
this.$el = $( element );
|
||
|
this._init( options );
|
||
|
};
|
||
|
|
||
|
// the options
|
||
|
$.DLMenu.defaults = {
|
||
|
// classes for the animation effects
|
||
|
animationClasses : { classin : 'dl-animate-in-1', classout : 'dl-animate-out-1' },
|
||
|
// callback: click a link that has a sub menu
|
||
|
// el is the link element (li); name is the level name
|
||
|
onLevelClick : function( el, name ) { return false; },
|
||
|
// callback: click a link that does not have a sub menu
|
||
|
// el is the link element (li); ev is the event obj
|
||
|
onLinkClick : function( el, ev ) { return false; }
|
||
|
};
|
||
|
|
||
|
$.DLMenu.prototype = {
|
||
|
_init : function( options ) {
|
||
|
|
||
|
// options
|
||
|
this.options = $.extend( true, {}, $.DLMenu.defaults, options );
|
||
|
// cache some elements and initialize some variables
|
||
|
this._config();
|
||
|
|
||
|
var animEndEventNames = {
|
||
|
'WebkitAnimation' : 'webkitAnimationEnd',
|
||
|
'OAnimation' : 'oAnimationEnd',
|
||
|
'msAnimation' : 'MSAnimationEnd',
|
||
|
'animation' : 'animationend'
|
||
|
},
|
||
|
transEndEventNames = {
|
||
|
'WebkitTransition' : 'webkitTransitionEnd',
|
||
|
'MozTransition' : 'transitionend',
|
||
|
'OTransition' : 'oTransitionEnd',
|
||
|
'msTransition' : 'MSTransitionEnd',
|
||
|
'transition' : 'transitionend'
|
||
|
};
|
||
|
// animation end event name
|
||
|
this.animEndEventName = animEndEventNames[ Modernizr.prefixed( 'animation' ) ] + '.dlmenu';
|
||
|
// transition end event name
|
||
|
this.transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ] + '.dlmenu',
|
||
|
// support for css animations and css transitions
|
||
|
this.supportAnimations = Modernizr.cssanimations,
|
||
|
this.supportTransitions = Modernizr.csstransitions;
|
||
|
|
||
|
this._initEvents();
|
||
|
|
||
|
},
|
||
|
_config : function() {
|
||
|
this.open = false;
|
||
|
this.$trigger = this.$el.children( '.dl-trigger' );
|
||
|
this.$menu = this.$el.children( 'ul.dl-menu' );
|
||
|
this.$menuitems = this.$menu.find( 'li:not(.dl-back)' );
|
||
|
this.$el.find( 'ul.dl-submenu' ).prepend( '<li class="dl-back"><a href="#">back</a></li>' );
|
||
|
this.$back = this.$menu.find( 'li.dl-back' );
|
||
|
},
|
||
|
_initEvents : function() {
|
||
|
|
||
|
var self = this;
|
||
|
|
||
|
this.$trigger.on( 'click.dlmenu', function() {
|
||
|
|
||
|
if( self.open ) {
|
||
|
self._closeMenu();
|
||
|
}
|
||
|
else {
|
||
|
self._openMenu();
|
||
|
}
|
||
|
return false;
|
||
|
|
||
|
} );
|
||
|
|
||
|
this.$menuitems.on( 'click.dlmenu', function( event ) {
|
||
|
|
||
|
event.stopPropagation();
|
||
|
|
||
|
var $item = $(this),
|
||
|
$submenu = $item.children( 'ul.dl-submenu' );
|
||
|
|
||
|
if( $submenu.length > 0 ) {
|
||
|
|
||
|
var $flyin = $submenu.clone().css( 'opacity', 0 ).insertAfter( self.$menu ),
|
||
|
onAnimationEndFn = function() {
|
||
|
self.$menu.off( self.animEndEventName ).removeClass( self.options.animationClasses.classout ).addClass( 'dl-subview' );
|
||
|
$item.addClass( 'dl-subviewopen' ).parents( '.dl-subviewopen:first' ).removeClass( 'dl-subviewopen' ).addClass( 'dl-subview' );
|
||
|
$flyin.remove();
|
||
|
};
|
||
|
|
||
|
setTimeout( function() {
|
||
|
$flyin.addClass( self.options.animationClasses.classin );
|
||
|
self.$menu.addClass( self.options.animationClasses.classout );
|
||
|
if( self.supportAnimations ) {
|
||
|
self.$menu.on( self.animEndEventName, onAnimationEndFn );
|
||
|
}
|
||
|
else {
|
||
|
onAnimationEndFn.call();
|
||
|
}
|
||
|
|
||
|
self.options.onLevelClick( $item, $item.children( 'a:first' ).text() );
|
||
|
} );
|
||
|
|
||
|
return false;
|
||
|
|
||
|
}
|
||
|
else {
|
||
|
self.options.onLinkClick( $item, event );
|
||
|
}
|
||
|
|
||
|
} );
|
||
|
|
||
|
this.$back.on( 'click.dlmenu', function( event ) {
|
||
|
|
||
|
var $this = $( this ),
|
||
|
$submenu = $this.parents( 'ul.dl-submenu:first' ),
|
||
|
$item = $submenu.parent(),
|
||
|
|
||
|
$flyin = $submenu.clone().insertAfter( self.$menu );
|
||
|
|
||
|
var onAnimationEndFn = function() {
|
||
|
self.$menu.off( self.animEndEventName ).removeClass( self.options.animationClasses.classin );
|
||
|
$flyin.remove();
|
||
|
};
|
||
|
|
||
|
setTimeout( function() {
|
||
|
$flyin.addClass( self.options.animationClasses.classout );
|
||
|
self.$menu.addClass( self.options.animationClasses.classin );
|
||
|
if( self.supportAnimations ) {
|
||
|
self.$menu.on( self.animEndEventName, onAnimationEndFn );
|
||
|
}
|
||
|
else {
|
||
|
onAnimationEndFn.call();
|
||
|
}
|
||
|
|
||
|
$item.removeClass( 'dl-subviewopen' );
|
||
|
|
||
|
var $subview = $this.parents( '.dl-subview:first' );
|
||
|
if( $subview.is( 'li' ) ) {
|
||
|
$subview.addClass( 'dl-subviewopen' );
|
||
|
}
|
||
|
$subview.removeClass( 'dl-subview' );
|
||
|
} );
|
||
|
|
||
|
return false;
|
||
|
|
||
|
} );
|
||
|
|
||
|
},
|
||
|
closeMenu : function() {
|
||
|
if( this.open ) {
|
||
|
this._closeMenu();
|
||
|
}
|
||
|
},
|
||
|
_closeMenu : function() {
|
||
|
var self = this,
|
||
|
onTransitionEndFn = function() {
|
||
|
self.$menu.off( self.transEndEventName );
|
||
|
self._resetMenu();
|
||
|
};
|
||
|
|
||
|
this.$menu.removeClass( 'dl-menuopen' );
|
||
|
this.$menu.addClass( 'dl-menu-toggle' );
|
||
|
this.$trigger.removeClass( 'dl-active' );
|
||
|
|
||
|
if( this.supportTransitions ) {
|
||
|
this.$menu.on( this.transEndEventName, onTransitionEndFn );
|
||
|
}
|
||
|
else {
|
||
|
onTransitionEndFn.call();
|
||
|
}
|
||
|
|
||
|
this.open = false;
|
||
|
},
|
||
|
openMenu : function() {
|
||
|
if( !this.open ) {
|
||
|
this._openMenu();
|
||
|
}
|
||
|
},
|
||
|
_openMenu : function() {
|
||
|
var self = this;
|
||
|
// clicking somewhere else makes the menu close
|
||
|
$body.off( 'click' ).on( 'click.dlmenu', function() {
|
||
|
self._closeMenu() ;
|
||
|
} );
|
||
|
this.$menu.addClass( 'dl-menuopen dl-menu-toggle' ).on( this.transEndEventName, function() {
|
||
|
$( this ).removeClass( 'dl-menu-toggle' );
|
||
|
} );
|
||
|
this.$trigger.addClass( 'dl-active' );
|
||
|
this.open = true;
|
||
|
},
|
||
|
// resets the menu to its original state (first level of options)
|
||
|
_resetMenu : function() {
|
||
|
this.$menu.removeClass( 'dl-subview' );
|
||
|
this.$menuitems.removeClass( 'dl-subview dl-subviewopen' );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var logError = function( message ) {
|
||
|
if ( window.console ) {
|
||
|
window.console.error( message );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$.fn.dlmenu = function( options ) {
|
||
|
if ( typeof options === 'string' ) {
|
||
|
var args = Array.prototype.slice.call( arguments, 1 );
|
||
|
this.each(function() {
|
||
|
var instance = $.data( this, 'dlmenu' );
|
||
|
if ( !instance ) {
|
||
|
logError( "cannot call methods on dlmenu prior to initialization; " +
|
||
|
"attempted to call method '" + options + "'" );
|
||
|
return;
|
||
|
}
|
||
|
if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
|
||
|
logError( "no such method '" + options + "' for dlmenu instance" );
|
||
|
return;
|
||
|
}
|
||
|
instance[ options ].apply( instance, args );
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
this.each(function() {
|
||
|
var instance = $.data( this, 'dlmenu' );
|
||
|
if ( instance ) {
|
||
|
instance._init();
|
||
|
}
|
||
|
else {
|
||
|
instance = $.data( this, 'dlmenu', new $.DLMenu( options, this ) );
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
} )( jQuery, window );
|
||
|
|
||
|
/*! Plugin options and other jQuery stuff */
|
||
|
|
||
|
// dl-menu options
|
||
|
$(function() {
|
||
|
$( '#dl-menu' ).dlmenu({
|
||
|
animationClasses : { classin : 'dl-animate-in', classout : 'dl-animate-out' }
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// FitVids options
|
||
|
$(function() {
|
||
|
$("article").fitVids();
|
||
|
});
|
||
|
|
||
|
$(".close-menu").click(function () {
|
||
|
$(".menu").toggleClass("disabled");
|
||
|
$(".links").toggleClass("enabled");
|
||
|
});
|
||
|
|
||
|
$(".about").click(function () {
|
||
|
$("#about").css('display','block');
|
||
|
});
|
||
|
|
||
|
$(".close-about").click(function () {
|
||
|
$("#about").css('display','');
|
||
|
});
|