/* extend javascript array functions */

/* Add filtering capability to Array objects that don't have that capability 
//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
*/
if (!Array.prototype.filter) {
	Array.prototype.filter = function(fun /*, thisp*/) {
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var res = new Array();
		var thisp = arguments[1];
		for (var i = 0; i < len; i++) {
			if (i in this) {
				var val = this[i]; // in case fun mutates this
				if (fun.call(thisp, val, i, this))
					res.push(val);
			}
		}

		return res;
	};
}

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

if (!Array.prototype.some) {
	Array.prototype.some = function(fun /*, thisp*/) {
		var len = this.length;
		if (typeof fun != "function")
			throw new TypeError();

		var thisp = arguments[1];
		for (var i = 0; i < len; i++) {
			if (i in this &&
          fun.call(thisp, this[i], i, this))
				return true;
		}

		return false;
	};
}

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

if (!Array.prototype.indexOf) {
	Array.prototype.indexOf = function(elt /*, from*/) {
		var len = this.length;

		var from = Number(arguments[1]) || 0;
		from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
		if (from < 0)
			from += len;

		for (; from < len; from++) {
			if (from in this &&
          this[from] === elt)
				return from;
		}
		return -1;
	};
}

/*
remove element at given index
*/
Array.prototype.removeAt = function(index) {
	this.splice(index, 1);
}

/*
return index of element in the array
*/
Array.prototype.remove = function(obj) {
	var index = this.indexOf(obj);
	if (index >= 0) {
		this.removeAt(index);
	}
}

/*
append to end of array, optionally checking for duplicates
*/
Array.prototype.append = function(obj, nodup) {
	if (!(nodup && this.contains(obj))) {
		this[this.length] = obj;
	}
}

/*
return true if element is in the array
*/
Array.prototype.contains = function(obj) {
	return (this.indexOf(obj) >= 0);
}

var isIE = (navigator.appName == "Microsoft Internet Explorer");

// NANO-CART
var rgoSelects = new Array(0);
var fSelectControlsCached = false;
var fOpen = false;

//For ingredients glossary descriptions
var ingredientDescShown = false;

//overlay close button
var gOverlayAssets = new Object();
var gOverlayEvtHandlers = new Object();
var gLastOverlayId = "";
//positioning coordinates for overlay
gOverlayAssets["initx"] = 400;
gOverlayAssets["inity"] = 348;
var gLastOverlaySource;
var gWinMgr;
var gSearch;

// Autocomplete
var timeoutVariable;
var autoCompleteObject;
// for the bug in IE where a select renders over all DIVs regardless of z-index
function cacheSelects() {
	if (navigator.appName != "Microsoft Internet Explorer") return;
	if (!fSelectControlsCached) {
		var arrayIndex = 0;
		for (var i = 0; i < document.all.length; i++) {
			if ((document.all(i).type == 'select-multiple') || (document.all(i).type == 'select-one')) {
				rgoSelects[arrayIndex] = document.all(i);
				arrayIndex++;
			}
		}
		fSelectControlsCached = true;
	}
}

// expands the nano-cart
function opendiv(odiv, oevent) {
	if (fOpen) return;
	fOpen = true;
	odiv.style.height = 'auto';
	if (!fSelectControlsCached) cacheSelects();
	hideSelects();
}

// closes the nano-cart
function closediv(odiv, oevent) {
	if (!fOpen) return;
	fOpen = false;
	odiv.style.height = '53px';
	unHideSelects();
}

// for IE, hide the selects on the page or else they render over all DIVs
function hideSelects() {
	if (navigator.appName != "Microsoft Internet Explorer") return;
	for (var arrayIndex2 = 0; arrayIndex2 < rgoSelects.length; arrayIndex2++) {
		if (rgoSelects[arrayIndex2])
			rgoSelects[arrayIndex2].style.visibility = "hidden";
	}
}

// for IE, un-hide the selects
function unHideSelects() {
	if (navigator.appName != "Microsoft Internet Explorer") return;
	var wshade = document.getElementById('expanded');
	for (var arrayIndex2 = 0; arrayIndex2 < rgoSelects.length; arrayIndex2++) {
		if (rgoSelects[arrayIndex2]) {
			if (wshade == null) {
				rgoSelects[arrayIndex2].style.visibility = "visible";
			} else if (document.all('expanded').style.display != 'block') {
				rgoSelects[arrayIndex2].style.visibility = "visible";
			}
		}
	}
}

// CATEGORY NAVIGATION

// global vars for handling the rollover functionality...
var g_szPrefix_tc_bookendLeft = 'gn_tc_bookend_left_';
var g_szPrefix_tc_bookendRight = 'gn_tc_bookend_right_';
var g_szPrefix_tc_divider = 'gn_tc_divider_';
var g_szPrefix_tc_subMenu = 'gn_tc_subMenu_';
var g_szPrefix_tc_cell = 'gn_tc_td_';
var g_szPrefix_tc_href = 'gn_tc_href_';

var g_nSubMenuWidth = 178;
var g_oDoc = (parent.frames.length > 0) ? parent.frames[0].document : parent.document;

// independent of events firing, this function simply turns off a category
function forceTurnOff(p_n, p_szFontColor, p_fIE) {

	// just in case the page hasn't loaded enough to cache the images
	if (g_szImgTCDivider == null) {
		return;
	}

	// is there a top-level category for this ordinal?
	var l_oThisHref = g_oDoc.getElementById(g_szPrefix_tc_href + p_n);
	if (l_oThisHref == null) {
		return;
	}

	// is there even an "on" state possible for this case?
	if (p_fIE) {
		if (g_oDoc.getElementById(g_szPrefix_tc_bookendLeft + p_n).src != g_szImgTCBookendLeftOn.src) {
			return;
		}
	}
	else {
		var l_szClassName = new String(l_oThisHref.className);
		if (l_szClassName.indexOf('_on') < 0) {
			return;
		}
	}

	// now we can safely turn this category "off"
	var l_oThisTD = g_oDoc.getElementById(g_szPrefix_tc_cell + p_n);
	var l_oWhiteSpace = g_oDoc.getElementById('gn_tc_whiteSpace');

	// 1. turn off white space (and then move it because it hampers mouseover on some browsers)
	l_oWhiteSpace.style.left = -1000;

	// 2. turn off subMenu (and then move it because it hampers mouseover on some browsers)
	var l_oSubnav = g_oDoc.getElementById(g_szPrefix_tc_subMenu + p_n);
	if (l_oSubnav != null) {
		l_oSubnav.style.left = -1000;
	}

	// 3. switch the category's bookends to be the *off* versions
	g_oDoc.getElementById(g_szPrefix_tc_bookendLeft + p_n).src = g_szImgTCBookendLeftOff.src;
	g_oDoc.getElementById(g_szPrefix_tc_bookendRight + p_n).src = g_szImgTCBookendRightOff.src;

	// 4. turn on the separating dash lines surrounding the category name
	switch (p_n) {
		case 0:
			// the left-most category has no separator to the left
			g_oDoc.getElementById(g_szPrefix_tc_divider + 0).src = g_szImgTCDivider.src;
			break;
		default:
			// we know this element has a separator to the left because the ordinal is high enough
			g_oDoc.getElementById(g_szPrefix_tc_divider + (p_n - 1)).src = g_szImgTCDivider.src;
			// the right-most category has no separator to the right, so test first
			var l_oSeparatorRight = g_oDoc.getElementById(g_szPrefix_tc_divider + p_n);
			if (l_oSeparatorRight != null) {
				l_oSeparatorRight.src = g_szImgTCDivider.src;
			}
	}

	if (p_fIE) {
		// 5. update the style class of the category to the *off* state's class
		l_oThisTD.style.backgroundImage = 'url(' + g_szImgTCBGOff.src + ')';

		// 6. update the link style class of the category link to be the *off* state's class
		l_oThisHref.style.color = p_szFontColor;
	}
	else {
		// 5. update the style class of the category to the *off* state's class
		l_oThisTD.className = 'gn_topCat_off';

		// 6. update the link style class of the category link to be the *off* state's class
		l_szClassName = l_szClassName.replace(/_on/, '_off');
		l_oThisHref.className = l_szClassName;
	}
}

// for turning a top category block to its *on* state
function gn_tc_over(p_n, p_oEvent) {

	// just in case the page hasn't loaded enough to cache the images
	if (g_szImgTCDivider == null) {
		return;
	}

	var l_oThisTD = g_oDoc.getElementById(g_szPrefix_tc_cell + p_n);

	// keep this event from over-firing
	if (!checkMouseEnter(l_oThisTD, p_oEvent)) {
		return;
	}

	// to be safe, turn off all other (assuming there won't be any more than 12 top-level categories)
	for (var i = 0; i <= 12; i++) {
		if (i != p_n) {
			forceTurnOff(i, '', false);
		}
	}

	// 1. turn off the separating dash lines surrounding the category name
	if (p_n == 0) {
		// the left-most category has no separator to the left
		g_oDoc.getElementById(g_szPrefix_tc_divider + 0).src = g_szImgTCBGOff.src;
	}
	else {
		// we know this element has a separator to the left because the ordinal is high enough
		g_oDoc.getElementById(g_szPrefix_tc_divider + (p_n - 1)).src = g_szImgTCBGOff.src;
		// the right-most category has no separator to the right, so test first
		var l_oSeparatorRight = g_oDoc.getElementById(g_szPrefix_tc_divider + p_n);
		if (l_oSeparatorRight != null) {
			l_oSeparatorRight.src = g_szImgTCBGOff.src;
		}
	}

	// 2. switch the category's bookends to be the *over* versions
	var l_oBookendLeft, l_oBookendRight, l_oNavEndRight, l_nNavHeight;
	l_oBookendLeft = g_oDoc.getElementById(g_szPrefix_tc_bookendLeft + p_n);
	l_oBookendLeft.src = g_szImgTCBookendLeftOn.src;
	l_oBookendRight = g_oDoc.getElementById(g_szPrefix_tc_bookendRight + p_n);
	l_oBookendRight.src = g_szImgTCBookendRightOn.src;
	l_oNavEndRight = g_oDoc.getElementById('gn_navend_right');
	l_nNavHeight = l_oNavEndRight.height;

	// 3. hover the submenu over the appropriate category, moving it over and up appropriately
	var l_rgL = gn_rgCoordinates(l_oBookendLeft);
	var l_rgR = gn_rgCoordinates(l_oBookendRight);
	var l_rgEnd = gn_rgCoordinates(l_oNavEndRight);
	var l_subMenu = g_oDoc.getElementById(g_szPrefix_tc_subMenu + p_n);

	// determine if the submenu needs to align with the left side and float right or with the right side and float left
	// NOTE: if we start using a doctype we'll have to account for using 'px'
	if (g_nSubMenuWidth > ((l_rgEnd[0] + l_oNavEndRight.width) - l_rgL[0])) {
		l_subMenu.style.left = (l_rgR[0] + l_oBookendRight.width) - g_nSubMenuWidth;
		l_subMenu.style.top = l_rgR[1] + (l_nNavHeight - 6);
		l_subMenu.style.display = 'block';
	}
	else {
		l_subMenu.style.left = l_rgL[0];
		l_subMenu.style.top = l_rgL[1] + (l_nNavHeight - 6);
		l_subMenu.style.display = 'block';
	}

	// 4. hover a spacer div to cover an appropriate amount of the submenu's top border
	// NOTE: if we start using a doctype we'll have to account for using 'px'
	var l_oWhiteSpace = g_oDoc.getElementById('gn_tc_whiteSpace');
	l_oWhiteSpace.style.left = l_rgL[0] + 1;
	l_oWhiteSpace.style.top = l_rgL[1] + (l_nNavHeight - 6);
	l_oWhiteSpace.style.width = l_rgR[0] - l_rgL[0] + l_oBookendRight.width;
	l_oWhiteSpace.style.display = 'block';

	// 5. update the style class of the category to the *over* state's class
	l_oThisTD.className = 'gn_topCat_on';

	// 6. update the link style class of the category link to be the *over* state's class
	var l_oLink = g_oDoc.getElementById(g_szPrefix_tc_href + p_n);
	var l_szClassNameOn = new String(l_oLink.className);
	l_szClassNameOn = l_szClassNameOn.replace(/_off/, '_on');
	l_oLink.className = l_szClassNameOn;
}

// for returning a top category block to its *off* state
function gn_tc_off(p_n, p_oEvent) {

	var l_oThisTD = g_oDoc.getElementById(g_szPrefix_tc_cell + p_n);

	// if this is not a valid ordinal, don't bother going further
	if (l_oThisTD == null) {
		return;
	}

	// keep this event from over-firing
	if (!checkMouseLeave(l_oThisTD, p_oEvent)) {
		return;
	}

	// if user happens to be hovering over the white space that hides a portion of the top border of the subnav, ignore
	if (!checkMouseLeave(g_oDoc.getElementById('gn_tc_whiteSpace'), p_oEvent)) {
		return;
	}

	forceTurnOff(p_n, '', false);
}


// <IE-SPECIFIC CODE> ############################################################################

// for IE, hide the selects on the page or else they render over all DIVs
// this function is specifically for the global nav submenu - the first cut at conditionally hiding the selects
// to do this right would require some re-structuring of our elements (this only works because the brand dropdown is currently at the right of the page)
function maybeHideSelectsForGN(p_nLayerEnd) {
	if (navigator.appName != "Microsoft Internet Explorer") return;

	var l_rgSelect;
	for (var arrayIndex2 = 0; arrayIndex2 < rgoSelects.length; arrayIndex2++) {
		if (rgoSelects[arrayIndex2]) {
			l_rgSelect = gn_rgCoordinates(rgoSelects[arrayIndex2]);
			if (p_nLayerEnd > l_rgSelect[0]) {
				rgoSelects[arrayIndex2].style.visibility = "hidden";
			}
		}
	}
}

// for turning a top category block to its *on* state
function gn_tc_overIE(p_n, p_oEvent) {

	// just in case the page hasn't loaded enough to cache the images
	if (g_szImgTCDivider == null) {
		return;
	}

	// 1. update the style class of the category to the *over* state's class
	g_oDoc.getElementById(g_szPrefix_tc_cell + p_n).style.backgroundImage = 'url(' + g_szImgTCBGOver.src + ')';

	// 2. update the link style class of the category link to be the *over* state's class
	g_oDoc.getElementById(g_szPrefix_tc_href + p_n).style.color = g_szTCFontColorOn;

	// 3. switch the category's bookends to be the *over* versions
	var l_oBookendLeft, l_oBookendRight, l_oNavEndRight, l_nNavHeight;
	l_oBookendLeft = g_oDoc.getElementById(g_szPrefix_tc_bookendLeft + p_n);
	l_oBookendLeft.src = g_szImgTCBookendLeftOn.src;
	l_oBookendRight = g_oDoc.getElementById(g_szPrefix_tc_bookendRight + p_n);
	l_oBookendRight.src = g_szImgTCBookendRightOn.src;
	l_oNavEndRight = g_oDoc.getElementById('gn_navend_right');
	l_nNavHeight = l_oNavEndRight.height;

	// 4. hover the submenu over the appropriate category, moving it over and up appropriately
	var l_rgL = gn_rgCoordinates(l_oBookendLeft);
	var l_rgR = gn_rgCoordinates(l_oBookendRight);
	var l_rgEnd = gn_rgCoordinates(l_oNavEndRight);
	var l_subMenu = g_oDoc.getElementById(g_szPrefix_tc_subMenu + p_n);

	// determine if the submenu needs to align with the left side and float right or with the right side and float left
	var l_nSubmenuXCoordinate, l_nSubmenuYCoordinate;
	if (g_nSubMenuWidth > ((l_rgEnd[0] + l_oNavEndRight.width) - l_rgL[0])) {
		l_nSubmenuXCoordinate = (l_rgR[0] + l_oBookendRight.width) - g_nSubMenuWidth;
		l_nSubmenuYCoordinate = l_rgR[1] + (l_nNavHeight - 6);
	}
	else {
		l_nSubmenuXCoordinate = l_rgL[0];
		l_nSubmenuYCoordinate = l_rgL[1] + (l_nNavHeight - 6);
	}
	// NOTE: if we start using a doctype we'll have to account for using 'px'
	l_subMenu.style.left = l_nSubmenuXCoordinate;
	l_subMenu.style.top = l_nSubmenuYCoordinate;
	// hack for IE bug where selects appear on top of all DIVs, regardless of z-index
	if (!fSelectControlsCached) cacheSelects();
	maybeHideSelectsForGN((l_nSubmenuXCoordinate + g_nSubMenuWidth));

	// 5. hover a spacer div to cover an appropriate amount of the submenu's top border
	// NOTE: if we start using a doctype we'll have to account for using 'px'
	var l_oWhiteSpace = g_oDoc.getElementById('gn_tc_whiteSpace');
	l_oWhiteSpace.style.left = l_rgL[0] + 1;
	l_oWhiteSpace.style.top = l_rgL[1] + (l_nNavHeight - 6);
	l_oWhiteSpace.style.width = l_rgR[0] - l_rgL[0] + l_oBookendRight.width;

	// 6. turn off the separating dash lines surrounding the category name
	if (p_n == 0) {
		// the left-most category has no separator to the left
		g_oDoc.getElementById(g_szPrefix_tc_divider + 0).src = g_szImgTCBGOff.src;
	}
	else {
		// we know this element has a separator to the left because the ordinal is high enough
		g_oDoc.getElementById(g_szPrefix_tc_divider + (p_n - 1)).src = g_szImgTCBGOff.src;
		// the right-most category has no separator to the right, so test first
		var l_oSeparatorRight = g_oDoc.getElementById(g_szPrefix_tc_divider + p_n);
		if (l_oSeparatorRight != null) {
			l_oSeparatorRight.src = g_szImgTCBGOff.src;
		}
	}

	// to be safe, turn off all others (assuming there won't be any more than 12 top-level categories)
	// TODO -- create a cached way to track the correct "on" color to revert back to. This is marginally okay because this is only a failsafe anyway
	for (var i = 0; i <= 12; i++) {
		if (i != p_n) {
			forceTurnOff(i, g_szTCFontColorOff, true);
		}
	}
}

// for returning a top category block to its *off* state
function gn_tc_offIE(p_n, p_szFontColor, p_oEvent) {

	var l_oThisTD = g_oDoc.getElementById(g_szPrefix_tc_cell + p_n);

	// if this is not a valid ordinal, don't bother going further
	if (l_oThisTD == null) {
		return;
	}

	// if user happens to be hovering over the white space that hides a portion of the top border of the subnav, ignore
	if (!checkMouseLeave(g_oDoc.getElementById('gn_tc_whiteSpace'), p_oEvent)) {
		return;
	}

	// hack for IE bug where selects appear on top of all DIVs, regardless of z-index
	unHideSelects();

	forceTurnOff(p_n, p_szFontColor, true);
}
// </IE-SPECIFIC CODE> ############################################################################


// ############## MISC HELPER FUNCTIONS FOR ROLLOVER FUNCTIONALITY ##############

// returns an array of the coordinates of an object
// - first element is the number of pixels from the *left* of the page
// - second element is the number of pixels from the *top* of the page
function gn_rgCoordinates(p_o) {
	if (p_o.offsetParent) {
		var l_X, l_Y;
		for (l_X = 0, l_Y = 0; p_o.offsetParent; p_o = p_o.offsetParent) {
			l_X += p_o.offsetLeft;
			l_Y += p_o.offsetTop;
		}
		return [l_X, l_Y];
	}
	else {
		return [p_o.x, p_o.y];
	}
}

// determine how this browser handles event bubbling
function containsDOM(container, containee) {
	var isParent = false;
	do {
		if ((isParent = container == containee))
			break;
		containee = containee.parentNode;
	}
	while (containee != null);
	return isParent;
}

// determine if the event is already active
function checkMouseEnter(element, evt) {
	if (element.contains && evt.fromElement) {
		return !element.contains(evt.fromElement);
	}
	else if (evt.relatedTarget) {
		return !containsDOM(element, evt.relatedTarget);
	}
}

// determine if the event is already active
function checkMouseLeave(element, evt) {
	if (element.contains && evt.toElement) {
		return !element.contains(evt.toElement);
	}
	else if (evt.relatedTarget) {
		return !containsDOM(element, evt.relatedTarget);
	}
}

//===============Function IsSearchBoxEmpty()==================================
// Purpose      : To block form submit, if search box value is empty. 
//                It will get fired during onsubmit of FORM
// Arguments    : Control Id [Auto Complete Searchbox]
// Date         : July 2007

function IsSearchBoxEmpty(p_oSearchBox) {
	try {

		var l_oSearchBox, l_szSearchValue;
		if (typeof (p_oSearchBox) == "object")
			l_oSearchBox = p_oSearchBox;
		else
			l_oSearchBox = document.getElementById(p_oSearchBox);

		var isDefaultTerm = SearchInputHasDefaultTerm(l_oSearchBox);
		if (isDefaultTerm) {
			SearchInputAlert(l_oSearchBox);
			return false;
		}

		//This string pattern will Trim the whitespaces    
		l_szSearchValue = l_oSearchBox.value.replace(/^\s+|\s+$/g, "");
		if (l_szSearchValue == "" || l_szSearchValue == null) {
			SearchInputAlert(l_oSearchBox);
			return false; //will block form submit
		}
		else
			return true;   // allow form submit
	}
	catch (e) { return true; }

	function SearchInputHasDefaultTerm(el) {
		if (gSearch) {
			var fieldDefinition = gSearch.GetFieldDefinition(el.id);
			if (fieldDefinition) {
				if (el.value.toLowerCase() == fieldDefinition.inputFieldDefaultText.toLowerCase()) {
					return true;
				}
			}
		}
		return false;
	}
	function SearchInputAlert(el) {
		alert("Search value is empty!");
		el.focus();
	}
}
//===============End of Function==============================================

//===============Function AddFormSubmitEvent()==================================
// Purpose      : To add onsubmit event to FORM 
//                This function will be called after rendering AutoComplete search box
// Arguments    : Control Id [Auto Complete Searchbox]
// Date         : July 2007

function AddFormSubmitEvent(p_oSearchBox) {
	try {
		var l_oSearchBox, l_oForm;
		if (typeof (p_oSearchBox) == "object")
			l_oSearchBox = p_oSearchBox;
		else
			l_oSearchBox = document.getElementById(p_oSearchBox);
		l_oForm = l_oSearchBox.form;
		l_oForm.onsubmit = function() { return IsSearchBoxEmpty(p_oSearchBox); };
	}
	catch (e) { }
}
//===============End of Function==============================================

//===============Function EncodeQueryString()==================================
// Purpose      : To Encode special characters like &,@,=,_ which are passed in query string
//                After encode it will be passed to AJAX Service engine
// Arguments    : String Value [Auto Complete SearchTerm]
// Date         : July 2007

function EncodeQueryString(p_szValue) {
	try {
		var l_szEnValue = escape(p_szValue);
		l_szEnValue = l_szEnValue.replace(/\?/g, "%3F");
		l_szEnValue = l_szEnValue.replace(/=/g, "%3D");
		l_szEnValue = l_szEnValue.replace(/&/g, "%26");
		l_szEnValue = l_szEnValue.replace(/@/g, "%40");
		// TODO: Handle other special characters if required
		return l_szEnValue;
	}
	catch (e) { }
}
//===============End of Function==============================================

//===============Function EncodeHTML()==================================
// Purpose      : To Encode HTML special characters & -> &amp; -> &
//                After encode it will be loaded into Autocomplete search box
// Arguments    : String Value [Auto Complete List Item]
// Date         : July 2007

function EncodeHTML(p_szValue) {
	try {
		var l_szEnValue = p_szValue;
		l_szEnValue = l_szEnValue.replace(/&amp;/g, "&");
		l_szEnValue = l_szEnValue.replace(/&lt;/g, "<");
		l_szEnValue = l_szEnValue.replace(/&gt;/g, ">");
		// TODO: Handle other special characters if required
		return l_szEnValue;
	}
	catch (e) { }
}
//===============End of Function==============================================



'' ////////////////////////////////////////////////////////////////////
'' //
'' // AJAX
'' //
'' // (c)2003 drugstore.com
'' //
'' // These scripts will be used for Asynchronous JavaScript Operations with XML   
'' // Created:                  04/2007
'' // Author:                   c-mnatarajan
'' //
'' ////////////////////////////////////////////////////////////////////


//===============Global Variables=============================================
var g_nCurrentPosition = 0; //Please do not remove... it is here for auto complete
//===============End of Global Variables======================================


//===============Function ClearControlValues()==================================
// Purpose      : To clear the table[result] rows in order to repaint new values
// Arguments    : NA
// Date         : May 28 2007

function ClearControlValues(p_oResultTable) {
	try {
		if (p_oResultTable) {
			var l_oRows = p_oResultTable.getElementsByTagName("tr");
			var l_nLength = l_oRows.length;
			var l_nIndex;
			for (l_nIndex = 0; l_nIndex < l_nLength; l_nIndex++) {
				p_oResultTable.deleteRow(0);
			}
		}
	}
	catch (e) { }
}
//===============End of Function==============================================



//===============Function RenderDIV()=========================
// Purpose      : To render the contents for DIV control without postback. 
//                Detect the existing TABLE object and add rows and columns during Async operation
// Arguments    : XML Response Object
// Date         : May 28 2007

function RenderDIV(p_szRes, p_oResultPlaceHolder, p_oResultTable, p_oForm, p_oAutoCommit) {
	try {
		if (p_szRes != null && p_szRes != "") {
			ClearControlValues(p_oResultTable);
			var l_rgszRes = p_szRes.split(",");
			// Existing static TABLE object in the client page [id="result"]   
			var l_nIndex;
			for (l_nIndex = 0; l_nIndex < l_rgszRes.length; l_nIndex++) {
				//Create row item for each line in response stream along with events                        
				var l_oRow = document.createElement("tr");
				l_oRow.className = "acitem";
				l_oRow.onmouseover = function() { ChangeRowColor(this, true); }
				l_oRow.onmouseout = function() { ChangeRowColor(this, false); }
				l_oRow.onclick = function() { PopulateSelectedValue(this, p_oResultPlaceHolder, p_oForm, p_oAutoCommit); }

				var l_oCell = document.createElement("td");
				l_oCell.setAttribute("align", "left");
				l_oCell.className = "accell";
				l_oCell.innerHTML = l_rgszRes[l_nIndex];
				l_oRow.appendChild(l_oCell);
				p_oResultTable.appendChild(l_oRow);
			}
		}
	}
	catch (e) { }
}

//===============End of Function==============================================

//===============Keyboard Event Handling For Extended Navigation==============//

//===============Function MoveNext()=========================
// Purpose      : To Move next record of Result Placeholder
// Arguments    : NA
// Date         : May 29 2007

function MoveNext(p_oResultTable, p_nMaxRows, p_oAutoCommit) {
	try {
		var l_oResultTable, l_nMaxRows;
		l_oResultTable = p_oResultTable;
		l_nMaxRows = p_nMaxRows;
		if (g_nCurrentPosition < l_nMaxRows) {
			if (g_nCurrentPosition == 0) {
				l_oResultTable.rows[g_nCurrentPosition].className = "acselected";
				SetSelectedValue(l_oResultTable.rows[g_nCurrentPosition].cells[0].innerHTML, p_oAutoCommit);
				g_nCurrentPosition++;
			}
			else {
				l_oResultTable.rows[g_nCurrentPosition - 1].className = "acitem";
				l_oResultTable.rows[g_nCurrentPosition].className = "acselected";
				SetSelectedValue(l_oResultTable.rows[g_nCurrentPosition].cells[0].innerHTML, p_oAutoCommit);
				g_nCurrentPosition++;
			}
		}
		else //For cyclic navigation
		{
			g_nCurrentPosition = 0;
			l_oResultTable.rows[l_nMaxRows - 1].className = "acitem";
			l_oResultTable.rows[g_nCurrentPosition].className = "acselected";
			SetSelectedValue(l_oResultTable.rows[g_nCurrentPosition].cells[0].innerHTML, p_oAutoCommit);
			g_nCurrentPosition++;
		}
	}
	catch (e) { }
}
//===============End of Function==============================================

//===============Function MovePrevious()=========================
// Purpose      : To Move previous record of Result Placeholder
// Arguments    : NA
// Date         : May 29 2007

function MovePrevious(p_oResultTable, p_nMaxRows, p_oAutoCommit) {
	try {
		var l_oResultTable, l_nMaxRows;
		l_nMaxRows = p_nMaxRows;
		l_oResultTable = p_oResultTable;
		if (g_nCurrentPosition > 1) {
			l_oResultTable.rows[g_nCurrentPosition - 1].className = "acitem";
			g_nCurrentPosition--;
			l_oResultTable.rows[g_nCurrentPosition - 1].className = "acselected";
			SetSelectedValue(l_oResultTable.rows[g_nCurrentPosition - 1].cells[0].innerHTML, p_oAutoCommit);
		}
		else if (g_nCurrentPosition == 1) //For cyclic navigation
		{
			l_oResultTable.rows[g_nCurrentPosition - 1].className = "acitem";
			l_oResultTable.rows[l_nMaxRows - 1].className = "acselected";
			g_nCurrentPosition = l_nMaxRows;
			SetSelectedValue(l_oResultTable.rows[g_nCurrentPosition - 1].cells[0].innerHTML, p_oAutoCommit);
		}
		else //For Zero index
		{
			l_oResultTable.rows[l_nMaxRows - 1].className = "acselected";
			g_nCurrentPosition = l_nMaxRows;
			SetSelectedValue(l_oResultTable.rows[g_nCurrentPosition - 1].cells[0].innerHTML, p_oAutoCommit);
		}
	}
	catch (e) { }
}

//===============End of Function==============================================


//===============Function changeRowColor()==================================
// Purpose      : To highlight selected value from Result Placeholder
// Arguments    : row, highlight[true, false]
// Date         : May 25 2007

function ChangeRowColor(p_oRow, p_fHighlight) {
	try {
		if (p_fHighlight) {
			p_oRow.className = "acselected";
		}
		else {
			p_oRow.className = "acitem";
		}
	}
	catch (e) { }
}

//===============End of Function==============================================

//===============Function SetSelectedValue()==================================
// Purpose      : To get the selected value from DIV & display in the textbox
// Arguments    : Selected Value
// Date         : May 25 2007

function SetSelectedValue(p_szValue, p_oAutoCommit) {
	try {
		// adjust the max length property so that the search box can hold the entire text selected by the user 
		// This fix is for IE as it restricts the length of text assigned to specified maxLength.
		if (p_szValue.length > p_oAutoCommit.maxLength)
			p_oAutoCommit.maxLength = p_szValue.length;
		p_oAutoCommit.value = EncodeHTML(p_szValue);
	}
	catch (e) { }
}
//===============End of Function==============================================

//===============Function PopulateSelectedValue()==================================
// Purpose      : To get the selected value from DIV & display in the textbox
// Arguments    : Selected Row as Object
// Date         : May 25 2007

function PopulateSelectedValue(p_oSource, p_oResultPlaceHolder, p_oForm, p_oAutoCommit) {
	try {
		var l_oResultPlaceHolder, l_oAutoCommit;
		l_oAutoCommit = p_oAutoCommit;
		SetSelectedValue(p_oSource.cells[0].innerHTML, l_oAutoCommit);
		SetElementProperty("visibility", "hidden", p_oResultPlaceHolder);
		p_oForm.submit();
	}
	catch (e) { }
}
//===============End of Function==============================================


//===============End of Keyboard Event Handling For Extended Navigation=======


//===============Function SetElementProperty()==================================
// Purpose      : To set the style properties for the source element
// Arguments    : Property, Value and Object
// Date         : jun 5 2007

function SetElementProperty(p_oProperty, p_szValue, p_oSource) {
	try {
		var l_oSource = p_oSource;
		if ((l_oSource != null) && (l_oSource.style != null)) {
			l_oSource = l_oSource.style;
			l_oSource[p_oProperty] = p_szValue;
		}
	}
	catch (e) { }
}
//===============End of Function==============================================

//===============Function PositionInfo()==================================
// Purpose      : To get the position info [left,top,height] of Autocommitcontrol
// Arguments    : AutoCommitControl Object
// Date         : jun 5 2007

function PositionInfo(p_oSource) {
	this.sourceElement = p_oSource;
}

PositionInfo.prototype.getElementWidth = function() {
	try {
		var l_nWidth = 0;
		if (this.sourceElement != null) {
			l_nWidth = this.sourceElement.offsetWidth;
		}
		return parseInt(l_nWidth);
	}
	catch (e) { }
}

PositionInfo.prototype.getElementHeight = function() {
	try {
		var l_nHeight = 0;
		if (this.sourceElement != null) {
			l_nHeight = this.sourceElement.offsetHeight;
		}
		return parseInt(l_nHeight);
	}
	catch (e) { }
}

PositionInfo.prototype.getElementLeft = function() {
	try {
		var l_nLeft = 0;
		var l_oTemp = this.sourceElement;
		while (l_oTemp != null) {
			l_nLeft += l_oTemp.offsetLeft;
			l_oTemp = l_oTemp.offsetParent;
		}
		return parseInt(l_nLeft);
	}
	catch (e) { }
}

PositionInfo.prototype.getElementTop = function() {
	try {
		var l_nTop = 0;
		var l_oTemp = this.sourceElement;
		while (l_oTemp != null) {
			l_nTop += l_oTemp.offsetTop;
			l_oTemp = l_oTemp.offsetParent;
		}
		return parseInt(l_nTop);
	}
	catch (e) { }
}

//===============Function PositionResultPlaceHolder()==================================
// Purpose      : To position the ResultPlaceHolder with respect to AutoCommitControl
// Arguments    : AutoCommitControl Object, ResultPlaceholder
// Date         : jun 5 2007

function PositionPlaceHolder(p_oSource, p_oDest) {
	try {
		var l_oPos = new PositionInfo(p_oSource);
		SetElementProperty('top', (l_oPos.getElementTop() + l_oPos.getElementHeight()) + 'px', p_oDest);
		SetElementProperty('left', l_oPos.getElementLeft() + 'px', p_oDest);
	}
	catch (e) { }
}
//===============End of Function=========================================================


// cross browser event fetch
function GetEvent(e) {
	if (!e)
		var e = window.event;
	return e.target || e.srcElement;
}

/*Javascript dictionary object implementation - Start*/

function KeyValuePair(p_oKey, p_oValue) {
	this.Key = p_oKey;
	this.Value = p_oValue;
}

function KeyValueCollection() {
	this.arList = []; //empty array
	this.Items = this.arList;
}

KeyValueCollection.prototype.Count = function() {
	return this.arList.length;
}

KeyValueCollection.prototype.Add = function(p_szKey, p_szValue) {
	var objKeyValuePair = new KeyValuePair(p_szKey, p_szValue);
	this.arList.push(objKeyValuePair);
}

KeyValueCollection.prototype.Remove = function(p_strKey) {
	for (i = 0; i < arList.length; i++) {
		if (this.arList[i].Key.toLowerCase() == p_strKey.toLowerCase()) {
			switch (i) {
				case 0:
					this.arList.shift();
					break;
				case arList.length - 1:
					this.arList.pop();
					break;
				default:
					var arHead = this.arList.slice(0, i);
					var arTail = this.arList.slice(i + 1);
					this.arList = arHead.concat(arTail);
					break;
			}
		}
	}
}

KeyValueCollection.prototype.Item = function(p_szKey) {
	var l_oValue = "";
	for (i = 0; i < this.arList.length; i++) {
		if (this.arList[i].Key.toLowerCase() == p_szKey.toLowerCase()) {
			l_oValue = this.arList[i].Value;
		}
	}
	return l_oValue;
}

KeyValueCollection.prototype.Exists = function(p_szKey) {
	var l_fItemExists = false
	for (i = 0; i < this.arList.length; i++) {
		if (this.arList[i].Key.toLowerCase() == p_szKey.toLowerCase()) {
			l_fItemExists = true;
			break;
		}
	}
	return l_fItemExists;
}

/*Javascript Dictionary Object Implementation - End*/

///////////////////////////////////

// XML (base object) has a property to identify IE and other objects to load/transform
var XML = new Object();
XML.IsIE = (document.implementation.createDocument) ? false : true;
XML.XMLLoader = new XMLLoader(this.XML);
XML.XMLTransformer = new XMLTransformer(this.XML);

function XMLLoader(base) { this.XMLBase = base; }
XMLLoader.prototype.load = function(xmlFile, async) {
	var xmlDocument;
	if (this.XMLBase.IsIE) {
		xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
	} else {
		xmlDocument = document.implementation.createDocument('', '', null);
	}
	xmlDocument.async = async;
	xmlDocument.load(xmlFile);
	return xmlDocument;
}

function XMLTransformer(base) { this.XMLBase = base; }
XMLTransformer.prototype.transform = function(xmlFile, xslFile) {
	var html;
	var XMLDoc = XML.XMLLoader.load(xmlFile, false);
	var XSLDoc = XML.XMLLoader.load(xslFile, false);
	if (this.XMLBase.IsIE) {
		html = XMLDoc.transformNode(XSLDoc);
	} else {
		var XSLProcessor = new XSLTProcessor();
		var XSLStylesheet = XSLDoc;
		XSLProcessor.importStylesheet(XSLStylesheet);
		html = XSLProcessor.transformToFragment(XMLDoc, document);
	}
	return html;
}



//===============Function HandleAutoCommit()==================================
// Purpose      : To fetch the search terms based on user's key stroke
// Arguments    : p_szResPanelId - Results panel id
//				  p_szResTableId - Results table id
//				  p_szServiceURL - web service url
//				  p_nMinChars    - min number of chars to wait before start scanning for matches
// Date         : Jul 03 2007
function HandleAutoCommit(p_szResPanelId, p_szResTableId, p_szServiceURL, p_nMinChars, p_nResPaneWidth, p_nKeyEntryDelayMilliSecs) {
	try {
		var e, l_oResultTable, l_oResultPlaceHolder, l_oForm, l_oAutoCommit, l_oRows;
		var l_nKeyCode, l_nMaxRows;

		l_oResultPlaceHolder = document.getElementById(p_szResPanelId);
		l_oResultTable = document.getElementById(p_szResTableId).getElementsByTagName("tbody")[0]
		//Browser compatibility
		e = window.event || arguments.callee.caller.arguments[0];
		l_oAutoCommit = e.srcElement || e.target;
		autoCompleteObject = l_oAutoCommit;
		if (l_oAutoCommit && l_oResultPlaceHolder && l_oResultTable) {
			l_oRows = l_oResultTable.getElementsByTagName("tr");
			l_oForm = l_oAutoCommit.form;
			l_nKeyCode = e.keyCode;
			l_nMaxRows = l_oRows.length;

			l_fn = function() {
				SetElementProperty("visibility", "hidden", l_oResultPlaceHolder);
				DisableFormElements(l_oResultPlaceHolder.id, 'select', false);
			}
			l_oAutoCommit.onblur = function() { setTimeout(l_fn, 1000); }

			if (!l_oAutoCommit.value) {
				ClearControlValues(l_oResultTable);
				SetElementProperty("visibility", "hidden", l_oResultPlaceHolder);
				DisableFormElements(l_oResultPlaceHolder.id, 'select', false);
			}

			if (e.type == "keyup") {
				if (l_nKeyCode == 40) //Arrow Key DOWN
				{
					MoveNext(l_oResultTable, l_nMaxRows, l_oAutoCommit);
				}
				else if (l_nKeyCode == 38) //Arrow Key UP
				{
					MovePrevious(l_oResultTable, l_nMaxRows, l_oAutoCommit);
				}
				else if (l_nKeyCode == 13) //Return Key
				{
					if (g_nCurrentPosition > 0)// Key will not handle the normal search
					{
						SetSelectedValue(l_oResultTable.rows[g_nCurrentPosition - 1].cells[0].innerHTML, l_oAutoCommit);
						SetElementProperty("visibility", "hidden", l_oResultPlaceHolder);
						DisableFormElements(l_oResultPlaceHolder.id, 'select', false);
						return false;
					}
				}
				else if (l_nKeyCode == 27) //ESC Key
				{
					SetElementProperty("visibility", "hidden", l_oResultPlaceHolder);
					DisableFormElements(l_oResultPlaceHolder.id, 'select', false);
				}
				// contact the web service when the number of chars is >= required number of chars
				// filter the "not eligible" chars from search term and then check for length
				else if (l_oAutoCommit.value && FilterTextIncluding(l_oAutoCommit.value, "abcdefghijklmnopqrstuvwxyz0123456789- ()&/#.").length >= p_nMinChars) {
					// Set a delay so that the auto complete search page will not be hit on every keypress, but only after the user has entered a set of characters and after a short delay.
					timeoutVariable = setTimeout(function() { GetAutoCompleteResults(l_oResultPlaceHolder, p_szServiceURL, p_nResPaneWidth, l_oResultTable, l_oForm, l_nMaxRows) }, p_nKeyEntryDelayMilliSecs);
				}
				// do not show results pane, if number of chars is less than required
				else if (l_oAutoCommit.value.length < p_nMinChars) {
					SetElementProperty("visibility", "hidden", l_oResultPlaceHolder);
					DisableFormElements(l_oResultPlaceHolder.id, 'select', false);
					if (l_nMaxRows > 0) {
						g_nCurrentPosition = 0;
					}
				}
			}
		}
	}
	catch (ex) { }
}

function GetAutoCompleteResults(p_oResultPlaceHolder, p_szServiceURL, p_nResPaneWidth, p_oResultTable, p_oForm, p_nMaxRows) {
	var l_szEncodedValue;
	//filter the "not eligible" chars from search term before sending it to AJAX service
	l_szEncodedValue = EncodeQueryString(FilterTextIncluding(autoCompleteObject.value, "abcdefghijklmnopqrstuvwxyz0123456789- ()&/#."));
	var l_oAJAXReq = new dsLib.AJAX.Request(p_szServiceURL + l_szEncodedValue, null, null, "GET", null, "text/html", false);
	var l_szRes = l_oAJAXReq.responseText;
	if (l_szRes != null && l_szRes != "") {
		//Position Result PlaceHolder with respect to Search textbox56
		PositionPlaceHolder(autoCompleteObject, p_oResultPlaceHolder);
		SetElementProperty("visibility", "visible", p_oResultPlaceHolder);
		SetElementProperty("width", p_nResPaneWidth + "px", p_oResultPlaceHolder);
		RenderDIV(l_oAJAXReq.responseText, p_oResultPlaceHolder, p_oResultTable, p_oForm, autoCompleteObject);
		DisableFormElements(p_oResultPlaceHolder.id, 'select', true);
	}
	else {
		ClearControlValues(p_oResultTable);
		SetElementProperty("visibility", "hidden", p_oResultPlaceHolder);
		DisableFormElements(p_oResultPlaceHolder.id, 'select', false);
	}
	if (p_nMaxRows > 0) {
		g_nCurrentPosition = 0;
	}
}
//===============End of Function HandleAutoCommit()==================================

function showHideRVA(p_szContentId, p_fShow, p_szExpandImgId, p_szCollapseImgId) {
	var objContent = document.getElementById(p_szContentId);
	var imgExpand = document.getElementById(p_szExpandImgId);
	var imgCollapse = document.getElementById(p_szCollapseImgId);
	if (objContent) {
		objContent.className = (p_fShow) ? "contentvisible" : "contenthidden";
	}
	if (imgExpand) {
		imgExpand.src = (p_fShow) ? "/img/icons/expand_inactive.gif" : "/img/icons/expand_active.gif";
	}
	if (imgCollapse) {
		imgCollapse.src = (p_fShow) ? "/img/icons/collapse_active.gif" : "/img/icons/collapse_inactive.gif";
	}
}


//////// PDetails JS Functions ////////////////

// To show/hide tabs
function ShowPDetailsTabContent(p_szActiveDivId, p_szAllDivIds, p_szActiveTabImgURL, p_szHiddenTabImgURL) {
	try {
		// Hide ingredient description div if it's being displayed.
		if (ingredientDescShown) {
			showIngredientDescription(null, null, null, false, null);
		}

		var l_rgszDivIds = p_szAllDivIds.split(',');
		for (i = 0; i < l_rgszDivIds.length; i++) {
			var divTemp;
			divTemp = document.getElementById(l_rgszDivIds[i]);
			if (divTemp) {
				if (p_szActiveDivId != l_rgszDivIds[i]) {
					divTemp.style.visibility = 'hidden';
					divTemp.style.display = 'none';
					// Will extract only the key value
					MakeTabActive(l_rgszDivIds[i].substring(3, l_rgszDivIds[i].length), p_szHiddenTabImgURL, false);
				}
				else {
					divTemp.style.visibility = 'visible';
					divTemp.style.display = 'block';
					MakeTabActive(l_rgszDivIds[i].substring(3, l_rgszDivIds[i].length), p_szActiveTabImgURL, true);
				}
			}
		}
	}
	catch (e) { }
}
//To include IMG for tab and apply styles b/w tabs
function MakeTabActive(p_szKey, p_szTabImgURL, p_fVisible) {
	try {
		var l_oTabButton, l_oImgButton, l_oTab;
		l_oTabButton = document.getElementById('btn' + p_szKey);
		l_oImgButton = document.getElementById('img' + p_szKey);
		l_oTab = document.getElementById('td' + p_szKey);
		if (p_fVisible) {
			l_oTabButton.className = 'TblPDetailsSelectedBtn';
			l_oImgButton.src = p_szTabImgURL;
			l_oImgButton.alt = p_szKey;
			l_oTab.className = 'selectedTab';
		}
		else {
			l_oTabButton.className = 'TblPDetailsBtn';
			l_oImgButton.src = p_szTabImgURL;
			l_oImgButton.alt = p_szKey;
			l_oTab.className = 'hiddenTab';
		}
	}
	catch (e) { }
}

// To show/hide tabs
function ShowTabContent(p_szActiveDivId, p_szAllDivIds, p_szActiveTabImgURL, p_szHiddenTabImgURL, p_szStyleNameSuffix) {
	try {
		// Hide ingredient description div if it's being displayed.
		if (ingredientDescShown) {
			showIngredientDescription(null, null, null, false, null);
		}

		var l_rgszDivIds = p_szAllDivIds.split(',');
		for (i = 0; i < l_rgszDivIds.length; i++) {
			var divTemp;
			divTemp = document.getElementById(l_rgszDivIds[i]);
			if (divTemp) {
				if (p_szActiveDivId != l_rgszDivIds[i]) {
					divTemp.style.visibility = 'hidden';
					divTemp.style.display = 'none';
					// Will extract only the key value
					ToggleTab(l_rgszDivIds[i].substring(3, l_rgszDivIds[i].length), p_szHiddenTabImgURL, false, p_szStyleNameSuffix);
				}
				else {
					divTemp.style.visibility = 'visible';
					divTemp.style.display = 'block';
					ToggleTab(l_rgszDivIds[i].substring(3, l_rgszDivIds[i].length), p_szActiveTabImgURL, true, p_szStyleNameSuffix);
				}
			}
		}
	}
	catch (e) { }
}
//To include IMG for tab and apply styles b/w tabs
function ToggleTab(p_szKey, p_szTabImgURL, p_fVisible, p_szStyleNameSuffix) {
	try {
		var l_oTabButton, l_oImgButton, l_oTab, l_szKey;
		l_szKey = p_szKey
		if (p_szKey.substring(p_szKey.length - p_szStyleNameSuffix.length) == p_szStyleNameSuffix)
			l_szKey = p_szKey.substring(0, p_szKey.length - p_szStyleNameSuffix.length)
		l_oTabButton = document.getElementById('btn' + l_szKey + p_szStyleNameSuffix);
		l_oImgButton = document.getElementById('img' + l_szKey + p_szStyleNameSuffix);
		l_oTab = document.getElementById('td' + l_szKey + p_szStyleNameSuffix);
		if (p_fVisible) {
			l_oTabButton.className = 'tdPDetailsSelectedBtn' + p_szStyleNameSuffix;
			l_oImgButton.src = p_szTabImgURL;
			l_oImgButton.alt = l_szKey;
			l_oTab.className = 'selectedTab' + p_szStyleNameSuffix;
		}
		else {
			l_oTabButton.className = 'tdPDetailsBtn' + p_szStyleNameSuffix;
			l_oImgButton.src = p_szTabImgURL;
			l_oImgButton.alt = l_szKey;
			l_oTab.className = 'hiddenTab' + p_szStyleNameSuffix;
		}
	}
	catch (e) { }
}
//////// End of PDetails JS Functions /////////

// PopUp Menu for pick color option

//To make all SELECT elements as hidden which is inside the DIV area - in order to avoid select overlap DIV pbm with IE
function DisableFormElements(p_oSource, p_szTagName, p_fHidden) {
	try {
		var l_oCollection;
		//Get the collection for select tag
		l_oCollection = document.getElementsByTagName(p_szTagName);
		var l_oSrc = new PositionInfo(document.getElementById(p_oSource));

		if (l_oSrc) {
			for (var i = 0; i <= l_oCollection.length - 1; i++) {
				if (l_oCollection[i]) {
					var l_oDes = new PositionInfo(l_oCollection[i]);
					//To check whether the SELECT element is residing inside DIV area
					if ((l_oDes.getElementLeft() + l_oDes.getElementWidth()) >= l_oSrc.getElementLeft() && l_oDes.getElementLeft() <= (l_oSrc.getElementLeft() + l_oSrc.getElementWidth()) && (l_oDes.getElementTop() + l_oDes.getElementHeight()) >= l_oSrc.getElementTop() && l_oDes.getElementTop() <= (l_oSrc.getElementTop() + l_oSrc.getElementHeight())) {
						SetElementProperty('visibility', (p_fHidden == true ? 'hidden' : 'visible'), l_oCollection[i]);
					}
				}
			}
		}
	}
	catch (e) { }
}

function handleCloseClick(p_oSource) {
	try {
		DisableFormElements(p_oSource, 'select', false);
		SetElementProperty('visibility', 'hidden', document.getElementById(p_oSource));
	}
	catch (e) { }
}

function handlePickColorClick(oDiv, url, evnt) {
	try {
		pickColor(oDiv, url, evnt);
		DisableFormElements(oDiv, 'select', true);
	}
	catch (e) { }
}

// PopUp Menu for pick color option
function pickColor(myDiv, url, evt) {
	try {
		var e = (window.event) ? window.event : evt;
		var myWidth = 0, myHeight = 0;
		if (typeof (window.innerWidth) == 'number') {
			//Non-IE
			myWidth = window.innerWidth;
			myHeight = window.innerHeight;
		} else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
			//IE 6+ in 'standards compliant mode'
			myWidth = document.documentElement.clientWidth;
			myHeight = document.documentElement.clientHeight;
		} else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
			//IE 4 compatible
			myWidth = document.body.clientWidth;
			myHeight = document.body.clientHeight;
		}

		var myY = (myHeight / 2) - 285 + document.body.scrollTop;
		if (myY < 0) myY = 0;

		var myX = (myWidth / 2) - 165;
		if (myX < 0) myX = 0

		var oDiv = document.getElementById(myDiv);
		oDiv.style.display = 'block';
		oDiv.style.visibility = 'visible';
		oDiv.style.top = myY;
		oDiv.style.left = myX;
		oDiv.style.height = 'auto';
		oDiv.style.width = 'auto';
		oDiv.innerHTML = "<div style='width:625px;text-align:right;padding:10px 16px 10px 10px '><span style='text-decoration:underline;cursor:pointer;' onclick=handleCloseClick('pcolor');>close</span></div><iframe title='Pick color overlay' src=" + url + " width='625' height='610' scrolling='no' frameborder='no' style='margin:0px;padding:0px;'></iframe>";
	}
	catch (e) { }
}
//End of PopUp Menu for pick color option

// function to filter the given set of chars from a given text
function FilterTextIncluding(p_szVal, p_szIncludeList) {
	var l_szNew, i, l_nLength, l_szChar, l_szCharList;

	if (p_szIncludeList.length = 0) {
		l_szNew = p_szVal;
	}
	else {
		l_szCharList = p_szIncludeList.toLowerCase();
		l_szNew = "";

		for (i = 0; i < p_szVal.length; i++) {
			l_szChar = p_szVal.charAt(i);
			if (l_szCharList.indexOf(l_szChar.toLowerCase()) > -1) {
				l_szNew = l_szNew + l_szChar;
			}
		}
	}
	return l_szNew;
}

//The following function has been written for WA
// This fuction used to track the checkout button click
function TrackCheckoutClick(p_szCName, p_szAccount, p_szSite, p_szProducts) {
	var s_account = p_szAccount;
	var l_oClickObject = document.getElementById(p_szCName);
	s.linkTrackVars = 'events,products';
	s.linkTrackEvents = 'scCheckout';
	s.events = 'scCheckout';
	s.products = p_szProducts;
	s.tl(l_oClickObject, 'o', 'Checkout Button');
}

// AR 65275 - Addition of below 2 new methods to replace the mail with the checkbox.
// This function used to track the Berman Accept button click when Checkbox is checked
function BermanOffer_Accepted_Checked(p_szCName, p_szAccount) {
	var s_account = p_szAccount;
	var l_oClickObject = document.getElementById(p_szCName);
	s.linkTrackVars = 'events';
	s.linkTrackEvents = 'event14';
	s.events = 'event14';
	s.tl(l_oClickObject, 'o', 'Berman Yes');
}

// This function used to track the Berman Accept button click when Checkbox is not checked.
function BermanOffer_Accepted_Unchecked(p_szCName, p_szAccount) {
	var s_account = p_szAccount;
	var l_oClickObject = document.getElementById(p_szCName);
	s.linkTrackVars = 'events';
	s.linkTrackEvents = 'event15';
	s.events = 'event15';
	s.tl(l_oClickObject, 'o', 'Berman Yes');
}









//The following function has been written for WA
// This function used to track the Berman Reject button click
function BermanOffer_Rejected(p_szCName, p_szAccount) {
	var s_account = p_szAccount;
	var l_oClickObject = document.getElementById(p_szCName);
	s.linkTrackVars = 'events';
	s.linkTrackEvents = 'event16';
	s.events = 'event16';
	s.tl(l_oClickObject, 'o', 'Berman No');
}

// This fuction used to track the checkout button click
function TrackGoogleCheckoutClick(p_szCName, p_szAccount, p_szProducts) {
	var s = s_gi(p_szAccount);
	var l_oClickObject = document.getElementById(p_szCName);
	s.linkTrackVars = 'events,products';
	s.linkTrackEvents = 'event7';
	s.events = 'event7';
	s.products = p_szProducts;
	s.tl(l_oClickObject, 'o', 'Google Checkout');
}

// This fuction used to track the checkout button click
function TrackRenewCheckoutClick(p_szCName) {
	if (!(document.all || document.getElementById)) return;
	var l_szProducts;
	l_szProducts = "";
	var l_oElements = document.getElementsByTagName('input');
	for (var i = 0; i < l_oElements.length; i++) {
		var l_oElt = l_oElements[i];
		if (l_oElt.type == "checkbox") {
			if (l_oElt.checked) {
				var l_oHdn = gE("hdn" + l_oElt.name);
				if (l_oHdn != undefined && l_oHdn != null) {
					l_szProducts = l_szProducts + l_oHdn.value;
				}
			}
		}
	}
	var l_oAccount = gE("hdnAccount");
	var s = s_gi(l_oAccount.value);
	var l_oClickObject = document.getElementById(p_szCName);
	s.linkTrackVars = 'events,products';
	s.linkTrackEvents = 'scCheckout,scAdd';
	s.events = 'scCheckout,scAdd';
	s.products = l_szProducts;
	s.tl(l_oClickObject, 'o', 'Checkout Button');
}

// This fuction used to track the Paypal button click
function TrackPaypalClick(p_szCName, p_szAccount, p_szProducts) {
	var s = s_gi(p_szAccount);
	var l_oClickObject = document.getElementById(p_szCName);
	s.linkTrackVars = 'events,products';
	s.linkTrackEvents = 'event12';
	s.events = 'event12';
	s.products = p_szProducts;
	s.tl(l_oClickObject, 'o', 'Paypal');
}

function TrackEnlargeImageClick(p_szCName, p_szAccount) {
	var s = s_gi(p_szAccount);
	s.linkTrackVars = 'pageName,prop4';
	s.pageName = 'bcom: larger photo'
	s.prop4 = 'larger photo'
	s.tl(null, 'o', 'larger photo');
}

function gE(id) {
	if (document.all) {
		return document.all[id];
	}
	else if (document.getElementById) {
		return document.getElementById(id);
	}
}
//The End of code for WA

// Get ingredient description using an AJAX call and show it
function showIngredientDescription(p_pageLocation, p_ingredientName, p_ingredientId, p_bShowDiv, evt) {
	var l_oAJAXReq, l_szRes

	if (p_pageLocation != null && p_ingredientId != null) {
		// The ingr ID and tracking params are added to the URL for later tracking purposes.
		l_oAJAXReq = new dsLib.AJAX.Request(p_pageLocation + '?id=' + p_ingredientId + '&trx=ingrdesc&trxp1=' + p_ingredientId, null, null, "GET", null, "text/html", false);
		l_szRes = l_oAJAXReq.responseText;
	}

	var ingrDescBox, ingrDescText, ingrHeaderText;

	if (document.all) {
		ingrDescBox = document.all.IngDescrBox;
		ingrDescText = document.all.IngrDescText;
		ingrHeaderText = document.all.IngrHeaderText
	}
	else if (document.getElementById) {
		ingrDescBox = document.getElementById('IngDescrBox');
		ingrDescText = document.getElementById('IngrDescText');
		ingrHeaderText = document.getElementById('IngrHeaderText');
	}

	if (p_bShowDiv == true) {
		if (!evt)
			eventVariable = window.event;
		else
			eventVariable = evt;

		var positionInfo = new PositionInfo(document.getElementById('TblProdForkIngredients'));
		var containerLeft, containerTop, containerWidth, containerHeight;

		containerLeft = positionInfo.getElementLeft();
		containerTop = positionInfo.getElementTop();
		containerWidth = positionInfo.getElementWidth();
		containerHeight = positionInfo.getElementHeight();

		ingrDescText.innerHTML = l_szRes;
		ingrHeaderText.innerHTML = p_ingredientName;

		// For IE, do special positioning
		if (!eventVariable.pageX) {
			ingrDescBox.style.top = "1px";
			ingrDescBox.style.left = "1px";
			ingrDescBox.style.height = containerHeight + "px";
			ingrDescBox.style.width = containerWidth + "px";
		}
		else {
			ingrDescBox.style.top = containerTop + 1 + "px";
			ingrDescBox.style.left = containerLeft + 1 + "px";
			ingrDescBox.style.height = containerHeight + "px";
			ingrDescBox.style.width = containerWidth - 25 + "px"; // subtract the padding - firefox clones are weird with that.
		}

		ingrDescBox.style.visibility = 'visible';
		ingrDescText.style.visibility = 'visible';
		ingrHeaderText.style.visibility = 'visible';
		ingredientDescShown = true;
	}
	else {
		ingrDescText.innerHTML = "";
		ingrHeaderText.innerHTML = "";
		ingrDescBox.style.visibility = 'hidden';
		ingrDescText.style.visibility = 'hidden';
		ingrHeaderText.style.visibility = 'hidden';
		ingredientDescShown = false;
	}
}

/* overlay related script - start */

//init with an possibly higher value so that even when used for then first time, it puts the element (e.g. div/overlay) upfront.
var oDragon = null;
var zIndex = 10;

function Dragon() {
	this.currX = 0;
	this.currY = 0;
	this.startX = 0;
	this.startY = 0;
	this.startCursorX = 0;
	this.startCursorY = 0;
	this.actionElement = null;
	this.movingElement = null;
}

function initADragon(evt, elementToMove) {

	var oPos, cursorPos, actionElement, movingElement;
	// init the elements and their positions
	actionElement = (evt.srcElement || evt.target);
	movingElement = ((elementToMove) ? elementToMove : actionElement);
	oDragon = new Dragon();
	oPos = new PositionInfo(movingElement);

	// init the dragon object
	oDragon.actionElement = actionElement;
	oDragon.movingElement = movingElement;

	oDragon.startX = oPos.getElementLeft();
	oDragon.startY = oPos.getElementTop();
	cursorPos = getCursorPos(evt);
	oDragon.startCursorX = cursorPos.x;
	oDragon.startCursorY = cursorPos.y;
	oDragon.movingElement.style.zIndex = ++zIndex; //assigning the highest possible z-index value

	attachEventHandlers();
	cancelDefaultEventActions(evt);
}

function moveADragon(evt) {
	var cursorPos, x, y, padding, oPos;
	if (oDragon != undefined) {
		cursorPos = getCursorPos(evt);
		oPos = new PositionInfo(oDragon.movingElement);
		x = (cursorPos.x - (oDragon.startCursorX - oDragon.startX));
		y = (cursorPos.y - (oDragon.startCursorY - oDragon.startY));
		padding = 10;
		x = (x < padding) ? padding : (x + oPos.getElementWidth() + padding > screen.availWidth) ? screen.availWidth - padding - oPos.getElementWidth() : x;
		y = (y < padding) ? padding : y;
		oDragon.movingElement.style.left = x + "px";
		oDragon.movingElement.style.top = y + "px";
		hideWindowedElements(oDragon.movingElement);
		cancelDefaultEventActions(evt);
	}
}

// this function is a hack to overcome an iE6.x only bug.
// Bug: combo box and list box html elements are windowed in IE6.x and so they appear on top of all the elements regardless of z-index.
// Fix: IFrame can hide the windowed elements. So, using the iframe to hide those elements.
function hideWindowedElements(overlayObj) {
	if (isIE && overlayObj) {
		var ieVersion = getIEVersion();
		if (ieVersion > -1 && ieVersion < 7) {
			var iFrameObj;
			// first check for associated one, if not available, use the generic one.
			// however using the generic one will cause issues when you have more than one active overlays in the same page.
			iFrameObj = gE("iFrmIE6Hack_" + overlayObj.id);
			if (!iFrameObj) iFrameObj = gE("iFrmIE6Hack");
			if (!iFrameObj) iFrameObj = self.parent.document.all["iFrmIE6Hack"];
			if (iFrameObj) {
				var pos = new PositionInfo(overlayObj);
				var visible = (overlayObj.style.visibility == "visible");
				iFrameObj.style.display = (visible) ? "block" : "none";
				if (visible) {
					iFrameObj.style.zIndex = overlayObj.style.zIndex - 1;
					iFrameObj.style.top = (pos.getElementTop()) + "px";
					iFrameObj.style.left = (pos.getElementLeft()) + "px";
					iFrameObj.style.height = (pos.getElementHeight()) + "px";
					iFrameObj.style.width = (pos.getElementWidth()) + "px";
				}
			}
		}
	}
}

//from msdn
function getIEVersion() {
	var version = -1;
	if (navigator.appName == 'Microsoft Internet Explorer') {
		var regEx = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
		if (regEx.exec(navigator.userAgent) != null)
			version = parseFloat(RegExp.$1);
	}
	return version;
}


function stopMoving(evt) {
	detachEventHandlers();
}

function cancelDefaultEventActions(evt) {
	if (isIE) {
		window.event.cancelBubble = true;
		window.event.returnValue = false;
	}
	else {
		evt.preventDefault();
	}
}

function attachEventHandlers() {
	// attach events
	if (isIE) {
		document.attachEvent("onmousemove", moveADragon);
		document.attachEvent("onmouseup", stopMoving);
	}
	else {
		document.addEventListener("mousemove", moveADragon, true);
		document.addEventListener("mouseup", stopMoving, true);
	}
}

function detachEventHandlers() {
	// detach events
	if (isIE) {
		document.detachEvent("onmousemove", moveADragon);
		document.detachEvent("onmouseup", stopMoving);
	}
	else {
		document.removeEventListener("mousemove", moveADragon, true);
		document.removeEventListener("mouseup", stopMoving, true);
	}
}

function putMeFront(obj) {
	if (obj) {
		obj.style.zIndex = ++zIndex;
		gLastOverlayId = obj.id;
	}
}

/* helpers - start */
function getCursorPos(evt) {
	return new Point(evt.clientX, evt.clientY);
}

function submitoverlay() {
	var l_oEle = self.parent.document.all['hdnPostBackOverlay']
	if (l_oEle) {
		l_oEle.value = '1';
	}
}

function showpickColorOverlay(obj, url, evt) {
	try {
		var pcOverlayName = "PCOverlay";
		var exists = false;
		var myDiv
		var e = (window.event) ? window.event : evt;
		var myWidth = 0, myHeight = 0;
		if (typeof (window.innerWidth) == 'number') {
			//Non-IE
			myWidth = window.innerWidth;
			myHeight = window.innerHeight;
		} else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
			//IE 6+ in 'standards compliant mode'
			myWidth = document.documentElement.clientWidth;
			myHeight = document.documentElement.clientHeight;
		} else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
			//IE 4 compatible
			myWidth = document.body.clientWidth;
			myHeight = document.body.clientHeight;
		}
		var myY = (myHeight / 2) - 285 + getScrollOffset().y;
		if (myY < 0) myY = 0;

		var myX = (myWidth / 2) - 165;
		if (myX < 0) myX = 0

		myDiv = gE('PCOverlay');
		if ((myDiv != null) && (gLastOverlaySource === obj)) {
			exists = true;
		}
		if (exists) {
			showOverlay(obj, pcOverlayName, true, false);
		}
		else {
			var html
			html = "<div class=\"PCOverlaybody\"><iframe title=\"Pick Color Overlay\" id=\"PCOverlayiFrame\" src=\"" + url + "\" scrolling=\"no\" frameborder=\"no\"></iframe></div>"
			createOverlay(html, 'Pick Color(s)', pcOverlayName, obj, false, false);
			myDiv = gE('PCOverlay');
		}
		if (myDiv) {
			myDiv.style.top = myY + "px";
			myDiv.style.left = myX + "px";
		}
		hideWindowedElements(myDiv);
		DisableFormElements(pcOverlayName, 'select', true);
	}
	catch (e) { }
}

function showBMLOverlay(obj, url) {
	var html, myFrame
	html = "<div class=\"BMLOverlaybody\"><iframe title=\"Bill me later Overlay\" id=\"BMLOverlayiFrame\" src=\"" + url + "\" width=\"530\" height=\"345\" scrolling=\"auto\" frameborder=\"no\"></iframe></div>"
	var name = "BMLOverlay", title = "Bill Me Later";
	var newOverlay = new Overlay(name, title, -1);
	newOverlay.bodyContent = html;
	newOverlay.showShadow = false;
	newOverlay.render();
	
	//position the overlay to center of the page
	var width = 0, height = 0, x = 0, y = 0;
	if (typeof (window.innerWidth) == "number") {
		//Non-IE
		width = window.innerWidth;
		height = window.innerHeight;
	} else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
		//IE 6+ in 'standards compliant mode'
		width = document.documentElement.clientWidth;
		height = document.documentElement.clientHeight;
	} else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
		//IE 4 compatible
		width = document.body.clientWidth;
		height = document.body.clientHeight;
	}
	
	var y = (height / 2) - 300 + getScrollOffset().y;
	if (y < 0) y = 0;
	var x = (width / 2) - 270;
	if (x < 0) x = 0
	var overlayElement = gE(name);
	overlayElement.style.left = x + "px";
	overlayElement.style.top = y + "px";
	
	showOverlay(obj, name, true, false);
	
	//This is hack for IE 6. The IFrame content is not refreshing
	myFrame = gE("BMLOverlayiFrame");
	if (isIE && myFrame) {
		myFrame.src = myFrame.src;
	}
}

/* 
function to show/hide overlay
positionNearBy - flag to position the overlay near by event triggering object.
*/
function showOverlay(obj, id, flag, positionNearBy) {
	gLastOverlaySource = obj
	var ele = gE(id);
	if (ele) {
		//only one overlay is active at a time.
		if (flag && gLastOverlayId.length > 0)
			if (gLastOverlayId != ele.id)
			closeOverlay(gLastOverlayId);
		// position the overlay based on the trigger object
		if (flag && obj && positionNearBy != undefined) {
			if (positionNearBy) {
				var triggerX, triggerY, width, height, x, y;
				var triggerPos = new PositionInfo(obj);
				var overlayPos = new PositionInfo(ele);
				var scrollOffset = getScrollOffset();

				triggerX = triggerPos.getElementLeft();
				triggerY = triggerPos.getElementTop();
				height = overlayPos.getElementHeight();
				width = overlayPos.getElementWidth();

				//repositioning the overlay so that it displayed within user's view area
				if ((triggerX + width) > (scrollOffset.x + document.body.clientWidth)) {
					x = triggerX - ((triggerX + width) - (scrollOffset.x + document.body.clientWidth));
					if (x < 0)
						x = triggerX; // if the calculated "left" position is taking the overlay out of view, reposition it.
				}
				else
					x = triggerX;

				if ((triggerY + height + 20) > (scrollOffset.y + document.body.clientHeight)) {
					y = triggerY - height - 10; //position it above the trigger object
					if (y < 0)
						y = triggerY + 20; // if the calculated "top" position is taking the overlay out of view, reposition it.
				}
				else
					y = triggerY + 20;

				ele.style.left = x + "px";
				ele.style.top = y + "px";
			}
		}
		ele.style.visibility = ((flag==true) ? "visible" : "hidden");
		ele.style.display = ((flag==true) ? "block" : "none");
		putMeFront(ele);
		hideWindowedElements(ele); //An IE only fix
		//save the id of the current overlay so that it can be hidden when any other overlay is shown.
		gLastOverlayId = ele.id;
		//attach ontimeout/onblur event handlers for the overlay 
		if (flag) {
			if (ele.getAttribute("closeonblur") == "true")
				attachOverlayOnBlurEventHandlers();
			else if (ele.getAttribute("closeontimeout") == "true") {
				var timer = getOverlayEvtHandler("timer", ele.id);
				if (timer) window.clearTimeout(timer); //clear the existing timer, if one exists for the current overlay.
				setOverlayEvtHandler("timer", ele.id, window.setTimeout(function() { closeOverlay(ele.id) }, 12000));
			}
		}
		else {
			if (ele.getAttribute("closeonblur") == "true")
				detachOverlayOnBlurEventHandlers();
		}
		//call the onshow/onhide event handlers for the current overlay, if available.
		var evtHandler = getOverlayEvtHandler((flag ? "onshow" : "onhide"), ele.id);
		if (evtHandler) evtHandler();
	}
}

function getOverlayEvtHandler(evtId, overlayId) {
	return gOverlayEvtHandlers[evtId + "_" + overlayId];
}

function setOverlayEvtHandler(evtId, overlayId, fn) {
	gOverlayEvtHandlers[evtId + "_" + overlayId] = fn;
}

function attachOverlayOnBlurEventHandlers() {
	// attach event handler
	if (isIE)
		document.attachEvent("onmousedown", closeLastShownOverlay);
	else
		document.addEventListener("mousedown", closeLastShownOverlay, true);
}

function detachOverlayOnBlurEventHandlers() {
	// detach event handler
	if (isIE)
		document.detachEvent("onmousedown", closeLastShownOverlay);
	else
		document.removeEventListener("mousedown", closeLastShownOverlay, true);
}

function closeLastShownOverlay(evt) {
	if (gLastOverlayId) {
		var lastOverlayObj = gE(gLastOverlayId);
		if ((lastOverlayObj.style.visibility != "hidden") && (lastOverlayObj.getAttribute("closeonblur") == "true")) {
			var evtX, evtY, left, top, height, width, oPos, cursorPos = getCursorPos(evt), scrollOffset = getScrollOffset();
			oPos = new PositionInfo(lastOverlayObj);
			left = oPos.getElementLeft(); top = oPos.getElementTop(); width = oPos.getElementWidth(); height = oPos.getElementHeight();
			evtX = cursorPos.x + scrollOffset.x; evtY = cursorPos.y + scrollOffset.y;
			if (!(evtX >= left && evtX <= (left + width) && evtY >= top && evtY <= (top + height))) {
				closeOverlay(gLastOverlayId);
				detachOverlayOnBlurEventHandlers();
			}
		}
	}
}

function closeOverlay(overlayId) {
	var ele = gE(overlayId);
	if (!ele) {
		ele = self.parent.document.all[overlayId];
	}
	if (ele) {
		if (ele.style.visibility != "hidden") {
			ele.style.visibility = "hidden";
			ele.style.display = "none";
			hideWindowedElements(ele); //hiding the iframe
		}
		//call the onhide event handlers for the current overlay, if available.
		var evtHandler = getOverlayEvtHandler("onhide", ele.id);
		if (evtHandler) evtHandler();
	}
}

function getScrollOffset() {
	var scrollOffsetX = 0, scrollOffsetY = 0;
	if (window.pageXOffset != undefined) {
		scrollOffsetX = window.pageXOffset;
		scrollOffsetY = window.pageYOffset;
	}
	else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
		scrollOffsetX = document.body.scrollLeft;
		scrollOffsetY = document.body.scrollTop;
	}
	else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
		scrollOffsetX = document.documentElement.scrollLeft;
		scrollOffsetY = document.documentElement.scrollTop;
	}
	return new Point(scrollOffsetX, scrollOffsetY);
}

/* tiny utility class to store a x and y position*/
function Point(x, y) {
	this.x = x;
	this.y = y;
}
/* helpers - end */

/*
client side class to create an overlay on the fly.
css classes are created to match the common needs for the overlay.
if you are customizing (e.g. no header, no footer etc.) your overlay, you need to add the css classes against the overlay id.
*/
function Overlay(id, title, width) {
	this.id = id;
	this.title = title;
	this.bodyContent = "";
	this.footerContent = "";
	this.headerContent = "";
	this.showHeader = true;
	this.showFooter = true;
	this.showShadow = true;
	this.movable = false;
	this.closeOnTimeout = false;
	this.closeOnBlur = false;
	this.width = width;
	this.initX = -1;
	this.initY = -1;
	this.faceID = this.id + "_face"
	this.titleID = this.id + "_face_title"
	this.headerID = this.id + "_face_header"
	this.contentID = this.id + "_face_content"
	this.contentInnID = this.id + "_face_content_inn"
	this.footerID = this.id + "_face_footer"
	this.footerInnID = this.id + "_face_footer_inn"
	this.className = "overlay";
	this.footerCloseBtn = true;
}

Overlay.prototype.render = function() {
	try {
		var overlayObj;
		overlayObj = gE(this.id);
		if (!overlayObj) {
			overlayObj = document.createElement("div");
			overlayObj.id = this.id;
			overlayObj.name = this.id;
			overlayObj.className = this.className;
			overlayObj.style.zIndex = ++zIndex;
			overlayObj.onclick = function() { putMeFront(this) };
			document.body.appendChild(overlayObj);
		}

		//add the custom attributes
		overlayObj.setAttribute("closeontimeout", (this.closeOnTimeout ? "true" : "false"));
		overlayObj.setAttribute("closeonblur", (this.closeOnBlur ? "true" : "false"));
		//add style	
		if (this.width > -1) overlayObj.style.width = this.width + "px";
		if (this.initX > -1) overlayObj.style.left = this.initX + "px"
		if (this.initY > -1) overlayObj.style.top = this.initY + "px";

		overlayObj.innerHTML = this.scriptIt(); //create the content only for the first time
	}
	catch (e)
	{ }
}

Overlay.prototype.scriptIt = function() {
	try {
		var html;
		html = "<div id=\"" + this.faceID + "\" class=\"" + (this.showShadow ? "face_shadow" : "face") + "\">";
		// css classes are created to match the common needs for the overlay.
		// if you are customizing (e.g. no header, no footer etc.) your overlay, you need to add the css classes against the overlay id.

		//header
		if (this.showHeader) {
			html = html + "<div id=\"" + this.headerID + "\" class=\"header\" " + (this.movable ? "onmousedown=\"javascript:initADragon(event,gE('" + this.id + "'));\" style=\"cursor:move;\"" : "") + ">";
			html = html + "<div class=\"close\" onclick=\"javascript:showOverlay(this, '" + this.id + "', false);\"><img src=\"" + gOverlayAssets["closebtnsrc"] + "\" class=\"headclosebtn\" border=\"0\" hspace=\"0\" vspace=\"0\" alt=\"close\" /></div>";
			html = html + "<div class=\"lc\" ></div>";
			html = html + "<div class=\"rc\" ></div>";
			html = html + "<div id=\"" + this.titleID + "\" class=\"title\">" + this.title + "</div>";
			html = html + "</div>";
		}

		var contentCSS;
		contentCSS = "content";
		contentCSS = contentCSS + (this.showHeader ? "" : " noheader");
		contentCSS = contentCSS + (this.showFooter ? "" : " nofooter");

		//body
		html = html + "<div id=\"" + this.contentID + "\" class=\"" + contentCSS + "\" >";
		html = html + "<div id=\"" + this.contentInnID + "\" class=\"inn\">";
		html = html + this.bodyContent;
		html = html + "</div>";
		html = html + "</div>";

		//footer
		if (this.showFooter) {
			html = html + "<div id=\"" + this.footerID + "\" class=\"footer\">";
			html = html + "<div class=\"bl\"></div>";
			html = html + "<div class=\"br\"></div>";
			html = html + "<div id=\"" + this.footerInnID + "\" class=\"inn\">";
			if (this.footerContent.length == 0) {
				if (this.footerCloseBtn) {
					html = html + "<span class=\"close\" onclick=\"javascript:showOverlay(this, '" + this.id + "', false);\">";
					if (gOverlayAssets) {
						var closeBtn = gOverlayAssets["closebtnsrc"]
						if (closeBtn) {
							html = html + "<img src=\"" + gOverlayAssets["closebtnsrc"] + "\" class=\"closebtn\" border=\"0\" hspace=\"0\" vspace=\"0\" alt=\"close\" />";
						}
						else {
							html = html + "close";
						}
					}
					html = html + "</span>";
				}
			}
			else {
				html = html + this.footerContent;
			}
			html = html + "</div>";
			html = html + "</div>";
		}
		html = html + "</div>";
		return html;
	}
	catch (e)
	{ }
}


function handleCheckOutClick(sHREF) {
	try {
		// Consider if our window is modal
		var winMgr = GetWinMgr();
		if (winMgr) {
			if (winMgr.IsModal()) {
				return false;
			}
		}
	}
	catch (e) { }

	if (document.frmRecalc && document.frmRecalc.hdnRedirect){
		document.frmRecalc.hdnRedirect.value = sHREF;
		document.frmRecalc.submit();
	}
}


/*
simple function to display alert/confirm messages. it uses the overlay object to display the message.
if "obj" parameter is NOT passed,
the alert box is positioned based on the top,left coordinates defined in style sheet
usage:
dsAlert("alert box");
dsAlert("alert box", "drugstore.com");
dsAlert("alert box", "drugstore.com", "mybox");
dsAlert("alert box", "drugstore.com", "mybox", hlnkDOMObj);
dsAlert("alert box", "drugstore.com", "mybox", hlnkDOMObj, false);
*/
function dsAlert(msg, title, name, obj, closeOnTimeout) {
	var tempTitle = title, tempName = name;

	if (tempTitle == undefined) tempTitle = "";
	if (tempName == undefined) tempName = "dsalert";
	else if (tempName.length == 0) tempName = "dsalert";

	var popup = new Overlay(tempName, tempTitle, -1);
	popup.bodyContent = msg;
	popup.showShadow = false;
	popup.className = "confirmoverlay";
	/*
	Generally, alert boxes are supposed to be closed after specified amount of time (12 secs).
	Incase, there are exceptions where the alert box shouldn't be auto closed, 
	"closeOnTimeout" flag can be set to false by the calling routine (e.g yourlist.js -> deleteConfirm)
	*/
	if (closeOnTimeout != undefined)
		popup.closeOnTimeout = closeOnTimeout;
	else
		popup.closeOnTimeout = true;
	popup.render();
	showOverlay(obj, tempName, true, true);
	//IE 6 hack, introduing the IFrame to show the overlay in IE6
	hideWindowedElements(obj);
}

//wrapper function to create an overlay
function createOverlay(msg, title, name, obj, closeOnTimeout, closeOnBlur) {
	var tempTitle = title, tempName = name;

	if (tempTitle == undefined) tempTitle = "";
	if (tempName == undefined) tempName = "dsalert";
	else if (tempName.length == 0) tempName = "dsalert";

	var newOverlay = new Overlay(tempName, tempTitle, -1);
	newOverlay.bodyContent = msg;

	if (closeOnTimeout != undefined)
		newOverlay.closeOnTimeout = closeOnTimeout;
	if (closeOnBlur != undefined)
		newOverlay.closeOnBlur = closeOnBlur;

	newOverlay.showShadow = false;
	newOverlay.render();
	showOverlay(obj, tempName, true, true);
}

/* overlay related script - end */

//function (called from email overlay) to confirm "Email Sending Action" to the user
function confirmEmailSend() {
	if (self.name == "iFrmProdRec") {
		parent.closeOverlay(parent.gLastOverlayId);
		parent.gReloadProdRecOverlay = true;
		var html = "<div class=\"prodrecconfirmbody\"><b>Thank you.</b>&nbsp;We've sent email to your friend about this product.</div>";
		parent.dsAlert(html, "", "ProdRecConfirm");
	}
}
//This function is the onkeydown event for the text are used in product_recommnder.asp
function emailmsgCounter(e) {
	return msgCounter(e, this, 500);
}
//This function is used to restrict the max character for given any control. 
//e is the event parameter which is passed by when user key on the control. 
// This function shouldnot be assigned directly to onkeydown event rather it should be called from the onkeydown event function 
function msgCounter(e, obj, p_nMax) {
	var nMax = p_nMax;
	var nLength = obj.value.length;
	var nKey = -1;
	var nBackSpaceKeyCode = 8;
	var nTabKeyCode = 9;
	var nDeleteKeyCode = 46;
	if (e && e.which) // Netscape keycode
		nKey = e.which;
	else if (window.event && window.event.keyCode) // IE keycode
		nKey = window.event.keyCode;
	// always allow deletion keys (backspace/delete)
	if ((nKey == nBackSpaceKeyCode) || (nKey == nDeleteKeyCode)) {
		if (nLength <= nMax)
			nLength = nLength - 1;
		if (nLength >= 0)
			return true;
		else
			return false;
	}
	// always allow neutral keys (just don't update the counter)
	else if (((nKey >= 33) && (nKey <= 40)) || (nKey == nTabKeyCode))
		return true;
	else {
		if (nLength < nMax) {
			nLength = nLength + 1;
			return true;
		}
		else
			return false;
	}
}

function f_clientWidth() {
	return f_filterResults(
		window.innerWidth ? window.innerWidth : 0,
		document.documentElement ? document.documentElement.clientWidth : 0,
		document.body ? document.body.clientWidth : 0
	);
}

function f_clientHeight() {
	return f_filterResults(
		window.innerHeight ? window.innerHeight : 0,
		document.documentElement ? document.documentElement.clientHeight : 0,
		document.body ? document.body.clientHeight : 0
	);
}

function f_scrollLeft() {
	return f_filterResults(
		window.pageXOffset ? window.pageXOffset : 0,
		document.documentElement ? document.documentElement.scrollLeft : 0,
		document.body ? document.body.scrollLeft : 0
	);
}

function f_scrollTop() {
	return f_filterResults(
		window.pageYOffset ? window.pageYOffset : 0,
		document.documentElement ? document.documentElement.scrollTop : 0,
		document.body ? document.body.scrollTop : 0
	);
}

function f_filterResults(n_win, n_docel, n_body) {
	var n_result = n_win ? n_win : 0;
	if (n_docel && (!n_result || (n_result > n_docel)))
		n_result = n_docel;
	return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result;
}

function GetWinMgr() {
	if (!gWinMgr) {
		gWinMgr = new WindowManager();
	}
	return gWinMgr;
}

function WindowManager() {
	var _isModal = false;
	this.IsModal = function() {
		return _isModal;
	}
	this.SetModal = function(fModal) {
		_isModal = fModal;
		try {
			if (_isModal) {
				document.body.onclick = function() { return false; }
			}
			else {
				document.body.onclick = null;
			}
		}
		catch (e) { }
	}
}

var SearchInput = new function() {
	this.Setup = function(runtimeConfig) {
		try {
			this.InitHelper();
			var fieldDefinition = new Object();
			fieldDefinition.inputFieldDefaultText = runtimeConfig.inputFieldDefaultText;
			fieldDefinition.element = document.getElementById(runtimeConfig.inputFieldId);
			fieldDefinition.useSearchTermEvents = true;
			gSearch.AddInputField(fieldDefinition);
		}
		catch (e) { /*eat it*/ }
	}
	this.InitHelper = function() {
		if (!gSearch) {
			gSearch = new SearchHelper();
		}
	}
}

function SearchHelper() {
	this.InputFields = new Array();
}
SearchHelper.prototype.AddInputField = function(fieldDefinition) {
	try {
		this.InputFields.push(fieldDefinition);
		if (fieldDefinition.useSearchTermEvents) {
			this.WireSearchTermEvents(fieldDefinition);
		}
	}
	catch (e) { throw e; }
}
SearchHelper.prototype.WireSearchTermEvents = function(fieldDefinition) {
	try {
		attachEventListener(fieldDefinition.element, "focus", this.SearchTermFocus);
		//attachEventListener(fieldDefinition.element, "blur", this.SearchTermBlur);
	}
	catch (e) { throw e; }
}
SearchHelper.prototype.SearchTermFocus = function(e) {
	try {
		var evnt = GetEvent(e);
		if (evnt) {
			var fieldDefinition = gSearch.GetFieldDefinition(evnt.id);
			if (fieldDefinition) {
				var elText = fieldDefinition.element;
				if (elText.value.toLowerCase() == fieldDefinition.inputFieldDefaultText.toLowerCase()) {
					elText.value = '';
				}
			}
		}
	}
	catch (e) { throw e; }
}
SearchHelper.prototype.SearchTermBlur = function(e) {
	try {
		var evnt = GetEvent(e);
		if (evnt) {
			var fieldDefinition = gSearch.GetFieldDefinition(evnt.id);
			if (fieldDefinition) {
				var elText = fieldDefinition.element.value;
				if (elText.length == 0) {
					fieldDefinition.element.value = fieldDefinition.inputFieldDefaultText;
				}
			}
		}
	}
	catch (e) { throw e; }
}
SearchHelper.prototype.GetFieldDefinition = function(elId) {
	try {
		for (var i = 0; i <= gSearch.InputFields.length - 1; i++) {
			if (gSearch.InputFields[i].element.id == elId) {
				return gSearch.InputFields[i];
				break;
			}
		}
	}
	catch (e) { throw e; }
}

function attachEventListener(el, eventName, handler) {
	if (el.attachEvent) {
		el.attachEvent('on' + eventName, handler);
	}
	else if (el.addEventListener) {
		el.addEventListener(eventName, handler, true);
	}
}

GetQSArgs = function() {
	var sSearch = document.location.search;
	var arArgs = "";

	if (sSearch) {
		if (sSearch.charAt(0) == "?") {
			sSearch = sSearch.substr(1);
		}
		arArgs = sSearch.split("&")
	}

	return arArgs;
}

//function to highlight the item row in "browse" nav bar
function setBrowseHoverStyle(obj, e, onMouseOverClass){
	if (e){
		var cssClassName = obj.className;
		var isMouseOver = (e.type == "mouseover");
		//assign/append the css class name
		if (isMouseOver){
			if (cssClassName.indexOf(onMouseOverClass) == -1)
			{
				if (cssClassName == "")
					cssClassName = onMouseOverClass;
				else
					cssClassName = cssClassName + " " + onMouseOverClass;
			}
		}
		//remove or replace the css class name
		else{
			if (cssClassName.indexOf(" " + onMouseOverClass) > -1){
				cssClassName = cssClassName.replace(" " + onMouseOverClass, "");
			}
			else if (cssClassName == onMouseOverClass){
				cssClassName = "";
			}
			else 
			{
				//do nothing
			}
		}
		obj.className = cssClassName;
	}
}

function resizeContainerFrame(iFrameID){
	var iFrm = gE(iFrameID);
	if(iFrm)
	{
		//adding 15px to fix IE issue. Need to find a cleaner one later.
		iFrm.style.height = window.frames[iFrameID].document.body.scrollHeight + 15 + "px";
	}
}
