

/*

 * superfish_width_mod v0.3 beta

 * Copyright (c) 2009 Cy Morris

 *

 * Dual licensed under the MIT and GPL licenses:

 * 	http://www.opensource.org/licenses/mit-license.php

 * 	http://www.gnu.org/licenses/gpl.html

 * 

 * Dependencies: jQuery

 *

 * Description: Allows you to set the width of your Superfish menu and have menu items automatically resized to fit.

 

	There are 5 different sizing options:

		1. Don't resize anything (disable this mod)

			HOW: disableMod: true

		2. Make all top menu items the same width, including separators

		   NOTE: If an item is already too big, it will be left too big and the remaining items will be shrunk

			HOW: equalWidth: true, resizeSeps: true

		3. Same as 1, but excluding separators (they will retain their original width)

			HOW: equalWidth: true, resizeSeps: false

		4. Resize each top menu item individually based on ratio of item width to menu width, including separators

			HOW: equalWidth: false, resizeSeps: true

		5. Same as 3, but excluding separators (they will retain their original width)

			HOW: equalWidth: false, resizeSeps: false

*/



;(function($){ // $ will refer to jQuery within this closure



	var defaults = {

		

		equalWidth: true,

		resizeSeps: false,

		vertical: false, // if it's a vertical menu, the items will all be set to 100% of the menu width

		

		/* set the menu width: can be number of pixels (format: 700,) or percent (format: '95%',) */

		menuWidth: 		'100%', 

		

		/* Resize submenus? If true, small submenus will be widened to match their parent item width */

		resizeSubMenus: true

		

	};

	

	var initialized = false;

								  

	$.fn.superfish_width_mod = function(options){

		// get options

		var opts = $.extend({}, $.fn.superfish_width_mod.defaults, options);



		// return original object to support chaining

		rVal = this.each(function() {

								  

			var menu = $(this);

			menu.timer = false;

			

			// support metadata

			var o = $.meta ? $.extend({}, opts, menu.data()) : opts;



			// cache all ul elements

			menuItems = menu.find('>li');



			var origMenuW   = menu.width();

			menu.width( o.menuWidth );

			newMenuW = menu.width();



			var sepAdjust 	= 0;

			var itemCount 	= menuItems.length;

			var itemsWidth = 0;



			// undo from previous resizes

			menuItems.each( function(){ $(this).removeClass('superfish_width_mod_skip'); });



			/*  SEPARATOR WIDTH ADJUSTMENT

				if there are separators but they are not to be resized, we need to adjust the newMenuW ratio to not 

				include them.  First we find each and gather it's width, then we subtract that from the newMenuW

			*/



			if( !o.vertical && !o.resizeSeps ) {

				menu.find('>li>span.separator').each( function() {

					$(this).parent().addClass('separator');

					$(this).parent().addClass('superfish_width_mod_skip');

					sepAdjust += $(this).parent().outerWidth(); // the width of the li

					itemCount--;

				} );

			}

			

			/*  END -- SEPARATOR WIDTH ADJUSTMENT  */

			

			/*  BIG MENU ITEMS ADJUSTMENT

				If equalWidth is set to true but some menu items are too big for the new item width, they 

				will retain their original width, so we have to adjust the newMenuW ratio to not include them

			*/

			if(!o.vertical && o.equalWidth) {

				menuItems.each( function() {

					mItem = $(this);

					if(mItem.hasClass('separator') && !o.resizeSeps) return; // already accounted for if true

					mItem.css('width','auto');

					if(mItem.width() > parseInt( (newMenuW-sepAdjust)/itemCount )) {

						mItem.addClass('superfish_width_mod_skip');

						sepAdjust += mItem.width();

						itemCount--;

					}

				} );

			}

//			alert(itemCount);



			/*  END -- BIG MENU ITEMS ADJUSTMENT */



			nW = 0;



			menuItems.each( function() {

				mItem = $(this);

				if(itemCount == 0) itemCount = 1;

				if(origMenuW == 0) origMenuW = 1;



				// if it's a vertical menu, items will be 100% the width

				if(o.vertical) newItemW = newMenuW;

				// large items and separators

				else if(mItem.hasClass('superfish_width_mod_skip')) newItemW = 0;//mItem.width();

				// resize equally

				else if(o.equalWidth) newItemW = parseInt( (newMenuW-sepAdjust)/itemCount );

				// resize by ratio

				else newItemW = parseInt( mItem.width()/(origMenuW-sepAdjust)*(newMenuW-sepAdjust) );

	

				// do the resize

				if(newItemW > 0) mItem.width( newItemW );

				nW += mItem.outerWidth(true);

				

				mItem.find('>ul').each( function() {

					subMenu = $(this);

					// resize submenus and move their submenus over

					if(o.vertical) {

						subMenu.css('left', newItemW+'px');

					} else if(o.resizeSubMenus && subMenu.width() < newItemW) {

						subMenu.width( newItemW );

						subMenu.find('>li>ul').css('left', newItemW+'px');

					}

				} );

				

			});

			// account for integer truncation ( 1.34232 would have become just 1 )

			while(nW < newMenuW) {

				for(var i=0; i<menuItems.length; i++) {

					mItem = $(menuItems[i]);

					if(mItem.hasClass('superfish_width_mod_skip')) continue;

					mItem.width( mItem.width()+1 );

					nW += 1;

					if(nW == newMenuW) break;

				}

			}

			while(nW > newMenuW) {

				for(var i=0; i<menuItems.length; i++) {

					mItem = $(menuItems[i]);

					if(mItem.hasClass('superfish_width_mod_skip')) continue;

					mItem.width( mItem.width()-1 );

					nW -= 1;

					if(nW == newMenuW) break;

				}

			}

			if(!initialized) $(window).resize( function() { 

				if(menu.timer) clearTimeout(menu.timer);

				menu.timer = setTimeout( 

					function() { 

						menu.superfish_width_mod(options); 

					}, 

					500

				)

			} );

		});



		initialized = true;

		return rVal;



	};

	// expose defaults

	$.fn.superfish_width_mod.defaults = defaults;

	

})(jQuery); // plugin code ends




