aboutsummaryrefslogtreecommitdiffstats
path: root/ui/client/lib/jquery.multilevelpushmenu.js
diff options
context:
space:
mode:
authorKoren Lev <korenlev@gmail.com>2017-07-27 16:42:15 +0300
committerKoren Lev <korenlev@gmail.com>2017-07-27 16:42:15 +0300
commitb88c78e3cf2bef22aa2f1c4d0bf305e303bc15f0 (patch)
treeffa30a6e1511d72562d8772b8700cda52b2752a1 /ui/client/lib/jquery.multilevelpushmenu.js
parentb70483739d1f6f4f0d31987ed2e4d1e30d71d579 (diff)
adding calipso ui
Change-Id: Ifa6f63daebb07f45580f747341960e898fdb00c4 Signed-off-by: Koren Lev <korenlev@gmail.com>
Diffstat (limited to 'ui/client/lib/jquery.multilevelpushmenu.js')
-rw-r--r--ui/client/lib/jquery.multilevelpushmenu.js1148
1 files changed, 1148 insertions, 0 deletions
diff --git a/ui/client/lib/jquery.multilevelpushmenu.js b/ui/client/lib/jquery.multilevelpushmenu.js
new file mode 100644
index 0000000..0b2a24d
--- /dev/null
+++ b/ui/client/lib/jquery.multilevelpushmenu.js
@@ -0,0 +1,1148 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * jquery.multilevelpushmenu.js v2.1.4
+ *
+ * Licensed under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * Copyright 2013-2014, Make IT d.o.o.
+ * http://multi-level-push-menu.make.rs
+ * https://github.com/adgsm/multi-level-push-menu
+ */
+(function ( $ ) {
+ $.fn.multilevelpushmenu = function( options ) {
+ "use strict";
+ var args = arguments,
+ returnValue = null;
+
+ this.each(function(){
+ var instance = this,
+ $this = $( this ),
+ $container = ( $this.context != undefined ) ? $this : $( 'body' ),
+ menu = ( options && options.menu != undefined ) ? options.menu : $this.find( 'nav' ),
+ clickEventType, dragEventType;
+
+ // Settings
+ var settings = $.extend({
+ container: $container,
+ containersToPush: null,
+ menuID: ( ( $container.prop( 'id' ) != undefined && $container.prop( 'id' ) != '' ) ? $container.prop( 'id' ) : this.nodeName.toLowerCase() ) + "_multilevelpushmenu",
+ wrapperClass: 'multilevelpushmenu_wrapper',
+ menuInactiveClass: 'multilevelpushmenu_inactive',
+ menu: menu,
+ menuWidth: 0,
+ menuHeight: 0,
+ collapsed: false,
+ fullCollapse: false,
+ direction: 'ltr',
+ backText: 'Back',
+ backItemClass: 'backItemClass',
+ backItemIcon: 'fa fa-angle-right',
+ groupIcon: 'fa fa-angle-left',
+ mode: 'overlap',
+ overlapWidth: 40,
+ preventItemClick: true,
+ preventGroupItemClick: true,
+ swipe: 'both',
+ durationSlideOut: 400,
+ durationSlideDown: 500,
+ durationTransition: 400,
+ onCollapseMenuStart: function() {},
+ onCollapseMenuEnd: function() {},
+ onExpandMenuStart: function() {},
+ onExpandMenuEnd: function() {},
+ onGroupItemClick: function() {},
+ onItemClick: function() {},
+ onTitleItemClick: function() {},
+ onBackItemClick: function() {},
+ onMenuReady: function() {},
+ onMenuSwipe: function() {}
+ }, options );
+
+ // Store a settings reference withint the element's data
+ if (!$.data(instance, 'plugin_multilevelpushmenu')) {
+ $.data(instance, 'plugin_multilevelpushmenu', settings);
+ instance.settings = $.data(instance, 'plugin_multilevelpushmenu');
+ }
+
+ // Exposed methods
+ var methods = {
+ // Initialize menu
+ init: function () {
+ return initialize.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Collapse menu
+ collapse: function () {
+ return collapseMenu.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Expand menu
+ expand: function () {
+ return expandMenu.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Menu expanded
+ menuexpanded: function () {
+ return menuExpanded.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Active menu
+ activemenu: function () {
+ return activeMenu.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Find menu(s) by title
+ findmenusbytitle: function () {
+ return findMenusByTitle.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Find item(s) by name
+ finditemsbyname: function () {
+ return findItemsByName.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Find path to root menu collection
+ pathtoroot: function () {
+ return pathToRoot.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Find shared path to root of two menus
+ comparepaths: function () {
+ return comparePaths.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Get/Set settings options
+ option: function () {
+ return manageOptions.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Add item(s)
+ additems: function () {
+ return addItems.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Remove item(s)
+ removeitems: function () {
+ return removeItems.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Size DOM elements
+ redraw: function () {
+ return sizeDOMelements.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Returns visible level holders
+ visiblemenus: function () {
+ return visibleLevelHolders.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Returns visible level holders
+ hiddenmenus: function () {
+ return hiddenLevelHolders.apply(this, Array.prototype.slice.call(arguments));
+ },
+ // Propagate event to underneath layer
+ propagateevent: function () {
+ return propagateEvent.apply(this, Array.prototype.slice.call(arguments));
+ }
+ };
+
+ // IE 8 and modern browsers, prevent event propagation
+ function stopEventPropagation( e ){
+ if ( e.stopPropagation && e.preventDefault ) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ else {
+ e.cancelBubble = true;
+ e.returnValue = false;
+ }
+ }
+
+ // propagate event to underneath layer
+ // http://jsfiddle.net/E9zTs/2/
+ function propagateEvent( $element , event ) {
+ if( $element == undefined || event == undefined ) return false;
+ $element.on( event , function ( e , ee ) {
+ $element.hide();
+ try {
+ if(!e.pageX || !e.pageY) return false;
+ ee = ee || {
+ pageX: e.pageX,
+ pageY: e.pageY
+ };
+ var next = document.elementFromPoint( ee.pageX , ee.pageY );
+ next = ( next.nodeType == 3 ) ? next.parentNode : next //Opera
+ $( next ).trigger( event , ee );
+ }
+ catch ( err ) {
+ $.error( 'Error while propagating event: ' + err.message );
+ }
+ finally {
+ $element.show();
+ }
+ });
+ }
+
+ // Create DOM structure if it does not already exist within the container (input: array)
+ function createDOMStructure() {
+ var $mainWrapper = $( "<nav />" )
+ .prop( { "id" : instance.settings.menuID, "className" : instance.settings.wrapperClass } )
+ .appendTo( instance.settings.container );
+ createNestedDOMStructure( instance.settings.menu, $mainWrapper );
+ }
+ function createNestedDOMStructure( menus, $wrapper ){
+ if( menus.level == undefined ) menus.level = 0;
+ $.each( menus, function(){
+ var $levelHolder = $( "<div />" )
+ .attr( { "class" : "levelHolderClass" + ( ( instance.settings.direction == 'rtl' ) ? " rtl" : " ltr" ), "data-level" : menus.level, "style" : ( ( instance.settings.direction == 'rtl' ) ? "margin-right: " : "margin-left: " ) + ( ( menus.level == 0 && !instance.settings.collapsed ) ? 0 : "-200%" ) } )
+ .appendTo( $wrapper ),
+ extWidth = ( isValidDim( instance.settings.menuWidth ) || ( isInt( instance.settings.menuWidth ) && instance.settings.menuWidth > 0 ) );
+ $levelHolder.bind( dragEventType , function(e){
+ holderSwipe( e, $levelHolder );
+ });
+ if( this.id != undefined ) $levelHolder.attr( { "id" : this.id } );
+ var $title = $( "<h2 />" )
+ .attr( { "style" : "text-align: " + ( ( instance.settings.direction == 'rtl' ) ? "right" : "left" ) } )
+ .text( this.title )
+ .appendTo( $levelHolder ),
+ $titleIcon = $( "<i />" )
+ .prop( { "class" : ( ( instance.settings.direction == 'rtl' ) ? "floatLeft" : "floatRight" ) + " cursorPointer " + this.icon } )
+ .prependTo( $title );
+ $titleIcon.bind( clickEventType , function(e){
+ titleIconClick(e, $levelHolder, menus);
+ });
+ if( menus.level > 0 ) createBackItem( $levelHolder );
+ var $itemGroup = $( "<ul />" )
+ .appendTo( $levelHolder );
+ $.each(this.items, function(){
+ createItem( this, $levelHolder , -1 );
+ })
+ });
+ }
+
+ // Update DOM structure if it already exists in container (input: HTML markup)
+ function updateDOMStructure() {
+ var $mainWrapper = ( instance.settings.container.find( 'nav' ).length > 0 ) ? instance.settings.container.find( 'nav' ) : instance.settings.menu;
+ if( $mainWrapper.length == 0 ) return false;
+ $mainWrapper.prop( { "id" : instance.settings.menuID, "className" : instance.settings.wrapperClass } );
+ updateNestedDOMStructure( $mainWrapper );
+ }
+ function updateNestedDOMStructure( $wrapper ){
+ if( $wrapper.level == undefined ) $wrapper.level = 0;
+ $.each( $wrapper, function(){
+ var $levelHolder = $( "<div />" )
+ .attr( { "class" : "levelHolderClass" + ( ( instance.settings.direction == 'rtl' ) ? " rtl" : " ltr" ), "data-level" : $wrapper.level, "style" : ( ( instance.settings.direction == 'rtl' ) ? "margin-right: " : "margin-left: " ) + ( ( $wrapper.level == 0 && !instance.settings.collapsed ) ? 0 : "-200%" ) } )
+ .appendTo( $wrapper ),
+ extWidth = ( isValidDim( instance.settings.menuWidth ) || ( isInt( instance.settings.menuWidth ) && instance.settings.menuWidth > 0 ) );
+ $levelHolder.bind( dragEventType , function(e){
+ holderSwipe( e, $levelHolder );
+ });
+ var $title = $wrapper.children( 'h2' );
+ $title.attr( { "style" : "text-align: " + ( ( instance.settings.direction == 'rtl' ) ? "right" : "left" ) } );
+ $title.appendTo( $levelHolder );
+ var $titleIcon = $title.children( 'i' );
+ $titleIcon.addClass( ( ( instance.settings.direction == 'rtl' ) ? "floatLeft" : "floatRight" ) + " cursorPointer" );
+ $titleIcon.bind( clickEventType , function(e){
+ titleIconClick(e, $levelHolder, $wrapper);
+ });
+ if( $wrapper.level > 0 ) createBackItem( $levelHolder );
+ var $itemGroup = $wrapper.children( 'ul' );
+ $itemGroup.appendTo( $levelHolder );
+ $.each($itemGroup.children( 'li' ), function(){
+ var $item = $( this );
+ $item.attr( { "style" : "text-align: " + ( ( instance.settings.direction == 'rtl' ) ? "right" : "left" ) } );
+ var $itemAnchor = $item.children( 'a' );
+ var $itemIcon = $itemAnchor.children( 'i' );
+ $itemIcon.addClass( ( ( instance.settings.direction == 'rtl' ) ? "floatLeft" : "floatRight" ) );
+ if($item.children( 'ul' ).length > 0) {
+ $itemAnchor.bind( clickEventType , function(e){
+ itemGroupAnchorClick( e, $levelHolder, $item );
+ });
+ createItemGroupIcon( $itemAnchor );
+ $item.level = $wrapper.level + 1;
+ updateNestedDOMStructure($item);
+ } else {
+ $itemAnchor.bind( clickEventType , function(e){
+ itemAnchorClick( e, $levelHolder, $item );
+ });
+ }
+ })
+ });
+ }
+
+ // Click event for title icon
+ function titleIconClick( e, $levelHolder, menus ) {
+ if( $(instance).find( 'div.levelHolderClass' ).is(':animated') ) return false;
+ instance.settings.onTitleItemClick.apply(this, Array.prototype.slice.call([e, $levelHolder, instance.settings]));
+ stopEventPropagation(e);
+ var instanceFC = ( instance.settings.direction == 'rtl' ) ?
+ parseInt( $levelHolder.css( 'margin-right' ) ) < 0
+ :
+ parseInt( $levelHolder.css( 'margin-left' ) ) < 0;
+ if( menus.level == 0 && instanceFC ) {
+ expandMenu();
+ }
+ else {
+ var $nextLevelHolders = instance.settings.container
+ .find( '#' + instance.settings.menuID + ' div.levelHolderClass' )
+ .filter(function(){
+ var retObjs = ( instance.settings.direction == 'rtl' ) ?
+ (($( this ).attr( 'data-level' ) > $levelHolder.attr( 'data-level' )) && ( parseInt( $( this ).css( 'margin-right' ) ) >= 0 ) )
+ :
+ (($( this ).attr( 'data-level' ) > $levelHolder.attr( 'data-level' )) && ( parseInt( $( this ).css( 'margin-left' ) ) >= 0 ) );
+ return retObjs;
+ }),
+ $prevLevelHolders = instance.settings.container
+ .find( '#' + instance.settings.menuID + ' div.levelHolderClass' )
+ .filter(function(){
+ var retObjs = ( instance.settings.direction == 'rtl' ) ?
+ (($( this ).attr( 'data-level' ) <= $levelHolder.attr( 'data-level' )) && ( parseInt( $( this ).css( 'margin-right' ) ) >= 0 ) )
+ :
+ (($( this ).attr( 'data-level' ) <= $levelHolder.attr( 'data-level' )) && ( parseInt( $( this ).css( 'margin-left' ) ) >= 0 ) );
+ return retObjs;
+ }),
+ collapseAll = ( $nextLevelHolders.length == 0 && $prevLevelHolders.length == 1 ) ? collapseMenu() : collapseMenu( parseInt( $levelHolder.attr( 'data-level' ) ) );
+ }
+ $levelHolder.css( 'visibility' , 'visible' );
+ $levelHolder.find( '.' + instance.settings.backItemClass ).css( 'visibility' , 'visible' );
+ $levelHolder.find( 'ul' ).css( 'visibility' , 'visible' );
+ $levelHolder.removeClass( instance.settings.menuInactiveClass );
+ }
+
+ // Create Back item DOM elements
+ function createBackItem( $levelHolder ) {
+ var $backItem = $( "<div />" )
+ .attr( { "class" : instance.settings.backItemClass } )
+ .appendTo( $levelHolder ),
+ $backItemAnchor = $( "<a />" )
+ .prop( { "href" : "#" } )
+ .text( instance.settings.backText )
+ .appendTo( $backItem ),
+ $backItemIcon = $( "<i />" )
+ .prop( { "class" : ( ( instance.settings.direction == 'rtl' ) ? "floatLeft " : "floatRight " ) + instance.settings.backItemIcon } )
+ .prependTo( $backItemAnchor );
+ $backItemAnchor.bind( clickEventType , function(e){
+ backItemAnchorClick(e, $levelHolder);
+ });
+ }
+
+ // Click event for back item
+ function backItemAnchorClick( e, $levelHolder ) {
+ if( $(instance).find( 'div.levelHolderClass' ).is(':animated') ) return false;
+ instance.settings.onBackItemClick.apply(this, Array.prototype.slice.call([e, $levelHolder, instance.settings]));
+ stopEventPropagation(e);
+ collapseMenu( parseInt( $levelHolder.attr( 'data-level' ) - 1 ) );
+ }
+
+ // Click event for group items
+ function itemGroupAnchorClick( e, $levelHolder, $item ) {
+ if( $(instance).find( 'div.levelHolderClass' ).is(':animated') ) return false;
+ instance.settings.onGroupItemClick.apply(this, Array.prototype.slice.call([e, $levelHolder, $item, instance.settings]));
+ expandMenu( $item.find( 'div:first' ) );
+ if( instance.settings.preventGroupItemClick ) stopEventPropagation(e);
+ }
+
+ // Create item group DOM element
+ function createItemGroupIcon( $itemAnchor ) {
+ var $itemGroupIcon = $( "<i />" )
+ .attr( { "class" : ( ( instance.settings.direction == 'rtl' ) ? " floatRight iconSpacing_rtl " : " floatLeft iconSpacing_ltr " ) + instance.settings.groupIcon } )
+ .prependTo( $itemAnchor );
+ }
+
+ // Create item DOM element
+ function createItem() {
+ var item = arguments[0],
+ $levelHolder = arguments[1],
+ position = arguments[2],
+ $itemGroup = $levelHolder.find( 'ul:first' ),
+ $item = $( "<li />" );
+ ( position < ( $itemGroup.children( 'li' ).length ) && position >= 0 ) ?
+ $item.insertBefore( $itemGroup.children( 'li' ).eq( position ) ) : $item.appendTo( $itemGroup );
+ $item.attr( { "style" : "text-align: " + ( ( instance.settings.direction == 'rtl' ) ? "right" : "left" ) } );
+ if( item.id != undefined ) $item.attr( { "id" : item.id } );
+ var $itemAnchor = $( "<a />" )
+ .prop( { "href" : item.link } )
+ .text( item.name )
+ .appendTo( $item ),
+ $itemIcon = $( "<i />" )
+ .prop( { "class" : ( ( instance.settings.direction == 'rtl' ) ? "floatLeft " : "floatRight " ) + item.icon } )
+ .prependTo( $itemAnchor );
+ if(item.items) {
+ $itemAnchor.bind( clickEventType , function(e){
+ itemGroupAnchorClick( e, $levelHolder, $item );
+ });
+ createItemGroupIcon( $itemAnchor );
+ item.items.level = parseInt( $levelHolder.attr( 'data-level' ), 10 ) + 1;
+ createNestedDOMStructure(item.items, $item);
+ } else {
+ $itemAnchor.bind( clickEventType , function(e){
+ itemAnchorClick( e, $levelHolder, $item );
+ });
+ }
+ }
+
+ // Click event for items
+ function itemAnchorClick( e, $levelHolder, $item ) {
+ instance.settings.onItemClick.apply(this, Array.prototype.slice.call([e, $levelHolder, $item, instance.settings]));
+ if( instance.settings.preventItemClick ) stopEventPropagation(e);
+ }
+
+ // Swipe/Drag event for holders
+ function holderSwipe( emd, $levelHolder ) {
+ var extRes = instance.settings.onMenuSwipe.apply(this, Array.prototype.slice.call([emd, $levelHolder, instance.settings]));
+ if( extRes == false ) return false;
+ if( $(instance).find( 'div.levelHolderClass' ).is(':animated') ) return false;
+ var level = ( $levelHolder.attr( 'data-level' ) > 0 ) ? $levelHolder.attr( 'data-level' ) - 1 : undefined;
+ if( emd.type == 'touchmove' && instance.settings.swipe != 'desktop' ) {
+ stopEventPropagation( emd );
+ emd = ( emd.touches ) ? emd : emd.originalEvent;
+ if( !emd.touches || emd.touches.length <= 0 ) return false;
+ var touch = emd.touches[0];
+ instance.settings.container.unbind( 'touchend' );
+ instance.settings.container.bind( 'touchend' , function( emm ) {
+ stopEventPropagation( emm );
+ $levelHolder.significance = 0;
+ $levelHolder.swipeStart = 0;
+ instance.settings.container.unbind( 'touchend' );
+ });
+ if ( $levelHolder.swipeStart != undefined && $levelHolder.swipeStart != 0 ) {
+ $levelHolder.significance = touch.pageX - $levelHolder.swipeStart;
+ }
+ else {
+ $levelHolder.significance = 0;
+ $levelHolder.swipeStart = touch.pageX;
+ return true;
+ }
+ if( Math.abs( $levelHolder.significance ) > instance.settings.overlapWidth*.3 ) {
+ if( instance.settings.direction == 'rtl' ) $levelHolder.significance *= ( -1 );
+ ( $levelHolder.significance > 0 ) ? expandMenu( ( level == undefined ) ? level : $levelHolder ) : collapseMenu( level );
+ $levelHolder.significance = 0;
+ $levelHolder.swipeStart = 0;
+ }
+ }
+ else if( instance.settings.swipe != 'touchscreen' ) {
+ stopEventPropagation( emd );
+ var significance = 0;
+ $levelHolder.unbind( 'mousemove' );
+ $levelHolder.bind( 'mousemove' , function( emm ){
+ significance = emm.clientX - emd.clientX;
+ if( Math.abs( significance ) > instance.settings.overlapWidth*.3 ) {
+ $levelHolder.unbind( 'mousemove' );
+ if( instance.settings.direction == 'rtl' ) significance *= ( -1 );
+ ( significance > 0 ) ? expandMenu( ( level == undefined ) ? level : $levelHolder ) : collapseMenu( level );
+ return true;
+ }
+ });
+ instance.settings.container.unbind( 'mouseup' );
+ instance.settings.container.bind( 'mouseup' , function(e){
+ stopEventPropagation( e );
+ $levelHolder.unbind( 'mousemove' );
+ instance.settings.container.unbind( 'mouseup' );
+ });
+ }
+ }
+
+ // Returns visible level holders
+ function visibleLevelHolders() {
+ var $visibleLevelHolders = instance.settings.container
+ .find( '#' + instance.settings.menuID + ' div.levelHolderClass' )
+ .filter(function(){
+ var retObjs = ( instance.settings.direction == 'rtl' ) ?
+ ( parseInt( $( this ).css( 'margin-right' ) ) >= 0 && $( this ).position().left < instance.settings.container.width() - instance.settings.overlapWidth )
+ :
+ ( parseInt( $( this ).css( 'margin-left' ) ) >= 0 && $( this ).position().left >= 0 );
+ return retObjs;
+ });
+ if( $visibleLevelHolders.length < 1 ) $visibleLevelHolders = false;
+ return $visibleLevelHolders;
+ }
+
+ // Returns hidden level holders
+ function hiddenLevelHolders() {
+ var $hiddenLevelHolders = instance.settings.container
+ .find( '#' + instance.settings.menuID + ' div.levelHolderClass' )
+ .filter(function(){
+ var retObjs = ( instance.settings.direction == 'rtl' ) ?
+ ( ( $( this ).position().left > instance.settings.container.width() || parseInt( $( this ).css( 'margin-right' ) ) < 0 ) )
+ :
+ ( ( $( this ).position().left < 0 || parseInt( $( this ).css( 'margin-left' ) ) < 0 ) );
+ return retObjs;
+ });
+ if( $hiddenLevelHolders.length < 1 ) $hiddenLevelHolders = false;
+ return $hiddenLevelHolders;
+ }
+
+ // Sizing DOM elements per creation/update
+ function sizeDOMelements() {
+ if( !instance.redraw ) {
+ instance.redraw = true;
+ var forceWidth = arguments[0],
+ forceHeight = arguments[1],
+ filter = arguments[2],
+ ieShadowFilterDistortion = ($('#' + instance.settings.menuID + ' div.levelHolderClass').first().css('filter').match(/DXImageTransform\.Microsoft\.Shadow/)) ? $('#' + instance.settings.menuID + ' div.levelHolderClass').first().get(0).filters.item("DXImageTransform.Microsoft.Shadow").strength : 0,
+ maxWidth = ( forceWidth == undefined ) ? Math.max.apply( null,
+ $('#' + instance.settings.menuID + ' div.levelHolderClass').map(function(){ return $(this).width(); }).get() ) - ieShadowFilterDistortion : forceWidth - ieShadowFilterDistortion,
+ maxLevel = Math.max.apply( null,
+ $('#' + instance.settings.menuID + ' div.levelHolderClass').map(function(){ return $(this).attr( 'data-level' ); }).get() ),
+ extWidth = ( isValidDim( instance.settings.menuWidth ) || ( isInt( instance.settings.menuWidth ) && instance.settings.menuWidth > 0 ) ),
+ extHeight = ( isValidDim( instance.settings.menuHeight ) || ( isInt( instance.settings.menuHeight ) && instance.settings.menuHeight > 0 ) ),
+ $objects = ( filter == undefined ) ? $('#' + instance.settings.menuID + ' div.levelHolderClass' ) : filter,
+ currWidth;
+ if ( !extWidth && instance.menuWidth != undefined ) maxWidth = instance.menuWidth;
+ ( extWidth && forceWidth == undefined ) ? $objects.width(instance.settings.menuWidth) : $objects.width( maxWidth );
+ if( extWidth ){
+ if( ( $objects.width() == 0 || ( isValidDim( instance.settings.menuWidth ) && instance.settings.menuWidth.indexOf( '%' ) != -1 ) ) && forceWidth == undefined ) {
+ $objects.css( 'min-width' , '' );
+ $objects.width( parseInt( instance.settings.container.parent().width() * parseInt( instance.settings.menuWidth )/100 ) )
+ };
+ maxWidth = $objects.width() - ieShadowFilterDistortion;
+ $objects.css( 'min-width' , $objects.width() - ieShadowFilterDistortion + 'px' );
+ }
+ var maxExtWidth = ( extWidth && forceWidth == undefined ) ? ( $objects.width() - ieShadowFilterDistortion + maxLevel * ( instance.settings.overlapWidth + ieShadowFilterDistortion ) ) : ( maxWidth + maxLevel * ( instance.settings.overlapWidth + ieShadowFilterDistortion ) ),
+ maxHeight = ( forceHeight == undefined ) ? Math.max.apply( null,
+ $('#' + instance.settings.menuID + ' div.levelHolderClass').map(function(){ return $(this).height(); }).get() ) : forceHeight;
+
+ instance.settings.container.css( 'min-height' , '' );
+ instance.settings.container.children( 'nav:first' ).css( 'min-height' , '' );
+ if( extHeight ) {
+ instance.settings.container.height( instance.settings.menuHeight );
+ instance.settings.container.css( 'min-height' , instance.settings.menuHeight );
+ instance.settings.container.children( 'nav:first' ).css( 'min-height' , instance.settings.menuHeight );
+ $('#' + instance.settings.menuID).height(instance.settings.menuHeight);
+ maxHeight = instance.settings.container.height();
+ }
+ else {
+ $('#' + instance.settings.menuID).height( maxHeight );
+ }
+ instance.settings.container.css( 'min-height' , maxHeight + 'px' );
+ instance.settings.container.children( 'nav:first' ).css( 'min-height' , maxHeight + 'px' );
+ instance.settings.container.width( maxExtWidth );
+ instance.settings.container.height( maxHeight );
+ var $baseLevelHolder = $('#' + instance.settings.menuID + ' div.levelHolderClass:first'),
+ $visibleLevelHolders = visibleLevelHolders(),
+ $hiddenLevelHolders = hiddenLevelHolders(),
+ $activeLevelHolder = activeMenu(),
+ activeLevel = ( $activeLevelHolder.length == 1 ) ? $activeLevelHolder.attr( 'data-level' ) : 0;
+ if( $visibleLevelHolders )
+ $visibleLevelHolders.each(function(){
+ if ( instance.settings.mode == 'overlap' )
+ $( this ).width( $( this ).width() + ( parseInt( activeLevel , 10) - parseInt( $( this ).attr( 'data-level' ) , 10) ) * ( instance.settings.overlapWidth + ieShadowFilterDistortion ) );
+ });
+ if( $hiddenLevelHolders )
+ $hiddenLevelHolders.each(function(){
+ ( instance.settings.direction == 'rtl' ) ?
+ $( this ).css( 'margin-right' , ( $( this ).attr( 'data-level' ) == $baseLevelHolder.attr( 'data-level' ) && !instance.settings.fullCollapse ) ? $( this ).width() * (-1) + instance.settings.overlapWidth : $( this ).width() * (-2) )
+ :
+ $( this ).css( 'margin-left' , ( $( this ).attr( 'data-level' ) == $baseLevelHolder.attr( 'data-level' ) && !instance.settings.fullCollapse ) ? $( this ).width() * (-1) + instance.settings.overlapWidth : $( this ).width() * (-2) );
+ });
+ currWidth = $baseLevelHolder.width() + parseInt( $baseLevelHolder.css( ( instance.settings.direction == 'rtl' ) ? 'margin-right' : 'margin-left' ) , 10 );
+ sizeElementWidth( instance.settings.container , currWidth );
+ instance.menuWidth = maxWidth;
+ instance.menuHeight = maxHeight;
+ instance.redraw = false;
+ }
+ }
+
+ // Simple/singe DOM element width sizing
+ function sizeElementWidth( $element , size ) {
+ if( $element == undefined || size == undefined ) return false;
+ $element.css( 'min-width' , '' );
+ $element.css( 'min-width' , size + 'px' );
+ $element.children( 'nav:first' ).css( 'min-width' , '' );
+ $element.children( 'nav:first' ).css( 'min-width' , size + 'px' );
+ $element.width( size );
+ }
+
+ // Hide wrappers in browsers that
+ // does not understand negative margin in %
+ // before DOM element got its dimensions
+ function fixLazyBrowsers() {
+ var $baseLevelHolder = $('#' + instance.settings.menuID + ' div.levelHolderClass:first'),
+ $hiddenLevelHolders = instance.settings.container
+ .find( '#' + instance.settings.menuID + ' div.levelHolderClass' )
+ .filter(function(){
+ var retObjs = ( instance.settings.direction == 'rtl' ) ?
+ ( ( $( this ).position().left > instance.settings.container.width() || parseInt( $( this ).css( 'margin-right' ) ) < 0 ) && $( this ).attr( 'data-level' ) > $baseLevelHolder.attr( 'data-level' ) )
+ :
+ ( ( $( this ).position().left < 0 || parseInt( $( this ).css( 'margin-left' ) ) < 0 ) && $( this ).attr( 'data-level' ) > $baseLevelHolder.attr( 'data-level' ) );
+ return retObjs;
+ });
+ $hiddenLevelHolders.each(function(){
+ if( instance.settings.direction == 'rtl' ){
+ $( this ).css( 'margin-right' , ( ( $( this ).attr( 'data-level' ) == $baseLevelHolder.attr( 'data-level' ) && !instance.settings.collapsed ) ? 0 : (-2) * $( this ).width() ) )
+ }
+ else {
+ $( this ).css( 'margin-left' , ( ( $( this ).attr( 'data-level' ) == $baseLevelHolder.attr( 'data-level' ) && !instance.settings.collapsed ) ? 0 : (-2) * $( this ).width() ) );
+ }
+ });
+ if( instance.settings.direction == 'rtl' ){
+ $baseLevelHolder.css( 'margin-right' , ( !instance.settings.collapsed ) ? 0 : (-2) * $baseLevelHolder.width() )
+ }
+ else {
+ $baseLevelHolder.css( 'margin-left' , ( !instance.settings.collapsed ) ? 0 : (-2) * $baseLevelHolder.width() );
+ }
+ }
+
+ // Is integer
+ function isInt( n ) {
+ return typeof n === 'number' && parseFloat( n ) == parseInt( n, 10 ) && !isNaN( n );
+ }
+
+ // Is Valid CSS dimension
+ function isValidDim( s ) {
+ return typeof s === 'string' && ( s.indexOf( '%' ) != -1 || s.indexOf( 'px' ) != -1 || s.indexOf( 'em' ) != -1 );
+ }
+
+ // Initialize menu level push menu
+ function initialize(){
+ var execute = ( options && options.menu != undefined ) ? createDOMStructure() : updateDOMStructure();
+ propagateEvent( instance.settings.container , clickEventType );
+ sizeDOMelements();
+ fixLazyBrowsers();
+ startMode( instance.settings.collapsed );
+ instance.settings.onMenuReady.apply(this, Array.prototype.slice.call([instance.settings]));
+ return $this;
+ }
+
+ // Initialize menu in collapsed/expanded mode
+ function startMode( mode ) {
+ if( mode ) {
+ var $baseLevelHolder = $('#' + instance.settings.menuID + ' div.levelHolderClass:first');
+ $baseLevelHolder.find( 'ul' ).hide();
+ $baseLevelHolder.addClass( instance.settings.menuInactiveClass );
+ if( instance.settings.direction == 'rtl' ) {
+ $baseLevelHolder.stop().animate({
+ marginRight: ( ( -1 ) * $baseLevelHolder.width() + ( ( instance.settings.fullCollapse ) ? 0 : instance.settings.overlapWidth ) )
+ }, instance.settings.durationSlideOut)
+ }
+ else {
+ $baseLevelHolder.stop().animate({
+ marginLeft: ( ( -1 ) * $baseLevelHolder.width() + ( ( instance.settings.fullCollapse ) ? 0 : instance.settings.overlapWidth ) )
+ }, instance.settings.durationSlideOut);
+ }
+ }
+ }
+
+ // Push container(s) of choice
+ function pushContainers( absMove ) {
+ if( instance.settings.containersToPush == null ) return false;
+ $.each( instance.settings.containersToPush, function() {
+ var lMr = parseInt( $( this ).css( 'margin-left' ) ),
+ lM = isInt( lMr ) ? lMr : 0,
+ rMr = parseInt( $( this ).css( 'margin-right' ) ),
+ rM = isInt( rMr ) ? rMr : 0;
+ $( this ).stop().animate({
+ marginLeft: lM + ( ( instance.settings.direction == 'rtl' ) ? (-1) : 1 ) * absMove,
+ marginRight: rM + ( ( instance.settings.direction == 'rtl' ) ? 1 : (-1) ) * absMove
+ }, instance.settings.durationSlideOut);
+ });
+ }
+
+ // Collapse menu
+ function collapseMenu() {
+ if( $(instance).find( 'div.levelHolderClass' ).is(':animated') ) return false;
+ instance.settings.onCollapseMenuStart.apply(this, Array.prototype.slice.call([instance.settings]));
+ var level = arguments[0],
+ callbacks = arguments[1],
+ collapingObjects = {},
+ ieShadowFilterDistortion,lwidth, lpush, lMarginLeft, lMarginLeftFC,
+ $baseLevelHolder = $('#' + instance.settings.menuID + ' div.levelHolderClass:first'),
+ collapseAll = ( level == undefined ) ? true : false,
+ currWidth;
+ collapingObjects[ 'collapsingEnded' ] = false;
+ if( typeof level == 'object' ) {
+ level = level.attr( 'data-level' );
+ }
+ else if( typeof level == 'string' ){
+ var $selectedLevelHolder = findMenusByTitle( level );
+ if( $selectedLevelHolder && $selectedLevelHolder.length == 1 ) {
+ level = $selectedLevelHolder.attr( 'data-level' );
+ }
+ else {
+ level = $baseLevelHolder.attr( 'data-level' );
+ }
+ }
+ else if( level == undefined || !isInt( level ) || level < 0 ) {
+ level = $baseLevelHolder.attr( 'data-level' );
+ }
+ if( callbacks == undefined && typeof callbacks != 'object' ) {
+ callbacks = [ { 'method' : instance.settings.onCollapseMenuEnd, 'args' : [instance.settings] } ];
+ } else {
+ $.merge(callbacks, [ { 'method' : instance.settings.onCollapseMenuEnd, 'args' : [instance.settings] } ]);
+ }
+ var $nextLevelHolders = instance.settings.container
+ .find( '#' + instance.settings.menuID + ' div.levelHolderClass' )
+ .filter(function(){
+ var retObjs = ( instance.settings.direction == 'rtl' ) ?
+ ($( this ).attr( 'data-level' ) > level) && (parseInt( $( this ).css( 'margin-right' ) ) >= 0 && $( this ).position().left < instance.settings.container.width() - instance.settings.overlapWidth )
+ :
+ ($( this ).attr( 'data-level' ) > level) && (parseInt( $( this ).css( 'margin-left' ) ) >= 0 && $( this ).position().left >= 0 );
+ return retObjs;
+ }),
+ $prevLevelHolders = instance.settings.container
+ .find( '#' + instance.settings.menuID + ' div.levelHolderClass' )
+ .filter(function(){
+ var retObjs = ( instance.settings.direction == 'rtl' ) ?
+ ($( this ).attr( 'data-level' ) <= level) && (parseInt( $( this ).css( 'margin-right' ) ) >= 0 && $( this ).position().left < instance.settings.container.width() - instance.settings.overlapWidth )
+ :
+ ($( this ).attr( 'data-level' ) <= level) && (parseInt( $( this ).css( 'margin-left' ) ) >= 0 && $( this ).position().left >= 0 );
+ return retObjs;
+ });
+ if( $prevLevelHolders.length > 0 ) {
+ collapingObjects[ 'prevAnimEnded' ] = false;
+ $nextLevelHolders.each(function( key, val ){
+ ieShadowFilterDistortion = ($( val ).css('filter').match(/DXImageTransform\.Microsoft\.Shadow/)) ? $( val ).get(0).filters.item("DXImageTransform.Microsoft.Shadow").strength : 0;
+ lwidth = ( instance.settings.mode == 'overlap' ) ? $( val ).width() - ( $nextLevelHolders.length + $prevLevelHolders.length - $( val ).attr( 'data-level' ) - 1) * ( instance.settings.overlapWidth + ieShadowFilterDistortion ) - ieShadowFilterDistortion : $( val ).width() - ieShadowFilterDistortion
+ if( instance.settings.direction == 'rtl' ) {
+ $( val ).stop().animate({
+ marginRight : ( (-1) * lwidth ),
+ width: lwidth
+ }, instance.settings.durationTransition);
+ }
+ else {
+ $( val ).stop().animate({
+ marginLeft : ( (-1) * lwidth ),
+ width: lwidth
+ }, instance.settings.durationTransition);
+ }
+ });
+ collapingObjects[ 'nextAnimEnded' ] = ( $nextLevelHolders.length > 0 ) ? false : true ;
+ $nextLevelHolders.last().queue(function(){
+ collapingObjects[ 'nextAnimEnded' ] = true;
+ animatedEventCallback( collapingObjects , callbacks );
+ });
+ $prevLevelHolders.each(function( key, val ){
+ ieShadowFilterDistortion = ($( val ).css('filter').match(/DXImageTransform\.Microsoft\.Shadow/)) ? $( val ).get(0).filters.item("DXImageTransform.Microsoft.Shadow").strength : 0;
+ var $makeLevelHolderVisible = $prevLevelHolders.filter(function(){
+ return $( this ).attr( 'data-level' ) == level;
+ });
+ $makeLevelHolderVisible.css( 'visibility' , 'visible' );
+ $makeLevelHolderVisible.find( '.' + instance.settings.backItemClass ).css( 'visibility' , 'visible' );
+ $makeLevelHolderVisible.find( 'ul' ).css( 'visibility' , 'visible' );
+ $makeLevelHolderVisible.removeClass( instance.settings.menuInactiveClass );
+ lwidth = ( instance.settings.mode == 'overlap' ) ? $( val ).width() - $nextLevelHolders.length * ( instance.settings.overlapWidth + ieShadowFilterDistortion ) - ieShadowFilterDistortion : $( val ).width() - ieShadowFilterDistortion;
+ if( instance.settings.direction == 'rtl' ) {
+ $( val ).stop().animate({
+ width: lwidth,
+ marginRight : ( $( val ).attr( 'data-level' ) == $baseLevelHolder.attr( 'data-level' ) && collapseAll ) ?
+ ( instance.settings.fullCollapse ) ?
+ ( -1 ) * $( val ).width()
+ :
+ ( ( -1 ) * $( val ).width() + ( ( instance.settings.mode == 'overlap' ) ? $nextLevelHolders.length + 1 : 1 ) * instance.settings.overlapWidth )
+ :
+ 0
+ }, instance.settings.durationSlideOut, function(){
+ if( $( val ).attr( 'data-level' ) == $baseLevelHolder.attr( 'data-level' ) && collapseAll ){
+ $baseLevelHolder.children( 'ul' ).first().hide(instance.settings.durationSlideDown, function(){
+ $baseLevelHolder.addClass( instance.settings.menuInactiveClass );
+ });
+ }
+ currWidth = $baseLevelHolder.width() + parseInt( $baseLevelHolder.css( 'margin-right' ) , 10 );
+ sizeElementWidth( instance.settings.container , currWidth );
+ });
+ }
+ else {
+ $( val ).stop().animate({
+ width: lwidth,
+ marginLeft : ( $( val ).attr( 'data-level' ) == $baseLevelHolder.attr( 'data-level' ) && collapseAll ) ?
+ ( instance.settings.fullCollapse ) ?
+ ( -1 ) * $( val ).width()
+ :
+ ( ( -1 ) * $( val ).width() + ( ( instance.settings.mode == 'overlap' ) ? $nextLevelHolders.length + 1 : 1 ) * instance.settings.overlapWidth )
+ :
+ 0
+ }, instance.settings.durationSlideOut, function(){
+ if( $( val ).attr( 'data-level' ) == $baseLevelHolder.attr( 'data-level' ) && collapseAll ){
+ $baseLevelHolder.children( 'ul' ).first().hide(instance.settings.durationSlideDown, function(){
+ $baseLevelHolder.addClass( instance.settings.menuInactiveClass );
+ });
+ }
+ currWidth = $baseLevelHolder.width() + parseInt( $baseLevelHolder.css( 'margin-left' ) , 10 );
+ sizeElementWidth( instance.settings.container , currWidth );
+ });
+ }
+ lpush = ( instance.settings.mode == 'overlap' ) ? ( (-1) * ( $nextLevelHolders.length * ( instance.settings.overlapWidth + ieShadowFilterDistortion ) ) ) : 0 ;
+ if( $( val ).attr( 'data-level' ) == $baseLevelHolder.attr( 'data-level' ) && collapseAll ){
+ var blpush = ( instance.settings.fullCollapse ) ? ( -1 ) * ( $baseLevelHolder.width() - ieShadowFilterDistortion ) : ( -1 ) * ( $baseLevelHolder.width() - ieShadowFilterDistortion ) + instance.settings.overlapWidth;
+ pushContainers( blpush );
+ }
+ else {
+ pushContainers( lpush );
+ }
+ });
+ $prevLevelHolders.last().queue(function(){
+ collapingObjects[ 'prevAnimEnded' ] = true;
+ animatedEventCallback( collapingObjects , callbacks );
+ });
+ }
+ collapingObjects[ 'collapsingEnded' ] = true;
+ animatedEventCallback( collapingObjects , callbacks );
+ return $this;
+ }
+
+ // Expand Menu helper
+ function expandMenuActions() {
+ if( $(instance).find( 'div.levelHolderClass' ).is(':animated') ) return false;
+ instance.settings.onExpandMenuStart.apply(this, Array.prototype.slice.call([instance.settings]));
+ var menuTitle = arguments[0],
+ callbacks = arguments[1],
+ ieShadowFilterDistortion, lwidth, lpush, blpush, currWidth,
+ expandingObjects = {},
+ $baseLevelHolder = $('#' + instance.settings.menuID + ' div.levelHolderClass:first'),
+ baseExpand = ( menuTitle == undefined ) ? true : false,
+ baseLevelHolderCollapsed = ( instance.settings.direction == 'rtl' ) ?
+ parseInt( $baseLevelHolder.css( 'margin-right' ), 10 ) < 0 || $baseLevelHolder.position().left >= instance.settings.container.width() - instance.settings.overlapWidth
+ :
+ parseInt( $baseLevelHolder.css( 'margin-left' ), 10 ) < 0 || $baseLevelHolder.position().left < 0;
+ expandingObjects[ 'expandingEnded' ] = false;
+ if( callbacks == undefined && typeof callbacks != 'object' ) {
+ callbacks = [ { 'method' : instance.settings.onExpandMenuEnd, 'args' : [instance.settings] } ];
+ } else {
+ $.merge(callbacks, [ { 'method' : instance.settings.onExpandMenuEnd, 'args' : [instance.settings] } ]);
+ }
+ if( baseExpand ) {
+ expandingObjects[ 'baseAnimEnded' ] = false;
+ $baseLevelHolder.removeClass( instance.settings.menuInactiveClass );
+ currWidth = $baseLevelHolder.width();
+ sizeElementWidth( instance.settings.container , currWidth );
+ if( instance.settings.direction == 'rtl' ) {
+ $baseLevelHolder.stop().animate({
+ marginRight: 0
+ }, instance.settings.durationSlideOut, function(){
+ $baseLevelHolder.children( 'ul' ).first().show(instance.settings.durationSlideDown , function(){
+ expandingObjects[ 'baseAnimEnded' ] = true;
+ animatedEventCallback( expandingObjects , callbacks );
+ });
+ });
+ }
+ else {
+ $baseLevelHolder.stop().animate({
+ marginLeft: 0
+ }, instance.settings.durationSlideOut, function(){
+ $baseLevelHolder.children( 'ul' ).first().show(instance.settings.durationSlideDown , function(){
+ expandingObjects[ 'baseAnimEnded' ] = true;
+ animatedEventCallback( expandingObjects , callbacks );
+ });
+ });
+ }
+ blpush = ( instance.settings.fullCollapse ) ? $baseLevelHolder.width() : $baseLevelHolder.width() - instance.settings.overlapWidth;
+ var pushbm = ( !menuExpanded( $baseLevelHolder ) ) ? pushContainers( blpush ) : null;
+ } else {
+ var $selectedLevelHolder;
+ if( typeof menuTitle == 'object' ) {
+ $selectedLevelHolder = menuTitle;
+ }
+ else if( typeof menuTitle == 'string' ){
+ $selectedLevelHolder = findMenusByTitle( menuTitle );
+ }
+ else {
+ $selectedLevelHolder = null;
+ $.error( 'Provided menu selector is not valid' );
+ }
+ if( $selectedLevelHolder && $selectedLevelHolder.length == 1 ) {
+ var $activeLevelHolder = activeMenu(),
+ activeLevel = ( $activeLevelHolder.length == 1 ) ? $activeLevelHolder.attr( 'data-level' ) : 0,
+ baseWidth = $selectedLevelHolder.width(),
+ setToOpenHolders = pathToRoot( $selectedLevelHolder );
+ expandingObjects[ 'setToOpenAnimEnded' ] = false;
+ if( setToOpenHolders ) {
+ var parentLevelHoldersLen = $( setToOpenHolders ).length - 1;
+ $baseLevelHolder.find( 'ul' ).each(function(){
+ $( this ).show(0);
+ });
+ $( setToOpenHolders ).find( 'ul' ).css( 'visibility' , 'hidden' );
+ $( setToOpenHolders ).find( 'div' ).css( 'visibility' , 'visible' );
+ $( setToOpenHolders ).find( '.' + instance.settings.backItemClass ).css( 'visibility' , 'hidden' );
+ $( setToOpenHolders ).each( function( key, val ) {
+ ieShadowFilterDistortion = ($( val ).css('filter').match(/DXImageTransform\.Microsoft\.Shadow/)) ? $( val ).get(0).filters.item("DXImageTransform.Microsoft.Shadow").strength : 0;
+ lwidth = baseWidth - ieShadowFilterDistortion + ( parentLevelHoldersLen - $( val ).attr( 'data-level' ) ) * ( instance.settings.overlapWidth + ieShadowFilterDistortion );
+ if(instance.settings.container.width() < lwidth && instance.settings.mode == 'overlap' )
+ sizeElementWidth( instance.settings.container , lwidth );
+ if( instance.settings.direction == 'rtl' ) {
+ $( val ).stop().animate({
+ marginRight: 0,
+ width: ( instance.settings.mode == 'overlap' ) ? lwidth : baseWidth - ieShadowFilterDistortion
+ }, instance.settings.durationTransition, function(){
+ $( val ).addClass( instance.settings.menuInactiveClass );
+ });
+ }
+ else {
+ $( val ).stop().animate({
+ marginLeft: 0,
+ width: ( instance.settings.mode == 'overlap' ) ? lwidth : baseWidth - ieShadowFilterDistortion
+ }, instance.settings.durationTransition, function(){
+ $( val ).addClass( instance.settings.menuInactiveClass );
+ });
+ }
+ });
+ $( setToOpenHolders ).last().queue(function(){
+ $( this ).removeClass( instance.settings.menuInactiveClass );
+ expandingObjects[ 'setToOpenAnimEnded' ] = true;
+ animatedEventCallback( expandingObjects , callbacks );
+ });
+ if( baseLevelHolderCollapsed ) {
+ blpush = ( instance.settings.fullCollapse ) ? $baseLevelHolder.width() : ( $baseLevelHolder.width() - instance.settings.overlapWidth );
+ pushContainers( blpush );
+ }
+ if( instance.settings.mode == 'overlap' ){
+ lpush = ( ( baseLevelHolderCollapsed ) ? ( baseWidth + ( parentLevelHoldersLen - ( ( instance.settings.fullCollapse ) ? 0 : 1 ) ) * ( instance.settings.overlapWidth + ieShadowFilterDistortion ) ) : ( ( parentLevelHoldersLen - activeLevel ) * ( instance.settings.overlapWidth + ieShadowFilterDistortion ) ) );
+ pushContainers( lpush );
+ }
+ $selectedLevelHolder.css( 'visibility' , 'visible' );
+ $selectedLevelHolder.find( '.' + instance.settings.backItemClass ).css( 'visibility' , 'visible' );
+ $selectedLevelHolder.find( 'ul' ).css( 'visibility' , 'visible' );
+ $selectedLevelHolder.removeClass( instance.settings.menuInactiveClass );
+ }
+ else {
+ $.error( 'Invalid menu object provided' );
+ }
+ }
+ else {
+ $.error( 'No or too many menus named ' + menuTitle );
+ }
+ }
+ expandingObjects[ 'expandingEnded' ] = true;
+ animatedEventCallback( expandingObjects , callbacks );
+ }
+
+ // Expand menu
+ function expandMenu() {
+ var menu = arguments[0],
+ $expandLevelHolder,
+ $activeLevelHolder = activeMenu(),
+ $sharedLevelHolders, collapseLevel, $searchRes;
+ if( typeof menu == 'object' ) {
+ $expandLevelHolder = menu;
+ }
+ else if( typeof menu == 'string' ){
+ $searchRes = findMenusByTitle( menu );
+ if($searchRes) {
+ $expandLevelHolder = $searchRes.eq( 0 );
+ }
+ else {
+ $.error( menu + ' menu level does not exist!' );
+ }
+ }
+ else {
+ $expandLevelHolder = $('#' + instance.settings.menuID + ' div.levelHolderClass:first');
+ }
+ $sharedLevelHolders = comparePaths( $expandLevelHolder , $activeLevelHolder, true );
+ collapseLevel = ( $sharedLevelHolders.length > 0 ) ? Math.max.apply( null,
+ $sharedLevelHolders.map(function(){ return $(this).attr( 'data-level' ); }).get() ) : 0;
+ if( collapseLevel < $activeLevelHolder.attr( 'data-level' ) ) {
+ collapseMenu( collapseLevel , [ { 'method' : expandMenuActions, 'args' : arguments } ] );
+ }
+ else {
+ expandMenuActions.apply( this, Array.prototype.slice.call( arguments ) );
+ }
+ return $this;
+ }
+
+ // Find menu(s) by Title text
+ function findMenusByTitle() {
+ var menuTitle = arguments[0],
+ response,
+ $selectedLevelHolders = instance.settings.container
+ .find( '#' + instance.settings.menuID + ' div.levelHolderClass' )
+ .filter(function(){
+ return ( ($( this ).children( 'h2' ).text() == menuTitle ) );
+ });
+ if( $selectedLevelHolders.length > 0 ) {
+ returnValue = $selectedLevelHolders;
+ response = returnValue;
+ }
+ else {
+ returnValue = false;
+ response = returnValue;
+ }
+ return response;
+ }
+
+ // Find item(s) by Name
+ function findItemsByName() {
+ var itemName = arguments[0],
+ response,
+ $selectedItems = instance.settings.container
+ .find( '#' + instance.settings.menuID + ' div.levelHolderClass li' )
+ .filter(function(){
+ return ( ($( this ).children( 'a' ).text() == itemName ) );
+ });
+ if( $selectedItems.length > 0 ) {
+ returnValue = $selectedItems;
+ response = returnValue;
+ }
+ else {
+ returnValue = false;
+ response = returnValue;
+ }
+ return response;
+ }
+
+ // Find pathToRoot for provided menu
+ function pathToRoot() {
+ var $selectedLevelHolder = arguments[0],
+ $parentLevelHolders, setToOpenHolders, response;
+ if( $selectedLevelHolder == undefined || $selectedLevelHolder.length != 1 ) {
+ returnValue = false;
+ return returnValue;
+ };
+ $parentLevelHolders = $selectedLevelHolder.parents( 'div.levelHolderClass' );
+ setToOpenHolders = $.merge( $parentLevelHolders.get().reverse(), $selectedLevelHolder.get() );
+ returnValue = setToOpenHolders;
+ return returnValue;
+ }
+
+ // Finds the same part of the path to root of two provided menus
+ function comparePaths() {
+ var $levelHolder0 = arguments[0],
+ $levelHolder1 = arguments[1],
+ mode = ( arguments[2] != undefined ) ? arguments[2] : false,
+ $parentLevelHolders0, $parentLevelHolders1, setParents0, setParents1, lPath, sPath, comparePath, response;
+ if( $levelHolder0 == undefined || $levelHolder1 == undefined ) {
+ returnValue = false;
+ return returnValue;
+ };
+ $parentLevelHolders0 = ( $levelHolder0.length == 1 ) ? $levelHolder0.parents( 'div.levelHolderClass' ) : null;
+ $parentLevelHolders1 = ( $levelHolder1.length == 1 ) ? $levelHolder1.parents( 'div.levelHolderClass' ) : null;
+ setParents0 = ( $parentLevelHolders0 != null ) ? $.merge( $parentLevelHolders0.get().reverse(), $levelHolder0.get() ) : [];
+ setParents1 = ( $parentLevelHolders1 != null ) ? $.merge( $parentLevelHolders1.get().reverse(), $levelHolder1.get() ) : [];
+ lPath = ( setParents0.length >= setParents1.length ) ? setParents0 : setParents1;
+ sPath = ( lPath === setParents0 ) ? setParents1 : setParents0;
+ comparePath = $( lPath ).filter(function() {
+ return ( mode ) ? ( $.inArray( this, sPath ) != -1 ) : ( $.inArray( this, sPath ) == -1 );
+ });
+ returnValue = comparePath;
+ return returnValue;
+ }
+
+ // Active menu
+ function activeMenu() {
+ var $activeLevelHolders = instance.settings.container
+ .find( '#' + instance.settings.menuID + ' div.levelHolderClass' )
+ .filter(function(){
+ var retObjs = ( instance.settings.direction == 'rtl' ) ?
+ ((parseInt( $( this ).css( 'margin-right' ) ) >= 0 && $( this ).position().left < instance.settings.container.width() - instance.settings.overlapWidth ) )
+ :
+ ((parseInt( $( this ).css( 'margin-left' ) ) >= 0 && $( this ).position().left >= 0 ) );
+ return retObjs;
+ }),
+ maxLevel = Math.max.apply( null,
+ $activeLevelHolders.map(function(){ return $(this).attr( 'data-level' ); }).get() ),
+ $activeLevelHolder = $activeLevelHolders.filter(function(){
+ return $( this ).attr( 'data-level' ) == maxLevel;
+ });
+ returnValue = $activeLevelHolder;
+ return returnValue;
+ }
+
+ // Menu expanded
+ function menuExpanded() {
+ var $levelHolder = arguments[0],
+ returnValue = false;
+ if( $levelHolder == undefined ) return returnValue;
+
+ var check = ( instance.settings.direction == 'rtl' ) ?
+ ( parseInt( $levelHolder.css( 'margin-right' ) ) >= 0 && $levelHolder.position().left < instance.settings.container.width() - instance.settings.overlapWidth )
+ :
+ ( parseInt( $levelHolder.css( 'margin-left' ) ) >= 0 && $levelHolder.position().left >= 0 );
+ return check;
+ }
+
+ // Add item(s)
+ function addItems() {
+ var items = arguments[0],
+ $levelHolder = arguments[1],
+ position = arguments[2];
+ if( $levelHolder == undefined || typeof items != 'object' || !$levelHolder ) return false;
+ if( items.level == undefined ) items.level = parseInt( $levelHolder.attr( 'data-level' ) , 10 );
+ if( position == undefined ) position = 0;
+ var $itemGroup = $levelHolder.find( 'ul:first' );
+ $.each(items, function() {
+ if( this.name != undefined )
+ createItem( this, $levelHolder, position );
+ });
+ sizeDOMelements( instance.menuWidth );
+ return $this;
+ }
+
+ // Remove item(s)
+ function removeItems() {
+ var $items = arguments[0];
+ if( $items == undefined || typeof $items != 'object' || $items.length == 0 ) return false;
+ $items.remove();
+ var $activeMenu = activeMenu();
+ if( $activeMenu.length == 1 ) {
+ $activeMenu.css( 'visibility' , 'visible' );
+ $activeMenu.find( '.' + instance.settings.backItemClass ).css( 'visibility' , 'visible' );
+ $activeMenu.find( 'ul' ).css( 'visibility' , 'visible' );
+ $activeMenu.removeClass( instance.settings.menuInactiveClass );
+ var widthDiff = $activeMenu.width() - instance.menuWidth;
+ if( widthDiff != 0 ) {
+ var $visibleLevelHolders = visibleLevelHolders();
+ if( $visibleLevelHolders )
+ $visibleLevelHolders.each(function(){
+ $( this ).width( $( this ).width() - widthDiff );
+ });
+ }
+ }
+ sizeDOMelements( instance.menuWidth );
+ return $this;
+ }
+
+ // Manage multiple animated events and associated callbacks
+ function animatedEventCallback( animatedObjects, callbacks ) {
+ var doCallBack = true;
+ $.each( animatedObjects, function( key, val ){
+ doCallBack = doCallBack && val;
+ });
+ if( doCallBack )
+ window.setTimeout(function(){
+ $.each( callbacks, function( key, val ){
+ val['method'].apply( this, Array.prototype.slice.call( val['args'] ) );
+ });
+ }, 1);
+ }
+
+ // Get/set settings options
+ function manageOptions() {
+ var response = false;
+ if( instance.settings[arguments[0]] != undefined ) {
+ if( arguments[1] != undefined )
+ instance.settings[arguments[0]] = arguments[1];
+ response = instance.settings[arguments[0]];
+ } else {
+ $.error('No option ' + arguments[0] + ' found in jQuery.multilevelpushmenu');
+ }
+ return response;
+ }
+
+ // Mobile check
+ // http://coveroverflow.com/a/11381730/989439
+ function mobileCheck() {
+ var check = false;
+ (function(a){if(/(android|ipad|playbook|silk|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
+ return check;
+ }
+
+ if( mobileCheck() ) {
+ clickEventType = 'touchend';
+ dragEventType = 'touchmove';
+ }
+ else {
+ clickEventType = 'click';
+ dragEventType = 'mousedown';
+ }
+
+ // Invoke called method or init
+ if ( methods[options] ) {
+ returnValue = methods[options].apply(this, Array.prototype.slice.call(args, 1));
+ return returnValue;
+ } else if (typeof options === 'object' || !options) {
+ returnValue = methods.init.apply(this, arguments);
+ return returnValue;
+ } else {
+ $.error('No ' + options + ' method found in jQuery.multilevelpushmenu');
+ }
+
+ // Return object instance or option value
+ if (!returnValue) {
+ returnValue = this;
+ }
+ });
+ return returnValue;
+ }
+}( jQuery ));