Template:ETH Zurich/jqueryjpanelmenuJS
/**
* * jPanelMenu 1.4.1 (http://jpanelmenu.com) * By Anthony Colangelo (http://acolangelo.com) *
- */
(function($){ $.jPanelMenu = function(options) { if ( typeof(options) == "undefined" || options == null ) { options = {}; };
var jP = { options: $.extend({ menu: '#menu', panel: 'body', trigger: '.menu-trigger', excludedPanelContent: 'style, script', clone: true, keepEventHandlers: false,
direction: 'left', openPosition: '250px', animated: true, closeOnContentClick: true,
keyboardShortcuts: [ { code: 27, open: false, close: true }, { code: 37, open: false, close: true }, { code: 39, open: true, close: true }, { code: 77, open: true, close: true } ],
duration: 150, openDuration: options.duration || 150, closeDuration: options.duration || 150,
easing: 'ease-in-out', openEasing: options.easing || 'ease-in-out', closeEasing: options.easing || 'ease-in-out',
before: function(){ }, beforeOpen: function(){ }, beforeClose: function(){ },
after: function(){ }, afterOpen: function(){ }, afterClose: function(){ },
beforeOn: function(){ }, afterOn: function(){ },
beforeOff: function(){ }, afterOff: function(){ } },options),
settings: { transitionsSupported: 'WebkitTransition' in document.body.style || 'MozTransition' in document.body.style || 'msTransition' in document.body.style || 'OTransition' in document.body.style || 'Transition' in document.body.style , transformsSupported: 'WebkitTransform' in document.body.style || 'MozTransform' in document.body.style || 'msTransform' in document.body.style || 'OTransform' in document.body.style || 'Transform' in document.body.style , cssPrefix: , panelPosition: 'static', positionUnits: 'px' },
menu: '#jPanelMenu-menu',
panel: '.jPanelMenu-panel',
timeouts: {},
clearTimeouts: function() { clearTimeout(jP.timeouts.open); clearTimeout(jP.timeouts.afterOpen); clearTimeout(jP.timeouts.afterClose); },
setPositionUnits: function() { var foundUnit = false, allowedUnits = ['%','px','em'] ;
for (var unitID = 0; unitID < allowedUnits.length; unitID++) { var unit = allowedUnits[unitID]; if ( jP.options.openPosition.toString().substr(-unit.length) == unit ) { foundUnit = true; jP.settings.positionUnits = unit; } }
if ( !foundUnit ) { jP.options.openPosition = parseInt(jP.options.openPosition) + jP.settings.positionUnits } },
computePositionStyle: function(open, string) { var position = (open)?jP.options.openPosition:'0' + jP.settings.positionUnits; var property = {}; if ( jP.settings.transformsSupported ) { var direction = (open && jP.options.direction == 'right')?'-':; var translate = 'translate3d(' + direction + position + ',0,0)'; var transform = 'transform';
if ( string ) { property = ; if ( jP.settings.cssPrefix != ) { property = jP.settings.cssPrefix + transform + ':' + translate + ';' } property += transform + ':' + translate + ';'; } else { if ( jP.settings.cssPrefix != ) { property[jP.settings.cssPrefix + transform] = translate; } property[transform] = translate; } } else { if ( string ) { property = ; property = jP.options.direction + ': ' + position + ';'; } else { property[jP.options.direction] = position; } } return property; },
setCSSPrefix: function() { jP.settings.cssPrefix = jP.getCSSPrefix(); },
setjPanelMenuStyles: function() { var bg = 'background:#fff', htmlBG = $('html').css('background-color'), bodyBG = $('body').css('background-color');
var backgroundGenerator = function(element){ var bgs = []; $.each(['background-color','background-image','background-position','background-repeat','background-attachment','background-size','background-clip'], function(i,value){ if( element.css(value) !== ) { bgs.push(value+':'+element.css(value)); } }); return bgs.join(';'); };
if ( bodyBG !== 'transparent' && bodyBG !== "rgba(0, 0, 0, 0)") { bg = backgroundGenerator($('body')); } else if ( htmlBG !== 'transparent' && htmlBG !== "rgba(0, 0, 0, 0)") { bg = backgroundGenerator($('html')); }
if ( $('#jPanelMenu-style-master').length == 0 ) { $('body').append('<style id="jPanelMenu-style-master">body{width:100%}.jPanelMenu,body{overflow-x:hidden}#jPanelMenu-menu{display:block;position:fixed;top:0;'+jP.options.direction+':0;height:100%;z-index:-1;overflow-x:hidden;overflow-y:scroll;-webkit-overflow-scrolling:touch}.jPanelMenu-panel{position:static;'+jP.options.direction+':0;top:0;z-index:2;width:100%;min-height:100%;' + bg + ';}</style>'); } },
setMenuState: function(open) { var position = (open)?'open':'closed'; $(jP.options.panel).attr('data-menu-position', position); },
getMenuState: function() { return $(jP.options.panel).attr('data-menu-position'); },
menuIsOpen: function() { if ( jP.getMenuState() == 'open' ) return true; else return false; },
setMenuStyle: function(styles) { $(jP.menu).css(styles); },
setPanelStyle: function(styles) { $(jP.panel).css(styles); },
showMenu: function() { jP.setMenuStyle({ display: 'block' }); jP.setMenuStyle({ 'z-index': '1' }); },
hideMenu: function() { jP.setMenuStyle({ 'z-index': '-1' }); jP.setMenuStyle({ display: 'none' }); },
enableTransitions: function(duration, easing) { var formattedDuration = duration/1000; var formattedEasing = jP.getCSSEasingFunction(easing); jP.disableTransitions(); $('body').append('<style id="jPanelMenu-style-transitions">.jPanelMenu-panel{' + jP.settings.cssPrefix + 'transition: all ' + formattedDuration + 's ' + formattedEasing + '; transition: all ' + formattedDuration + 's ' + formattedEasing + ';}</style>'); },
disableTransitions: function() { $('#jPanelMenu-style-transitions').remove(); },
getCSSEasingFunction: function(name) { switch ( name ) { case 'linear': return name; break;
case 'ease': return name; break;
case 'ease-in': return name; break;
case 'ease-out': return name; break;
case 'ease-in-out': return name; break;
default: return 'ease-in-out'; break; } },
getJSEasingFunction: function(name) { switch ( name ) { case 'linear': return name; break;
default: return 'swing'; break; } },
getVendorPrefix: function() { // Thanks to Lea Verou for this beautiful function. (http://lea.verou.me/2009/02/find-the-vendor-prefix-of-the-current-browser) if('result' in arguments.callee) return arguments.callee.result;
var regex = /^(Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/;
var someScript = document.getElementsByTagName('script')[0];
for(var prop in someScript.style) { if(regex.test(prop)) { // test is faster than match, so it's better to perform // that on the lot and match only when necessary return arguments.callee.result = prop.match(regex)[0]; }
}
// Nothing found so far? Webkit does not enumerate over the CSS properties of the style object. // However (prop in style) returns the correct value, so we'll have to test for // the precence of a specific property if('WebkitOpacity' in someScript.style) return arguments.callee.result = 'Webkit'; if('KhtmlOpacity' in someScript.style) return arguments.callee.result = 'Khtml';
return arguments.callee.result = ; },
getCSSPrefix: function() { var prefix = jP.getVendorPrefix(); if ( prefix != ) { return '-' + prefix.toLowerCase() + '-'; } return ; },
openMenu: function(animated) { if ( typeof(animated) == "undefined" || animated == null ) { animated = jP.options.animated };
jP.clearTimeouts();
jP.options.before(); jP.options.beforeOpen();
jP.setMenuState(true);
jP.showMenu();
var animationChecks = { none: (!animated)?true:false, transitions: (animated && jP.settings.transitionsSupported)?true:false };
if ( animationChecks.transitions || animationChecks.none ) { if ( animationChecks.none ) jP.disableTransitions(); if ( animationChecks.transitions ) jP.enableTransitions(jP.options.openDuration, jP.options.openEasing);
var newPanelStyle = jP.computePositionStyle(true); jP.setPanelStyle(newPanelStyle);
jP.timeouts.afterOpen = setTimeout(function(){ jP.options.after(); jP.options.afterOpen(); jP.initiateContentClickListeners(); }, jP.options.openDuration); } else { var formattedEasing = jP.getJSEasingFunction(jP.options.openEasing);
var animationOptions = {}; animationOptions[jP.options.direction] = jP.options.openPosition; $(jP.panel).stop().animate(animationOptions, jP.options.openDuration, formattedEasing, function(){ jP.options.after(); jP.options.afterOpen(); jP.initiateContentClickListeners(); }); } },
closeMenu: function(animated) { if ( typeof(animated) == "undefined" || animated == null ) { animated = jP.options.animated };
jP.clearTimeouts();
jP.options.before(); jP.options.beforeClose();
jP.setMenuState(false);
var animationChecks = { none: (!animated)?true:false, transitions: (animated && jP.settings.transitionsSupported)?true:false };
if ( animationChecks.transitions || animationChecks.none ) { if ( animationChecks.none ) jP.disableTransitions(); if ( animationChecks.transitions ) jP.enableTransitions(jP.options.closeDuration, jP.options.closeEasing);
var newPanelStyle = jP.computePositionStyle(); jP.setPanelStyle(newPanelStyle);
jP.timeouts.afterClose = setTimeout(function(){ jP.disableTransitions();
jP.hideMenu(); jP.options.after(); jP.options.afterClose(); jP.destroyContentClickListeners(); }, jP.options.closeDuration); } else { var formattedEasing = jP.getJSEasingFunction(jP.options.closeEasing);
var animationOptions = {}; animationOptions[jP.options.direction] = 0 + jP.settings.positionUnits; $(jP.panel).stop().animate(animationOptions, jP.options.closeDuration, formattedEasing, function(){ jP.hideMenu(); jP.options.after(); jP.options.afterClose(); jP.destroyContentClickListeners(); }); } },
triggerMenu: function(animated) { if ( jP.menuIsOpen() ) jP.closeMenu(animated); else jP.openMenu(animated); },
initiateClickListeners: function() { $(document).on('click touchend',jP.options.trigger,function(e){ jP.triggerMenu(jP.options.animated); e.preventDefault(); }); },
destroyClickListeners: function() { $(document).off('click touchend',jP.options.trigger,null); },
initiateContentClickListeners: function() { if ( !jP.options.closeOnContentClick ) return false;
$(document).on('click touchend',jP.panel,function(e){ if ( jP.menuIsOpen() ) jP.closeMenu(jP.options.animated); e.preventDefault(); }); },
destroyContentClickListeners: function() { if ( !jP.options.closeOnContentClick ) return false;
$(document).off('click touchend',jP.panel,null); },
initiateKeyboardListeners: function() { var preventKeyListeners = ['input', 'textarea', 'select']; $(document).on('keydown',function(e){ var target = $(e.target), prevent = false;
$.each(preventKeyListeners, function(){ if (target.is(this.toString())) { prevent = true; } });
if ( prevent ) return true;
for ( mapping in jP.options.keyboardShortcuts ) { if ( e.which == jP.options.keyboardShortcuts[mapping].code ) { var key = jP.options.keyboardShortcuts[mapping];
if ( key.open && key.close ) { jP.triggerMenu(jP.options.animated); } else if ( (key.open && !key.close) && !jP.menuIsOpen() ) { jP.openMenu(jP.options.animated); } else if ( (!key.open && key.close) && jP.menuIsOpen() ) { jP.closeMenu(jP.options.animated); }
e.preventDefault(); } } }); },
destroyKeyboardListeners: function() { $(document).off('keydown',null); },
setupMarkup: function() { $('html').addClass('jPanelMenu'); $(jP.options.panel + ' > *').not(jP.menu + ', ' + jP.options.excludedPanelContent).wrapAll('<div class="' + jP.panel.replace('.',) + '"/>'); var menu = ( jP.options.clone )?$(jP.options.menu).clone(jP.options.keepEventHandlers):$(jP.options.menu); menu.attr('id', jP.menu.replace('#',)).insertAfter(jP.options.panel + ' > ' + jP.panel); },
resetMarkup: function() { $('html').removeClass('jPanelMenu'); $(jP.options.panel + ' > ' + jP.panel + ' > *').unwrap(); $(jP.menu).remove(); },
init: function() { jP.options.beforeOn();
jP.setPositionUnits(); jP.setCSSPrefix(); jP.initiateClickListeners(); if ( Object.prototype.toString.call(jP.options.keyboardShortcuts) === '[object Array]' ) { jP.initiateKeyboardListeners(); }
jP.setjPanelMenuStyles(); jP.setMenuState(false); jP.setupMarkup();
jP.setPanelStyle({ position: (( jP.options.animated && jP.settings.panelPosition === 'static' )?'relative':jP.settings.panelPosition) }); jP.setMenuStyle({ width: jP.options.openPosition });
jP.closeMenu(false);
jP.options.afterOn(); },
destroy: function() { jP.options.beforeOff();
jP.closeMenu(); jP.destroyClickListeners(); if ( Object.prototype.toString.call(jP.options.keyboardShortcuts) === '[object Array]' ) { jP.destroyKeyboardListeners(); }
jP.resetMarkup(); var childrenStyles = {}; childrenStyles[jP.options.direction] = 'auto';
jP.options.afterOff(); } };
return { on: jP.init, off: jP.destroy, trigger: jP.triggerMenu, open: jP.openMenu, close: jP.closeMenu, isOpen: jP.menuIsOpen, menu: jP.menu, getMenu: function() { return $(jP.menu); }, panel: jP.panel, getPanel: function() { return $(jP.panel); }, setPosition: function(position) { if ( typeof(position) == "undefined" || position == null ) { position = jP.options.openPosition } jP.options.openPosition = position; jP.setMenuStyle({ width: jP.options.openPosition }); } }; }; })(jQuery);