/**

* 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,
                                        margin: 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 );