function Menu( elem, params ){ this.element = jQuery(elem); this.params = params || {}; this.classActiveItem = this.params.classActiveItem || 'JS-Menu-Item-active'; this.fadeDuration = this.params.fadeDuration || 400; this.durationMultiplier = this.params.durationMultiplier || 5; this.minHeight = this.params.minHeight || 0; this.__construct(); } Menu.prototype.__construct = function(){ this._isBusy = false; this.items = this.element.find('.JS-Menu-Item').has('.JS-Menu-Subitems'); this.buttons = this.element.find('.JS-Menu-Button'); this.subitems = this.element.find('.JS-Menu-Subitems'); this.active = jQuery('.JS-Menu-Active').remove().removeClass('g-hidden'); this.submenu = jQuery('.JS-Menu-Submenu'); this.activeHeight = this.active.css({'visibility' : 'hidden'}).appendTo('body').height(); this.active.remove().css({'visibility' : 'visible'}); this._init(); }; Menu.prototype._init = function(){ var context = this; this.items.has(this.subitems).find(this.buttons).bind('click', function(){ return context.setActiveItem.apply(context, [jQuery(this)]) }); this._openSub(this.items.filter('.JS-Menu-Item-active'), 0); }; Menu.prototype.setActiveItem = function( button ){ if( this._isBusy ){ return false; } var item = this.items.has(button), current = this.items.filter('.JS-Menu-Item-active'), itemLen = item.length, currentLen = current.length; if( !currentLen ){ this._openSub(item, this.durationMultiplier); }else if( itemLen && current[0] != item[0] ){ this._updateSub(item); }else{ this._closeSub(item, this.durationMultiplier); } return false; }; Menu.prototype._closeSub = function( item, durationMultiplier ){ this._isBusy = true; var context = this, subWrapper = this.submenu.parent(), subHeight = subWrapper.height() - this.minHeight; item.removeClass(this.classActiveItem).removeClass('JS-Menu-Item-active'); subWrapper.animate({'height' : this.minHeight + 'px'}, subHeight * durationMultiplier, function(){ context.cb_closeSub.apply(context, [item, durationMultiplier]); }); return false; }; Menu.prototype.cb_closeSub = function( item, durationMultiplier ){ var subWrapper = this.submenu.parent(); subWrapper.css({'height' : this.minHeight + 'px'}); this.submenu.find(this.subitems).appendTo(item).css({'margin-left' : '0px'}); this.active.css({'height' : '0px'}); this.final_closeSub(item); }; Menu.prototype.final_closeSub = function( item ){ this._isBusy = false; }; Menu.prototype._openSub = function( item, durationMultiplier ){ if( !item.length ){ return false; } this._isBusy = true; var context = this, position = 0; item.addClass(this.classActiveItem).addClass('JS-Menu-Item-active'); this.submenu.append(item.find(this.subitems)); this.active.css({'height' : '0px'}).appendTo(item).animate({'height' : this.activeHeight + 'px'}, this.activeHeight * durationMultiplier, function(){ context.cb_openSub.apply(context, [item, durationMultiplier]); }); return false; }; Menu.prototype.cb_openSub = function( item, durationMultiplier ){ var viewportLeft, viewportWidth, subitemsPosition, subitemsWidth, context = this, subWrapper = this.submenu.parent(), subHeight = this.submenu.height(), subitems = this.submenu.find(this.subitems); subWrapper.css({'width' : '100%', 'height' : this.minHeight + 'px'}); viewportLeft = this.submenu.offset().left; viewportWidth = this.submenu.width(); subitemsPosition = item.offset().left - viewportLeft; subitemsWidth = subitems.outerWidth(true); if( subitemsPosition + subitemsWidth > viewportWidth ){ subitemsPosition = viewportWidth - subitemsWidth - 1; } subitemsPosition = subitemsPosition < 0 ? 0 : subitemsPosition; subitems.css({'margin-left' : subitemsPosition + 'px'}); subWrapper.animate({'height' : subHeight + 'px'}, (subHeight - this.minHeight) * durationMultiplier, function(){ context.final_openSub.apply(context, [item]); }); }; Menu.prototype.final_openSub = function( item ){ this._isBusy = false; }; Menu.prototype._updateSub = function( item ){ this._isBusy = true; var context = this, current = this.items.filter('.JS-Menu-Item-active'); current.removeClass(this.classActiveItem).removeClass('JS-Menu-Item-active'); item.addClass(this.classActiveItem).addClass('JS-Menu-Item-active'); this.submenu.find(this.subitems).css({'opacity' : '1'}).animate({'opacity' : '0'}, this.fadeDuration/2, function(){ context.cb_updateSub.apply(context, [item, current]); }); return false; }; Menu.prototype.cb_updateSub = function( item, current ){ var subitemsWidth, context = this, viewportLeft = this.submenu.offset().left, viewportWidth = this.submenu.width(), subitems = item.find(this.subitems).css({'opacity' : '0'}), subitemsPosition = item.offset().left - viewportLeft; item.append(this.active); this.submenu.find(this.subitems).appendTo(current).css({'opacity' : '1', 'margin-left' : '0px'}); this.submenu.append(subitems); subitemsWidth = subitems.outerWidth(true); if( subitemsPosition + subitemsWidth > viewportWidth ){ subitemsPosition = viewportWidth - subitemsWidth - 1; } subitemsPosition = subitemsPosition < 0 ? 0 : subitemsPosition; subitems.css({'margin-left' : subitemsPosition + 'px'}); subitems.animate({'opacity' : '1'}, this.fadeDuration/2, function(){ context.final_updateSub.apply(context, [item, current]); }); }; Menu.prototype.final_updateSub = function( item, current ){ this._isBusy = false; }; /*--/menu--*/