/** * jquery.dlmenu.js v1.0.0 * 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 : { in : 'dl-animate-in-1', out : 'dl-animate-out-1' } }; $.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( 'button' ); this.$menu = this.$el.children( 'ul.dl-menu' ); this.$menuitems = this.$menu.find( 'li:not(.dl-back)' ); 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(); // clicking somewhere else makes the menu close $body.off( 'click' ).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' ); if( $submenu.length > 0 ) { var $flyin = $submenu.clone().insertafter( self.$menu ).addclass( self.options.animationclasses.in ), onanimationendfn = function() { self.$menu.off( self.animendeventname ).removeclass( self.options.animationclasses.out ).addclass( 'dl-subview' ); $item.addclass( 'dl-subviewopen' ).parents( '.dl-subviewopen:first' ).removeclass( 'dl-subviewopen' ).addclass( 'dl-subview' ); $flyin.remove(); }; self.$menu.addclass( self.options.animationclasses.out ); if( self.supportanimations ) { self.$menu.on( self.animendeventname, onanimationendfn ); } else { onanimationendfn.call(); } return false; } } ); 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 ).addclass( self.options.animationclasses.out ); var onanimationendfn = function() { self.$menu.off( self.animendeventname ).removeclass( self.options.animationclasses.in ); $flyin.remove(); }; self.$menu.addclass( self.options.animationclasses.in ); 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() { 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() { 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 );