// SpryMenuBarIEWorkaroundsPlugin.js - version 0.8 - Spry Pre-Release 1.7//// Copyright (c) 2010. Adobe Systems Incorporated.// All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are met:////   * Redistributions of source code must retain the above copyright notice,//     this list of conditions and the following disclaimer.//   * Redistributions in binary form must reproduce the above copyright notice,//     this list of conditions and the following disclaimer in the documentation//     and/or other materials provided with the distribution.//   * Neither the name of Adobe Systems Incorporated nor the names of its//     contributors may be used to endorse or promote products derived from this//     software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE// POSSIBILITY OF SUCH DAMAGE.(function() { // BeginSpryComponentif (typeof Spry == "undefined" || !Spry.Widget || !Spry.Widget.MenuBar2){	alert("SpryMenuBarIEWorkaroundsPlugin.js requires SpryMenu.js!");	return;}var isIE6 = (window.ActiveXObject && !window.XMLHttpRequest);if (isIE6)	Spry.Utils.addClassName(document.documentElement, "SpryIsIE6");var isIE = window.ActiveXObject ? true : false;// This plugin attempts to workaround the following problems with IE6, IE7 and IE8://// A. Submenus render underneath <select> elements (IE6).////    - When the plugin is enabled, it will automatically insert transparent iframes beneath each//      subMenu. This has the effect of forcing the subMenu to render above elements like <select> that//      use native windows.//// B. Multiple class selectors are not supported (IE6).////    - IE6 does not support selectors that make use of multiple class names on a single element.//      For example a selector of the form .MenuItemWithSubMenu.MenuItemHover will be interpreted//      by IE6 as simply .MenuItemHover. To workaround this problem set the 'useCombinedClassNames'//      option for the plugin (true by default) which will generate combined class names such as//      .MenuItemWithSubMenuHover, .MenuItemFirstHover, .MenuItemFirstWithSubMenuHover, etc. Class//      names generated by this plugin are as follows:////          MenuItemFirstWithSubMenu//          MenuItemLastWithSubMenu//          MenuItemFirstHover//          MenuItemLastHover//          MenuItemWithSubMenuHover//          MenuItemFirstWithSubMenuHover//          MenuItemLastWithSubMenuHover//// C. Elements with position values other than 'static' establish a new z-index context (IE6).////    - This problem manifests itself when subMenus overlap. You will see subMenus rendering//      behind menu items that come after the subMenu's parent menu item. The solution for this//      is to set the z-index of the entire subMenu parent element hierarchy such that they are//      higher than any of their siblings. By default, the plugin will place a z-index of 1000//      on all parents of the currentSubMenu. You can change the z-index value by passing the//      'miContainerZIndex' option with the desired z-index integer value. If you would prefer//      to control the z-index via a CSS rule, set the 'miContainerHoverZIndex' option to undefined,//      and then use the class 'MenuItemContainerHover' in your stylesheet to set the desired//      z-index value.////      You can read more about this problem here:////          http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&postId=829&productId=1&loc=en_US//// D. <li> elements that contain <a> elements render with gaps below them. (IE6-IE8)////    - This one is a doozy to work around. For menu items with no subMenus, you can get rid of gaps//      by using this CSS trick:////          http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&postId=824&productId=1&loc=en_US////      But the trick above does not work for menu items with sub menus since once they become//      visible, IE6 adds the gap. There are all sorts of tricks that work in specific scenarios,//      that involve setting the <li> to inline and floating, etc, etc. But that doesn't seem to work//      in every styling case/situation. IE8 is especially sneaky, since the problem seems to be//		sensitive to the specific characters in the whitespace too, so can crop up after seemingly innocuous changes.//		The only fool-proof way to get rid of this problem is to get rid of the <ul> and <li> elements //		in the generated markup for the menubar.////      Getting rid of <ul>/<li> elements is the default behavior for this plugin. If you really want to deal//      with the headache/IE Hacks necessary to get rid of the gaps, you can turn this behavior off by setting//      the 'useDivs' option to false. If 'useDivs' is true, you will not have to use any tricks/hacks in your//      CSS to get rid of gaps.//// One other bug that you may see, while styling your menubar, that is *NOT* covered by this plugin is when// <a> tags are modified to be display:block, sometimes they are not clickable unless you click over the text.// this problem can be solved by using one of the tricks mentioned here:////    http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&postId=1643&productId=1&loc=en_USvar IEWP = Spry.Widget.MenuBar2.IEWorkaroundsPlugin = {	config: {		pluginOptionsProp:      "IEWP",		enablePlugin:           undefined, // true or false, if undefined, defaults to true for IE6-IE8		stripWhiteSpace:        false,		useDivs:                undefined, // defaults to true for all IE, false for other browsers.		useCombinedClassNames:  undefined,	// defaults to true for IE6, false for other IE and other browsers		miContainerZIndex:      undefined,		miContainerHoverZIndex: 1000	},	initialize: function(mb)	{		var opts = mb.setOptions({}, IEWP.config);		if (mb[opts.pluginOptionsProp])			mb.setOptions(opts, mb[opts.pluginOptionsProp]);				opts.useDivs = (opts.useDivs != undefined) ? opts.useDivs : isIE;		opts.useCombinedClassNames = (opts.useCombinedClassNames != undefined) ? opts.useCombinedClassNames : isIE6;		mb[opts.pluginOptionsProp] = opts;		// If the enabled property is undefined, we will automatically		// enable the plugin if running on IE.		var enabled = (opts.enablePlugin != undefined) ? opts.enablePlugin : isIE;		if (enabled)			mb.addObserver(this);	},	getOptions: function(mb)	{		return mb[IEWP.config.pluginOptionsProp];	},	getMenuItemContainer: function(mb, sm)	{		return sm ? Spry.Utils.getAncestor(sm, "." + mb.menuItemContainerClass) : null;	},	showSubMenuIFrame: function(mb, sm)	{		if (!sm.ieIFrame)		{			var iframe = document.createElement("iframe");			iframe.tabIndex = '-1';			iframe.src = 'javascript:""';			iframe.frameBorder = '0';			iframe.scrolling = 'no';			iframe.style.opacity = "0.01";			iframe.style.filter = "alpha(opacity=1)";			iframe.style.position = "absolute";			sm.ieIFrame = iframe;		}			var iframe = sm.ieIFrame;		iframe.style.top = sm.offsetTop + "px";		iframe.style.left = sm.offsetLeft + "px";		iframe.style.width = sm.offsetWidth + "px";		iframe.style.height = sm.offsetHeight + "px";		sm.parentNode.insertBefore(iframe, sm);	},	hideSubMenuIFrame: function(mb, sm)	{		if (sm)		{			var iframe = sm.ieIFrame;			if (iframe)			{				var p = iframe.parentNode;				if (p) p.removeChild(iframe);			}		}	},	stripTextNodes: function(ele)	{		var c = ele.firstChild;		while (c)		{			var n = c;			c = c.nextSibling;			if (n.nodeType == 3) // Node.TEXT_NODE				ele.removeChild(n);		}	},	getMenuItemClasses: function(mb, mi)	{		// MenuItem[First|Last]?[WithSubMenu]?[Hover]?		var results = [];		var posArr = [ "" ];		if (mb.hasClassName(mi, mb.menuItemFirstClass))			posArr.push("First");		if (mb.hasClassName(mi, mb.menuItemLastClass))			posArr.push("Last");		var hasSubMenu = mb.hasClassName(mi, mb.menuItemWithSubMenuClass);		var miClass = mb.menuItemClass;		for (var i = 0; i < posArr.length; i++)		{			var c = miClass + posArr[i];			results.push(c);			if (hasSubMenu)				results.push(c + "WithSubMenu");		}		return results;	},	getMenuItemHoverClasses: function(mb, mi)	{		var results = IEWP.getMenuItemClasses(mb, mi);		for (var i = 0; i < results.length; i++)			results[i] += "Hover";		return results;	},	onPostTransformMarkup: function(mb, evt)	{		var opts = IEWP.getOptions(mb);		if (opts.stripWhiteSpace)		{			var uls = Spry.$$("ul", mb.element);			for (var i = 0; i < uls.length; i++)			{				var ul = uls[i];				IEWP.stripTextNodes(ul);				var eles = mb.getElementChildren(ul);				for (var j = 0; j < eles.length; j++)					IEWP.stripTextNodes(eles[j]);			}		}		// IE6 has some issues with gaps between menu items. We can easily fix		// menu items with no submenus by either stripping the whitespace in and		// around <ul> and <li> elements, or we can use a zoom:1 property on the <li>		// elements, but that doesn't fix the gap problem when dealing with menu items		// that have submenus. To work around this and ease the styling hacks/pains, we		// can also convert ul/li elements to divs.		if (opts.useDivs)		{			var uls = Spry.$$("ul", mb.element);			for (var i = 0; i < uls.length; i++)			{				var ul = uls[i];				var div = document.createElement("div");				if (ul.id) div.id = div.id;				if (ul.className) div.className = ul.className;				var children = [];				var c = ul.firstChild;				while (c)				{					var n = c;					if (n.nodeName.toLowerCase() == "li")					{						n = document.createElement("div");						if (c.id) n.id = c.id;						if (c.className) n.className = c.className;						mb.appendChildNodes(n, mb.extractChildNodes(c));					}					children.push(n);					c = c.nextSibling;				}				var p = ul.parentNode;				p.insertBefore(div, ul);				p.removeChild(ul);				mb.appendChildNodes(div, children);			}		}		if (opts.useCombinedClassNames)		{			var mis = Spry.$$("." + mb.menuItemClass, mb.element);			for (var i = 0; i < mis.length; i++)			{				var mi = mis[i];				var classes = IEWP.getMenuItemClasses(mb, mi);				for (var j = 0; j < classes.length; j++)					mb.addClassName(mi, classes[j]);			}		}	},	onPostAddHoverClass: function(mb, evt)	{		var opts = IEWP.getOptions(mb);		if (!opts.useCombinedClassNames)			return;		var mi = evt.menuItem;		var classNames = IEWP.getMenuItemHoverClasses(mb, mi);		for (var i = 0; i < classNames.length; i++)			mb.addClassName(mi, classNames[i]);	},	onPostRemoveHoverClass: function(mb, evt)	{		var opts = IEWP.getOptions(mb);		if (!opts.useCombinedClassNames)			return;		var mi = evt.menuItem;		var classNames = IEWP.getMenuItemHoverClasses(mb, mi);		for (var i = 0; i < classNames.length; i++)			mb.removeClassName(mi, classNames[i]);	},	onPreHideSubMenuHierarchy: function(mb, evt)	{		var smh = evt.subMenus;		if (smh && smh.length)		{			var opts = IEWP.getOptions(mb);			for (var i = 0; i < smh.length; i++)			{				IEWP.hideSubMenuIFrame(mb, smh[i]);				if (opts.miContainerHoverZIndex)				{					var mic = IEWP.getMenuItemContainer(mb, smh[i]);					if (mic)						mic.style.zIndex = (opts.miContainerZIndex ? miContainerZIndex : "" ) + "";				}			}		}	},	onPostShowSubMenuHierarchy: function(mb, evt)	{		var smh = evt.subMenus;		if (smh && smh.length)		{			var opts = IEWP.getOptions(mb);			for (var i = 0; i < smh.length; i++)			{				IEWP.showSubMenuIFrame(mb, smh[i]);				if (opts.miContainerHoverZIndex)				{					var mic = IEWP.getMenuItemContainer(mb, smh[i]);					if (mic)						mic.style.zIndex = opts.miContainerHoverZIndex + "";				}			}		}	}};// We want to add our plugin to the default configuration for MenuBar2 if it is included!Spry.Widget.MenuBar2.config.plugIns.push(Spry.Widget.MenuBar2.IEWorkaroundsPlugin);})(); // EndSpryComponent
