/** * * jPanelMenu 1.3.0 (http://jpanelmenu.com) * By Anthony Colangelo (http://acolangelo.com) * * Legacy Build * This is the old, original jPanelMenu build that relies on jQuery animation. * The official build uses CSS transforms instead of jQuery animation, which makes * fixed positioning go crazy. If you need fixed positioning, use this legacy * build. Otherwise, use the current version. * * */ (function($){ $.jPanelMenu = function(options) { if ( typeof(options) == "undefined" || options == null ) { options = {}; }; var jP = { options: $.extend({ menu: '#menu', trigger: '.menu-trigger', excludedPanelContent: 'style, script', 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 , shiftFixedChildren: false, panelPosition: 'relative', positionUnits: 'px' }, menu: '#jPanelMenu-menu', panel: '.jPanelMenu-panel', fixedChildren: [], timeouts: {}, clearTimeouts: function() { clearTimeout(jP.timeouts.open); clearTimeout(jP.timeouts.afterOpen); clearTimeout(jP.timeouts.afterClose); }, setPositionUnits: function() { var foundUnit = false, allowedUnits = ['%','px','em'] ; for ( unitID in allowedUnits ) { 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 } }, checkFixedChildren: function() { jP.disableTransitions(); var defaultPanelStyle = { position: $(jP.panel).css('position') }; defaultPanelStyle[jP.options.direction] = ($(jP.panel).css(jP.options.direction) == 'auto')?0:$(jP.panel).css(jP.options.direction); $(jP.panel).find('> *').each(function(){ if ( $(this).css('position') == 'fixed' && $(this).css(jP.options.direction) == 'auto' ) { jP.fixedChildren.push(this); } }); if ( jP.fixedChildren.length > 0 ) { var newPanelStyle = { position: 'relative' }; newPanelStyle[jP.options.direction] = '1px'; jP.setPanelStyle(newPanelStyle); if ( parseInt($(jP.fixedChildren[0]).offset().left) == 0 ) { jP.settings.shiftFixedChildren = true; } } jP.setPanelStyle(defaultPanelStyle); }, setjPanelMenuStyles: function() { var bgColor = '#fff'; var htmlBG = $('html').css('background-color'); var bodyBG = $('body').css('background-color'); if ( bodyBG != 'transparent' && bodyBG != "rgba(0, 0, 0, 0)") { bgColor = bodyBG; } else if ( htmlBG != 'transparent' && htmlBG != "rgba(0, 0, 0, 0)") { bgColor = htmlBG; } else { bgColor = '#fff'; } if ( $('#jPanelMenu-style-master').length == 0 ) { $('body').append(''); } }, setMenuState: function(open) { var position = (open)?'open':'closed'; $('body').attr('data-menu-position', position); }, getMenuState: function() { return $('body').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(''); }, disableTransitions: function() { $('#jPanelMenu-style-transitions').remove(); }, enableFixedTransitions: function(selector, id, duration, easing) { var formattedDuration = duration/1000; var formattedEasing = jP.getCSSEasingFunction(easing); jP.disableFixedTransitions(id); $('body').append(''); }, disableFixedTransitions: function(id) { $('#jPanelMenu-style-fixed-' + id).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; } }, 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.setPanelStyle({ position: 'relative' }); 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 = {}; newPanelStyle[jP.options.direction] = jP.options.openPosition; jP.setPanelStyle(newPanelStyle); if ( jP.settings.shiftFixedChildren ) { $(jP.fixedChildren).each(function(){ var id = $(this).prop("tagName").toLowerCase() + ' ' + $(this).attr('class'), selector = id.replace(' ','.'), id = id.replace(' ','-') ; if ( animationChecks.none ) jP.disableFixedTransitions(id); if ( animationChecks.transitions ) jP.enableFixedTransitions(selector, id, jP.options.openDuration, jP.options.openEasing); var newChildrenStyle = {}; newChildrenStyle[jP.options.direction] = jP.options.openPosition; $(this).css(newChildrenStyle); }); } jP.timeouts.afterOpen = setTimeout(function(){ jP.disableTransitions(); if ( jP.settings.shiftFixedChildren ) { $(jP.fixedChildren).each(function(){ var id = $(this).prop("tagName").toLowerCase() + ' ' + $(this).attr('class'), id = id.replace(' ','-') ; jP.disableFixedTransitions(id); }); } 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(); }); if ( jP.settings.shiftFixedChildren ) { $(jP.fixedChildren).each(function(){ var childrenAnimationOptions = {}; childrenAnimationOptions[jP.options.direction] = jP.options.openPosition; $(this).stop().animate(childrenAnimationOptions, jP.options.openDuration, formattedEasing); }); } } }, 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 = {}; newPanelStyle[jP.options.direction] = 0 + jP.settings.positionUnits; jP.setPanelStyle(newPanelStyle); if ( jP.settings.shiftFixedChildren ) { $(jP.fixedChildren).each(function(){ var id = $(this).prop("tagName").toLowerCase() + ' ' + $(this).attr('class'), selector = id.replace(' ','.'), id = id.replace(' ','-') ; if ( animationChecks.none ) jP.disableFixedTransitions(id); if ( animationChecks.transitions ) jP.enableFixedTransitions(selector, id, jP.options.closeDuration, jP.options.closeEasing); var newChildrenStyle = {}; newChildrenStyle[jP.options.direction] = 0 + jP.settings.positionUnits; $(this).css(newChildrenStyle); }); } jP.timeouts.afterClose = setTimeout(function(){ jP.setPanelStyle({ position: jP.settings.panelPosition }); jP.disableTransitions(); if ( jP.settings.shiftFixedChildren ) { $(jP.fixedChildren).each(function(){ var id = $(this).prop("tagName").toLowerCase() + ' ' + $(this).attr('class'), id = id.replace(' ','-') ; jP.disableFixedTransitions(id); }); } 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.setPanelStyle({ position: jP.settings.panelPosition }); jP.hideMenu(); jP.options.after(); jP.options.afterClose(); jP.destroyContentClickListeners(); }); if ( jP.settings.shiftFixedChildren ) { $(jP.fixedChildren).each(function(){ var childrenAnimationOptions = {}; childrenAnimationOptions[jP.options.direction] = 0 + jP.settings.positionUnits; $(this).stop().animate(childrenAnimationOptions, jP.options.closeDuration, formattedEasing); }); } } }, triggerMenu: function(animated) { if ( jP.menuIsOpen() ) jP.closeMenu(animated); else jP.openMenu(animated); }, initiateClickListeners: function() { $(document).on('click',jP.options.trigger,function(){ jP.triggerMenu(jP.options.animated); return false; }); }, destroyClickListeners: function() { $(document).off('click',jP.options.trigger,null); }, initiateContentClickListeners: function() { if ( !jP.options.closeOnContentClick ) return false; $(document).on('click',jP.panel,function(e){ if ( jP.menuIsOpen() ) jP.closeMenu(jP.options.animated); }); $(document).on('touchend',jP.panel,function(e){ if ( jP.menuIsOpen() ) jP.closeMenu(jP.options.animated); }); }, destroyContentClickListeners: function() { if ( !jP.options.closeOnContentClick ) return false; $(document).off('click',jP.panel,null); $(document).off('touchend',jP.panel,null); }, initiateKeyboardListeners: function() { var preventKeyListeners = ['input', 'textarea']; $(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); } return false; } } }); }, destroyKeyboardListeners: function() { $(document).off('keydown',null); }, setupMarkup: function() { $('html').addClass('jPanelMenu'); $('body > *').not(jP.menu + ', ' + jP.options.excludedPanelContent).wrapAll('
'); $(jP.options.menu).clone(jP.options.keepEventHandlers).attr('id', jP.menu.replace('#','')).insertAfter('body > ' + jP.panel); }, resetMarkup: function() { $('html').removeClass('jPanelMenu'); $('body > ' + jP.panel + ' > *').unwrap(); $(jP.menu).remove(); }, init: function() { jP.options.beforeOn(); jP.initiateClickListeners(); if ( Object.prototype.toString.call(jP.options.keyboardShortcuts) === '[object Array]' ) { jP.initiateKeyboardListeners(); } jP.setjPanelMenuStyles(); jP.setMenuState(false); jP.setupMarkup(); jP.setMenuStyle({ width: jP.options.openPosition }); jP.checkFixedChildren(); jP.setPositionUnits(); 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.fixedChildren).each(function(){ $(this).css(childrenStyles); }); jP.fixedChildren = []; 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); } }; }; })(jQuery);