/** * 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 $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; }, backLabel: 'Back', showCurrentLabel: 'Show this page', // Change to "true" to use the active item as back link label. useActiveItemAsBackLabel: false, // Change to "true" to add a navigable link to the active item to its child // menu. useActiveItemAsLink: true }; $.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', "MozAnimation" : "animationend" }, transEndEventNames = { 'WebkitTransition' : 'webkitTransitionEnd', 'MozTransition' : 'transitionend', 'OTransition' : 'oTransitionEnd', 'msTransition' : 'MSTransitionEnd', 'transition' : 'transitionend' }; // animation end event name if (animEndEventNames[ window.supportedAnimation ] != undefined) { this.animEndEventName = animEndEventNames[ window.supportedAnimation ] + '.dlmenu'; } else { this.animEndEventName = animEndEventNames[ 'animation' ] + '.dlmenu'; } // transition end event name if (transEndEventNames[ window.supportedTransition ] != undefined) { this.transEndEventName = transEndEventNames[ window.supportedTransition ] + '.dlmenu'; } else { this.transEndEventName = transEndEventNames[ 'transition' ] + '.dlmenu'; } // support for css animations and css transitions this.supportAnimations = window.supportsAnimations; this.supportTransitions = window.supportsTransitions; this._initEvents(); }, _config : function() { var self = this; this.open = false; this.$trigger = this.$el.hasClass('primary-navigation') && $('#perspective-menu-buttons').length > 0 ? $('#perspective-menu-buttons .dl-trigger') : this.$el.find( '.dl-trigger:first' ); this.$menu = this.$el.find( 'ul.dl-menu:first' ); this.$menuitems = this.$menu.find( 'li:not(.dl-back):not(.not-dlmenu)' ); this.$el.find( 'ul.dl-submenu' ).prepend( '
  • ' + this.options.backLabel + '
  • ' ); this.$back = this.$menu.find( 'li.dl-back' ); // Set the label text for the back link. if (this.options.useActiveItemAsBackLabel) { this.$back.each(function() { var $this = $(this), parentLabel = $this.parents('li:first').find('a:first').text(); $this.find('a').html(parentLabel); }); } // If the active item should also be a clickable link, create one and put // it at the top of our menu. if (this.options.useActiveItemAsLink) { this.$el.find( 'ul.dl-submenu' ).prepend(function() { var activeLi = $(this).parents('li:not(.dl-back):first'); var parentli = activeLi.find('a:first'); if (activeLi.hasClass('mobile-clickable')) return '
  • ' + self.options.showCurrentLabel + '
  • '; else return ''; }); } }, _initEvents : function() { var self = this; this.$trigger.on( 'click.dlmenu', function() { if( self.open ) { self._closeMenu(); } else { self._openMenu(); // clicking somewhere else makes the menu close $body.off( 'click' ).children().on( 'click.dlmenu', function() { self._closeMenu() ; } ); } return false; } ); this.$menuitems.on( 'click.dlmenu', function( event ) { event.stopPropagation(); var $item = $(this), $submenu = $item.children( 'ul.dl-submenu' ), level = 1; if (!self.$menu.hasClass( 'dl-menuopen')) { self.options.onLinkClick( $item, event ); return; } var $itemList = $item.parent(); while ($itemList.attr('id') != 'primary-menu') { if ($itemList[0].nodeName.toUpperCase() == 'UL') { level++; } $itemList = $itemList.parent(); if (!$itemList.length) { break; } } if (level > 3) { level = 3; } // Only go to the next menu level if one exists AND the link isn't the // one we added specifically for navigating to parent item pages. if( ($submenu.length > 0) && !($(event.currentTarget).hasClass('dl-subviewopen'))) { var $flyin = $submenu.clone().addClass('level' + (level+1)).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(), level = 1; var $itemList = $this.parent(); while ($itemList.attr('id') != 'primary-menu') { if ($itemList[0].nodeName.toUpperCase() == 'UL') { level++; } $itemList = $itemList.parent(); if (!$itemList.length) { break; } } if (level > 3) { level = 3; } var $flyin = $submenu.clone().addClass('level' + level).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 );