252 lines
6.8 KiB
JavaScript
252 lines
6.8 KiB
JavaScript
|
/**
|
||
|
* 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 );
|