/* Create a name space for all Artline specific JavaScript functions. */

var ARTLINE = {
	mouse : {},
	event : {},
	dom : {},
	menu : {},
	category : {
		mouseX : 0,
		mouseY : 0,
		hoverCard : {
			index : 0,
			itemID : 0,
			timer : null,
			event : null,
			element : null
		},
		itemOverlay : {
			overlay : null,
			x : 0,
			y : 0,
			urls :  new Array(),
			offset : {
				x : 15,
				y : 15
			}
		}
	},
	searchForm : {
		placeholderText : "Enter style, theme, or card #"
	},
	orderForm : {}
};

/* Returns the x position of the mouse for the specified event. */

ARTLINE.mouse.mouseX = function (event)
{
	// Error handling for IE during page load. Not exactly sure what causes it.
	
	try
	{
		if (event.pageX)
		{
			return event.pageX;
		}
		else if (event.clientX)
		{
			return event.clientX + (document.documentElement.scrollLeft ?  document.documentElement.scrollLeft : document.body.scrollLeft);
		}
		else
		{
			return 0;
		}
	}
	catch(e)
	{
		return 0;
	}
};

/* Returns the y position of the mouse for the specified event. */

ARTLINE.mouse.mouseY = function (event)
{
	// Error handling for IE during page load. Not exactly sure what causes it.
	
	try
	{
		if (event.pageY)
		{
			return event.pageY;
		}
		else if (event.clientY)
		{
			return event.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
		}
		else
		{
			return 0;
		}
	}
	catch(e)
	{
		return 0;
	}
};

/* Adds an event listener in a non-destructive manner. */

ARTLINE.event.addEventListener = function (element, eventName, listener)
{
	if (element.attachEvent)
	{
		// Use Internet Explorer method.
		element.attachEvent("on" + eventName, listener);
	}
	else
	{
		// Use newer DOM method supported by Firefox.
		element.addEventListener(eventName, listener, true);
	}
};

/* This method is called when the XMLHTTPRequest returns from its round-trip
 * with the server. The overlay is updated, positioned, and displayed. */

ARTLINE.category.overlayCallback = function(o)
{
	var itemOverlay = ARTLINE.category.itemOverlay;
	var overlay = itemOverlay.overlay;
	
	// Bail out if the response text is undefined
	// (this occurs sometimes in Firefox)
	
	if (!o.responseText)
		return;
	
	// Pull down the HTML and render the overlay

	overlay.body.innerHTML = o.responseText;
	
	overlay.render();
	
	// Move the overlay by the given amount
	
	var left = itemOverlay.x + itemOverlay.offset.x;
	var top = itemOverlay.y + itemOverlay.offset.y;
	
	overlay.cfg.setProperty("xy", [left, top])
	
	overlay.show();
}

/* After waiting for the timer to fire, we can finally request the details page
 * from the server. */

ARTLINE.category.showCardHoverPanel = function()
{
	var category = ARTLINE.category;
	var itemOverlay = category.itemOverlay;
	
	// First, take a snapshot of the cursor position so the 
	// overlay can be positioned properly when the callback fires
	
	itemOverlay.x = category.mouseX;
	itemOverlay.y = category.mouseY;
	
	// Now do the HTTP request
	
	YAHOO.util.Connect.asyncRequest(
			'GET',
			itemOverlay.urls[category.hoverCard.index - 1],
			{
				success : category.overlayCallback,
				failure : category.overlayCallback,
				argument : null
			}
	);
	
	return;
}

/* This is an event listener which will position the card hover element based on
 * the current mouse position. This should be attached to the onmousemove
 * event. */

ARTLINE.category.handleMouseMove = function (event)
{
	var category = ARTLINE.category;
	var hoverCard = category.hoverCard;
	
	// Update the mouse position
	
	category.mouseX = ARTLINE.mouse.mouseX(event);
	category.mouseY = ARTLINE.mouse.mouseY(event);
	
	// Determine if we want to hide the overlay by comparing the mouse position
	// to the position of the image.
	
	if (hoverCard.event)
	{
		var image = hoverCard.image;
		var region = YAHOO.util.Region.getRegion(image);
		var point = new YAHOO.util.Point(category.mouseX, category.mouseY);
		
		if (!region.contains(point))
		{
			category.hideOverlay(event);
		}
	}
	
	// Bail if no item is being hovered, or if we're alreading waiting for a
	// pop-up to show
	
	if (hoverCard.itemID == 0 || hoverCard.timer)
	{
		return;
	}
	
	// Hide the tooltip. Otherwise, it will display on top of the overlay in
	// Internet Explorer.
	
	hoverCard.image.alt = "";
	hoverCard.image.title = "";
	
	// Delay the actual appearance of the panel. Note that this also helps with
	// the animation, since the fade-out needs a certain amount time to complete
	// before the overlay DIV can be re-assigned to this item
	
	hoverCard.timer = setTimeout("ARTLINE.category.showCardHoverPanel()", 350);
};

/* This method records the item whose hover element we should show. Another
 * method, one attached to the onmousemove event, will position the element.
 * This method should be called when the mouse moves over the card thumbnail. */

ARTLINE.category.showOverlay = function (event, index, itemID, image)
{
	var hoverCard = ARTLINE.category.hoverCard;
	
	hoverCard.event = event;
	
	hoverCard.index = index;
	
	hoverCard.itemID = itemID;
	
	hoverCard.image = document.getElementById(image);
};

/* This method hides the current card hover element. This should be called when
 * the mouse moves off of a card thumbnail. */

ARTLINE.category.hideOverlay = function (event)
{
	var hoverCard = ARTLINE.category.hoverCard;
	
	clearTimeout(hoverCard.timer); 
	
	hoverCard.timer = null;
	
	hoverCard.index = 0;
	
	hoverCard.itemID = 0;
		
	hoverCard.event = null;
	
	hoverCard.image = null;
	
	ARTLINE.category.itemOverlay.overlay.hide();
};

ARTLINE.searchForm.handleSubmit = function(form)
{
	// Normalize the keyword field. By default, it will have some help text in
	// it.
	
	if (form.keywords.value == ARTLINE.searchForm.placeholderText)
	{
		form.keywords.value = "";
	}
	
	// If the keyword field is empty, give the user a warning rather than trying
	// to run a search.
	
	if (form.keywords.value == "")
	{
		alert("Please provide a keyword, style or card number.");
		
		return false;
	}
	
	// Log the keywords to the IndexTools stats script.
	
	if (typeof(captureClickout) != "undefined")
	{
		try
		{
			captureClickout("05", form.keywords.value);
		}
		catch(e)
		{
			// Do nothing.
		}
	}
	
	return true;
};

ARTLINE.searchForm.handleClick = function(formName)
{
	var form = document.getElementById(formName);
	
	if (ARTLINE.searchForm.handleSubmit(form))
	{
		form.submit();
	}
};

ARTLINE.searchForm.handleKeywordFocus = function(field)
{
	// Hide the help text when the user selects the field.
	
	if (field.value == ARTLINE.searchForm.placeholderText)
	{
		field.value = "";
		
		field.className = "";
	}
};

ARTLINE.searchForm.handleKeywordBlur = function(field)
{
	// If the user has moved away from the field and it is empty, re-insert the
	// help text.
	
	if (field.value == "")
	{
		field.value = ARTLINE.searchForm.placeholderText;
		
		field.className = "hint";
	}
};

/* Watch to see if there's a card hover element that we should display. */

ARTLINE.event.addEventListener(document, "mousemove", ARTLINE.category.handleMouseMove);


/* ****************************** Order Form ****************************** */

ARTLINE.orderForm.panels = {};

ARTLINE.orderForm.updateSwatch = function(name)
{
	var select = document.getElementById(name + "Select");
	
	// NOTE: In what circumstances does this return undefined/null?
	
	if (!select)
	{
		return;
	}
	
	var swatch = document.getElementById(name + "Swatch");
	var color = select.options[select.selectedIndex].value;
	
	try
	{
		swatch.style.backgroundColor = "#" + color;
	}
	catch (ex)
	{
		// NOTE: In what circumstances will this throw an error?
	}
	
	var colorName = document.getElementById(name + "Name");
	
	colorName.value = select.options[select.selectedIndex].text;
};

ARTLINE.orderForm.getForm = function()
{
	return document.forms.orderForm;
};

ARTLINE.orderForm.getIsCustomVerse = function()
{
	var form = ARTLINE.orderForm.getForm();
	
	return form.isCustomVerse;
};

ARTLINE.orderForm.getIsCustomVerseOption = function(value)
{
	var input = ARTLINE.orderForm.getIsCustomVerse();
	
	// NOTE: We have to check for the existence of the radio button because
	// it will not exist if the card does not have a verse option set.
	
	if (input)
	{
		for (var i = 0; i < input.length; i++)
		{
			var option = input[i];
			
			if (option.value == value)
			{
				return option;
			}
		}
	}
	
	return null;
};

ARTLINE.orderForm.getVerseSelect = function()
{
	return document.getElementById("versesSelect");
};

ARTLINE.orderForm.getCustomVerse = function()
{
	return document.getElementById("customVerse");
};

ARTLINE.orderForm.setIsCustomVerse = function(isCustomVerse)
{
	var verseSelectInput;
	var customVerseInput;
	var customVerseOption;
	var notCustomVerseOption;
	var enabledInput;
	var disabledInput;
	var checkedRadio;
	var uncheckedRadio;
	
	// Fetch the form elements that we'll be toggling.
	
	verseSelectInput = ARTLINE.orderForm.getVerseSelect();
	customVerseInput = ARTLINE.orderForm.getCustomVerse();
	customVerseOption = ARTLINE.orderForm.getIsCustomVerseOption(1);
	notCustomVerseOption = ARTLINE.orderForm.getIsCustomVerseOption(0);
	
	// Determine which elements get toggled in which direction.
	
	if (isCustomVerse)
	{
		enabledInput = customVerseInput;
		disabledInput = verseSelectInput;
		checkedRadio = customVerseOption;
		uncheckedRadio = notCustomVerseOption;
	}
	else
	{
		enabledInput = verseSelectInput;
		disabledInput = customVerseInput;		
		checkedRadio = notCustomVerseOption;
		uncheckedRadio = customVerseOption;
	}
	
	// Change the style of the disabled element. We're doing this instead of
	// actually disabling the element because the visual effect of disabling an
	// element is harsh.
	
	// NOTE: We have to check for the existence of the inputs before enabling
	// and disabling them because the verse select input will not be available
	// if there are no verses.
	
	// FIXME: We should refactor class manipulation into separate methods.
	
	if (enabledInput)
	{
		enabledInput.className = enabledInput.className.replace(" disabled", "");
	}
	
	if (disabledInput)
	{
		if (disabledInput.className.indexOf(" disabled") == -1)
		{
			disabledInput.className += " disabled";
		}
	}
	
	// NOTE: The checkbox itself will not exist if the card does not even have
	// a verse option set.
	
	if (checkedRadio)
	{
		checkedRadio.checked = true;
	}
};

ARTLINE.orderForm.selectPanelOption = function(panelName, selectName, selectIndex)
{
	
	var selectElement = document.getElementById(selectName);
	
	selectElement.selectedIndex = selectIndex;
	
	if (name == "verses")
	{
		ARTLINE.orderForm.setIsCustomVerse(false);
	}
	
	if (selectElement.onchange)
	{
		selectElement.onchange();
	}
		
	ARTLINE.orderForm.panels[panelName].hide();
};


ARTLINE.orderForm.panelCallBack = function(response)
{
	if (response.status != 0)
	{
		
		var id = response.argument.id;
		
		var panelBody = document.getElementById(id);
		
		panelBody.innerHTML = response.responseText;
		
	}
};


ARTLINE.orderForm.registerPanel = function(name, fetchBody, printable, clickable, url)
{
	var linkName = name + "Link";
	
	var panelOptions = {
		"width" : "600px",
		"height" : "400px",
		"close" : true,
		"context" : ["orderForm", "tl", "tl"],
		"visible" : false,
		"fixedcenter" : true,
		"draggable" : false,
		"modal" : false,
		"constraintoviewport" : true,
		"effect" : {
			"effect" : YAHOO.widget.ContainerEffect.FADE,
			"duration" : 0.25
		}
	};
	
	var panel = new YAHOO.widget.Panel(name, panelOptions);
	
	if (printable == null)
		printable = true;
		
	if (clickable == null)
		clickable = true;
	
	ARTLINE.orderForm.panels[name] = panel;
	
	// NOTE: If the panels are not located directly under the body
	// tag, errors may occur in IE when calling this during the
	// onload or domready events. In which case, render should be
	// called immediately before show().
	
	panel.render();
	
	if (fetchBody)
	{
		var bodyName = name + "Body";
		
		YAHOO.util.Event.addListener(
			linkName,
			"click",
			function()
			{
				var transaction = YAHOO.util.Connect.asyncRequest(
						'GET',
						/* NOTE: Adding a timestamp to prevent caching in IE. */
						url + "&printable=" + printable + "&clickable=" + clickable + "&id=" + name,
						{
							"success" : ARTLINE.orderForm.panelCallBack,
							"failure" : ARTLINE.orderForm.panelCallBack,
							"argument": {
								"id" : bodyName
							}
						}
				);
			}
		);
	}
	
	YAHOO.util.Event.addListener(
			linkName,
			"click",
			function(e)
			{
				panel.show(panel, true);
				// The panel is hidden by default to avoid scroll bars
				// in IE. We want to wait until the panel has been
				// positioned before displaying it.
				document.getElementById(name).style.display = "block";
				e.cancelBubble = true;
			}
	);
};
		
/* Helper method for printing the content of a panel. */
		
ARTLINE.orderForm.printPanel = function(id)
{
	var iframe = document.getElementById("printFrame");
	
	// From:
	//   
	//   http://xkr.us/articles/dom/iframe-document/
	//   
	// In short:
	//   
	//   contentWindow returns the window object in IE and Gecko.
	//   contentDocument returns the document in Safari.
	//   contentDocument returns the window in Opera.
	
	var iframeDoc = iframe.contentWindow || iframe.contentDocument;
	
	// We may have a window or document. We want a document.
	
	if (iframeDoc.document)
	{
		iframeDoc = iframeDoc.document;
	}
	
	iframeDoc.open();
	
	var panel = document.getElementById(id);
	
	iframeDoc.write(panel.innerHTML);
	
	/* NOTE: window.print() does not work in the Safari 3 beta
	  --- for Windows. For the moment, we're going to ignore it in
	  --- the hopes that it will be fixed before the final
	  --- release. */
	
	/* The window.focus() command is for IE. */
	
	var printCommand = "setTimeout(\"window.focus(); window.print();\", 1000);";
	
	var script = "<s" + "cript type=\"text/javascript\">" + printCommand + "</s" + "cript>";
	
	iframeDoc.write(script);
	
	iframeDoc.close();
};
		

ARTLINE.orderForm.onTextFocus = function(text, defaultString) {
	if (text.value == defaultString) {
		text.value = "";
		text.setAttribute("class", "text");
		text.setAttribute("className", "text");
	}
}

ARTLINE.orderForm.onTextBlur = function(text, defaultString) {
	if (text.value == "") {
		text.value = defaultString;
		text.setAttribute("class", "text disabled");
		text.setAttribute("className", "text disabled");
	}
}

ARTLINE.orderForm.enableInputs = function(inputs, enabled) {
	for (var i = 0; i < inputs.length; i++) {
		input = document.getElementById(inputs[i]);
		
		if (!input) return;
		
		if (enabled) {
			
			input.removeAttribute("disabled");
			
			if (input.getAttribute("class")) {
				input.setAttribute("class", input.getAttribute("class").replace(/disabled/g, ""));
				input.setAttribute("className", input.getAttribute("className").replace(/disabled/g, ""));
			}
			
		} else {
			
			input.setAttribute("disabled", "disabled");
			
			if (input.getAttribute("class") || input.getAttribute("className")) {
				input.setAttribute("class", input.getAttribute("class") + " disabled");
				input.setAttribute("className", input.getAttribute("className") + " disabled");
			} else {
				input.setAttribute("class", "disabled");
				input.setAttribute("className", "disabled");
			}
		}
	}
}
