// Get the document domain.
var SITE_DOMAIN = document.location.href;
SITE_DOMAIN		= "/";

// An iterator class.
function Iterator (values)
	{	// Initialize the values.
		this.values		= values;
		this.curr_index	= 0;

		// This method determines whether any more values occur within the iteration.
		this.hasMoreElements = function ()
			{	return this.curr_index < this.values.length;
			}; // this.hasMoreElements = function ()

		// This method returns the next item in the iteration; or false.
		this.next = function ()
			{	return this.hasMoreElements() ? this.values[this.curr_index++] : false;
			}; // this.next = function ()

		return this;
	}; // function Iterator (values)

// ----------------------------------------------------------------------------------------------------------------

// A class which iterates over suggestions.
function SuggestionIterator (root)
	{	// Initialize the values.
		this.values		= root ? root.getElementsByTagName("suggestion") : false;
		this.curr_index	= 0;

		// This method determines whether any more values occur within the iteration.
		this.hasMoreElements = function ()
			{	var has_more = this.values && this.curr_index < this.values.length;
				return has_more;
			}; // this.hasMoreElements = function ()

		// This method returns the next item in the iteration; or false.
		this.next = function ()
			{	if ( this.hasMoreElements() )
					{	// Get the next value.
						var suggestion	= this.values.item(this.curr_index++);

						// Convert it to an accessible object.
						var value	= {};

						// Get the id.
						// value.id		= suggestion.attributes["id"] ? suggestion.attributes["id"].nodeValue : "-1";
						value.id		= suggestion.getAttribute("id");

						// Is this value active?
						// value.active	= suggestion.attributes["active"] ? suggestion.attributes["active"].nodeValue == "yes" : false;
						value.active	= suggestion.getAttribute("active") == "yes"; 

						// Get the action to perform.
						value.action	= suggestion.getAttribute("action"); 
						value.action	= value.action ? value.action.replace(/\&#38;/g, "&") : value.action;

						// Get the target.
						value.target	= suggestion.getAttribute("target");

						// Get the dimensions.
						var dims	= "" + suggestion.getAttribute("dims");
						var width	= dims.indexOf(",") >= 0 ? dims.replace(/,[^$]*$/, "") : "400";
						width		= width.replace(/^\s+|\s+$/g, "");
						var height	= dims.indexOf(",") >= 0 ? dims.replace(/^[^,]*,/, "") : "400";
						height		= height.replace(/^\s+|\s+$/g, "");
						value.dims	= new Array(width, height);

						// Get the title.
						value.title		= suggestion.getElementsByTagName("title");
						value.title		= value.title && value.title.length > 0 ? value.title.item(0) : false;
						value.title		= value.title && value.title.firstChild ? value.title.firstChild.nodeValue : "";

						// Get the URL.
						value.url		= suggestion.getElementsByTagName("url");
						value.url		= value.url&& value.url.length > 0 ? value.url.item(0) : false;
						value.url		= value.url && value.url.firstChild ? value.url.firstChild.nodeValue : "";		
						value.url		= value.url.replace(/\&#38;/g, "&");
						
						return value;
					} // if ( this.hasMoreElements() )
				else
					{	return false;
					}; // else
			}; // this.next = function ()

		// This method resets the iteration.
		this.reset = function ()
			{	this.curr_index = 0;
			}; // this.reset = function ()

		return this;
	}; // function SuggestionIterator (root)

// ----------------------------------------------------------------------------------------------------------------

// This function initializes the auto-complete form.
function setupAutoComplete (field_id, display_id)
	{	// Get the auto-complete UI component.
		var auto = document.getElementById(field_id);

		// Set its data, events, and methods.
		if ( auto )
			{	// Initialize values.
				auto.enabled	= false;
				auto.display_id	= display_id;
				auto.init		= true;
				auto.ref_id		= false;
				auto.ref_urls	= new Array();
				auto.bkg		= false;
				auto.content	= false;
				auto.component	= false;

				// Set various events.
				auto.onfocus =
					function ()
						{	
						}; // function ()

				auto.onkeyup =
					function (event)
						{	// The component is enabled.
							if ( this.enabled )
								{	var code = window.event ? window.event.keyCode : event.keyCode;
									switch ( code ) 
										{	// Display the previous suggestion.
											case 38: // Up arrow
												if ( this.component && this.component.prevSuggestion )
													{	this.component.prevSuggestion ();
													}; // if ( this.component && && this.component.prevSuggestion  )
												break;
												
											// Display the next suggestion.
											case 40: // Down arrow
												if ( this.component && this.component.nextSuggestion )
													{	this.component.nextSuggestion();
													}; // if ( this.component && this.component.nextSuggestion )
												break;

											case 13: // Enter
												if ( this.component.link )
													{	document.location = this.component.link;
														return false;
													};
												// this.hideSuggestions();
												// break;

											// Perform the auto-complete.
											default:
												this.component.link = undefined;
												this.autoComplete(this.value);
												break;
										}; // switch ( code ) 
								}; // if ( this.enabled )
						}; // function (event)

				// This method performs an auto-completion update.
				auto.autoComplete = function (value)
					{	// Make the AJAX request to get the suggestions.
						var ref_url = this.ref_id != false && this.ref_urls[this.ref_id] ? this.ref_urls[this.ref_id] : "";

						// Substitute in the term.
						ref_url = ref_url.replace("{query}", escape(value));

						// Make the AJAX request.
						if ( this.enabled && ref_url !== "" )
							{	// Make the AJAX call.
								makeAJaxRequest(ref_url, "get", this, new Array(this.ref_id, value));
							}; // if ( this.enabled && ref_url !== "" )
					}; // function autoComplete (url, values, auto_id)

				// This method creates the content for 0 result queries.
				auto.createErrorView = function (component, value, xml)
					{	// Get any error messages.
						var error = xml ? xml.getElementsByTagName("error") : false;

						// Create the content.
						var content			= document.createElement("div");
						content.className	= "content no_results";

						// Add the window footer.
						content.appendChild(this.createWindowFooter(component));

						// Get the error.
						error = error.item(0);
						error = error.firstChild ? error.firstChild.nodeValue : "";

						// Replace tag values.
						error = error.replace(/\[div\]/g, "<div>");
						error = error.replace(/\[\/div\]/g, "</div>");
						error = error.replace(/\[br\]/g, "<br />");
						error = error.replace(/\[br\s*\/\]/g, "<br />");
						error = error.replace(/\[\/br\]/g, "");
						error = error.replace(/\[h2\]/g, "<h2>");
						error = error.replace(/\[\/h2\]/g, "</h2>");
						error = error.replace(/\[p\]/g, "<p>");
						error = error.replace(/\[\/p\]/g, "</p>");
						error = error.replace(/\[a\s+href\s*=\s*\"([^\"]*)\"\s*(onclick=\s*\s*"[^\"]*")?\]/g, "<a href=\"$1\" $2>");
						error = error.replace(/\[\/a\]/g, "</a>");
						error = error.replace(/\[title\]/g, "<div class=\"title\">");
						error = error.replace(/\[\/title\]/g, "</div>");

						// Create the error panel.
						var element		= document.createElement("div");
						element.innerHTML	= error;

						// Set the cotent's inner HTML.
						content.appendChild(element);

						// Add the window footer.
						//content.appendChild(this.createWindowFooter(component));

						return content;
					}; // auto.createErrorView = function (component, value, xml)

				// This method creates the no suggestions view.
				auto.createNoSuggestionsView = function (component, value, xml)
					{	// Create the content.
						var content			= document.createElement("div");
						content.className	= "content no_results";

						// Add the window footer.
						content.appendChild(this.createWindowFooter(component));
					
						var element			= document.createElement("h2");

						// Sanitize the value.
						value = value.replace(/</g, "&lt;");
						value = value.replace(/>/g, "&gt;");						

						content.appendChild(element);

						element				= document.createElement("p");
						element.innerHTML	= "Perhaps you spelled it incorrectly?";
						content.appendChild(element)

						// Add the window footer.
						//content.appendChild(this.createWindowFooter(component));

						return content;
					}; // auto.createNoSuggestionsView = function (component, value, xml)

				// This method creates the suggestion view.
				auto.createSuggestionsView = function (component, value, xml, suggestions)
					{	// Get the resources.
						var res			= xml.getElementsByTagName("resource");
						var resources	= new Array();

						// Sanitize the value.
						value = value.replace(/</g, "&lt;");
						value = value.replace(/>/g, "&gt;");

						// Extract the resources.
						for ( var index = 0; index < res.length; index++ )
							{	// Get the next resource.
								var resource = res.item(index);

								// Get the resource value.
								var res_value = resource.firstChild ? resource.firstChild.nodeValue : "";

								// Add it to the list.
								resources[resource.getAttribute("resid")] = res_value;
							}; // for ( var index = 0; index < res.length; index++ )

						// Get the title (if provided).
						var title	= xml.getElementsByTagName("title");

						if ( title && title.length >= 1 && title.item(0).firstChild && title.item(0).parentNode.nodeName == "suggestions" )
							{	title		= title.item(0).firstChild.nodeValue;
								title		= title.replace(/\[h2\]/, "<h2>");
								title		= title.replace(/\[\/h2\]/, "</h2>");
								title		= title.replace(/\[p\]/, "<p>");
								title		= title.replace(/\[\/p\]/, "</p>");
							} // if ( title && title.length >= 1 && title.item(0).firstChild && title.item(0).parentNode.nodeName == "suggestions" )

						else 
							{	title = "<h2>Search Suggestions</h2>";
							};
						
						// Add the header.
						var content 		= document.createElement("div");
						content.className	= "content";

						// Add the window footer.
						content.appendChild(this.createWindowFooter(component));

						var element			= document.createElement("div");
						element.className	= "title";
						element.innerHTML	= title;
						content.appendChild(element);

						// Add the Search History blurb.
						if ( this.ref_id == "search_history" )
							{	var blurb		= document.createElement("p");
								blurb.innerHTML	= value.replace(/^\s+|\s+$/g, "")  == "" ? "Words you have searched:" : 'Words you have searched that match "' + value + '":';								
								content.appendChild(blurb);
							} // if ( this.ref_id == "search_history" )

						// Add the My Dictionary blurb.
						else if ( this.ref_id == "mydict" )
							{	var blurb		= document.createElement("p");
								blurb.innerHTML	= value.replace(/^\s+|\s+$/g, "")  == "" ? "Your saved words:" : 'Your saved words that match "' + value + '":';								
								content.appendChild(blurb);
							} // else if ( this.ref_id == "mydict" )

						// Add the 3,000 Words blurb.
						else if ( this.ref_id == "words3k" )
							{	var blurb		= document.createElement("p");
								blurb.innerHTML	= value.replace(/^\s+|\s+$/g, "")  == "" ? "Important words to learn:" : 'Important words to learn that match "' + value + '":';								
								content.appendChild(blurb);
							} // else if ( this.ref_id == "words3k" )

						// Add the Learner's blurb.
						else if ( this.ref_id == "learners" )
							{	var blurb		= document.createElement("p");
								blurb.innerHTML	= value.replace(/^\s+|\s+$/g, "")  == "" ? "Words in the Learner's Dictionary:" : 'Words that match "' + value + '" in the Learner\'s Dictionary:';								
								content.appendChild(blurb);
							}; // else if ( this.ref_id == "learners" )

						// Determine whether the list is mutable.
						var actions	= xml.getElementsByTagName("action");

						// @del, var mutable = actions.length > 0;
						var mutable	= this.ref_id != "learners"; // actions.length > 0;

						// Create the suggestion box.
						element				= document.createElement("ol");
						element.className	= "results";

						// The current suggestion index.
						var index = 0;

						// Add each term.
						while ( suggestions.hasMoreElements() )
							{	// Get the next suggestion.
								var suggestion = suggestions.next(); 

								// Get the next term.
								var term = suggestion["title"];

								// Remove homograph indices.
								term = term.replace(/\{[^\}]\}$/, "");

								// Create the list item.
								var item		= document.createElement("li");
								item.className	= "suggestion_" + index++;

								// This list is mutable.
								if ( mutable )
									{	// This item is active; therefore, add a checkbox.
										if ( suggestion.active )
											{	var link			= document.createElement("a");
												link.href			= "";												
												link.className		= "image_action";
												link.item_id		= suggestion.id;
												link.item_action	= suggestion.action;
												link.item_target	= suggestion.target;
												link.item_dims		= suggestion.dims;
												link.peer			= this;
												link.onclick		= 
													function () 
														{	// Perform the action.
															if ( this.item_id != "" )
																{	// Open the target in a new window.
																	if ( this.item_target != "this" )
																		{	this.peer.openTarget(this.item_action, this.item_target, this.item_dims[0], this.item_dims[1]);
																		} // if ( this.item_target != "this" )

																	// Display the error message.
																	else if ( !my_dict_logged_in )
																		{	// Get the existing bubble.
																			var bubble = document.getElementById("auto_bubble");

																			// The bubble doesn't exist; therefore, create it.
																			if ( !bubble )
																				{	bubble					= document.createElement("div");																					
																					bubble.id				= "auto_bubble";																					
																					bubble.onmouseout		= function () { this.style.display = "none"; };
																				}; // if ( !bubble )

																			// Add the bubble.
																			this.parentNode.insertBefore(bubble, this);

																			// Show the bubble.
																			bubble.style.display = "block";										
																		} // else if ( !my_dict_logged_in )

																	// Process it via AJAX.
																	else 
																		{	this.peer.process(this.item_action, query); 
																		}; // else
																}; // if ( this.item_id != "" )

															 return false; 
														};
												var img			= document.createElement("img");
												img.src			= resources["active-icon"] ? resources["active-icon"] : "icon_active_item.gif";
												link.appendChild(img);
												item.appendChild(link);
											} // if ( suggestion.active )

										// This item is inactive; therefore, exclude a checkbox for it.
										else
											{	var img		= document.createElement("img");
												img.src		= resources["inactive-icon"] ? resources["inactive-icon"] : "icon_inactive_item.gif";
												item.appendChild(img);
											}; // else
									}; // if ( mutable )

								// Create the hyperlink.
								var anchor 			= document.createElement("a");
								anchor.href			= suggestion.url; // "/search/" + suggestion.url;
								anchor.value		= "";
								anchor.rel			= suggestion.id;
								anchor.search_term	= this;
								anchor.popup		= component;
								anchor.innerHTML	= term;

								// Make this suggestion draggable.
								if ( this.ref_id == "mydict" || this.ref_id == "search_history" || this.ref_id == "words3k" )
									{	// Create the transform to be applied.
										var transform = new SnapToTransform(10);

										// Set the object's onclick event.
										anchor.onclick = function (event) { this.parentNode.removeChild(this); document.location.href = this.href; return true; };

										// Setup the on drag released.
										anchor.onDragReleased = function ()
											{	// Get any transform the drag object may have defined.
												var transform = this.getDragProperties().getTransform();

												// Apply the transform.
												if ( transform )
													{	// Reset the transform.
														transform.reset();

														// Set the node to be transformed.
														transform.setNode(this);

														// Now tell it to start transforming the drag object.
														transform.start();
													}; // if ( transform )
											};

										// Set the on drop event.
										anchor.onDropTarget = function (drop_target)
											{	this.parentNode.removeChild(this);
											}; // link.onDropTarget = function (drop_target)

										anchor.onEndTransform = function (transform)
											{	this.parentNode.removeChild(this);
											}; 

										// Create the drag object.
										DragClass.createDragObject(anchor, new DragProperties(false, .5, true, transform, 10));

										// Add the drag value.
										anchor.getDragValue = function () { return this.rel; };
									}; // if ( this.ref_id == "mydict" )

								// Add the item.
								item.appendChild(anchor);
								element.appendChild(item);
							}; // while ( suggestions.hasMoreElements() )

						// Append the list.
						content.appendChild(element);

						// Create the action buttons.
						if ( mutable )
							{	// Create the tool panel.
								var tools			= document.createElement("ol");
								tools.className		= "tools";

								// Get the query.
								var query	= xml.getElementsByTagName("query");
								query		= query.length > 0 ? query.item(0) : false;
								query		= query && query.firstChild ? query.firstChild.nodeValue : "";

								// Create a link for each action.
								for ( var index = 0; index < actions.length; index++ )
									{	// Get the action, it's label and it's href.
										var action	= actions.item(index);
										var label	= "" + ( action.firstChild ? action.firstChild.nodeValue : "" );										
										label		= label.replace(/^\s+|\s+$/g, "");
										label		= label.replace(/</g, "&lt;");
										label		= label.replace(/>/g, "&gt;");
										var href	= action.getAttribute("href").replace(/\&#38;/g, "&");
										var action_id	= "" + action.getAttribute("id");
										var target	= action.attributes["target"] ? action.attributes["target"].nodeValue : action.getAttribute("target");
										var dims	= action.attributes["dims"] ? action.attributes["dims"].nodeValue : action.getAttribute("dims");
										dims		= dims == null ? "" : dims;
										var width	= dims.indexOf(",") >= 0 ? dims.replace(/,[^$]*$/, "") : "400";
										width		= width.replace(/^\s+|\s+$/g, "");
										var height	= dims.indexOf(",") >= 0 ? dims.replace(/^[^,]*,/, "") : "400";
										height		= height.replace(/^\s+|\s+$/g, "");
										dims		= new Array(width, height);
										var icon	= action.getAttribute("icon") ? action.getAttribute("icon") : "";										

										// The action has a label; therefore, display it.
										if ( label )
											{	var item			= document.createElement("li");
												item.className		= "action-" + action_id;
												var tool			= document.createElement("a");
												tool.href			= href;
												tool.target			= target;
												tool.dims			= dims;
												tool.innerHTML		= icon != "" ? ( "<img src=\"" + icon + "\" alt=\"" + label + "\" align=\"top\" />" ) : "" + label;
												tool.peer			= this;
												tool.query			= query;
												tool.onclick		= function () 
																		{	// Open the target in a new window.
																			if ( this.target != "this" )
																				{	this.peer.openTarget(this.href, this.target, this.dims[0], this.dims[1]);
																				} // if ( this.target != "this" )

																			// Process it via AJAX.
																			else 
																				{	this.peer.process(this.href, query); 
																				}; // else

																			 return false; 
																		};
												item.appendChild(tool);
												tools.appendChild(item);
											}; // if ( label )
									}; // for ( var index = 0; index < actions.length; index++ )

								// Add the tools panel to the component.
								content.appendChild(tools);
							}; // if ( mutable )
						
						// Add the window footer.
						//content.appendChild(this.createWindowFooter(component));

						return content;
					}; // auto.createSuggestionsView = function (component, value, xml, suggestions)

				// This method creates this component's view from the XML data.
				auto.createView = function (component, ref_id, value, xml)
					{	// Perform the auto-complete.
						if ( component )
							{	// Display the component.
								component.style.display = "inline";

								// Set the component's peer.
								component.peer = this;

								// Get the campaign id.
								var campaign_id = xml.getElementsByTagName("campaign");
								campaign_id		= campaign_id && campaign_id.length > 0 ? campaign_id.item(0) : false;
								campaign_id		= campaign_id && campaign_id.firstChild ? campaign_id.firstChild.nodeValue : "default";

								// Set the component's CSS class name based on the campaign id.
								component.className = campaign_id;

								// Add the popup background.
								if ( !this.bkg )
									{	var bkg					= document.createElement("div");
										bkg.className			= "bkg";										
										component.appendChild(this.bkg = bkg);
									}; // if ( !this.bkg )

								// Remove the previous content.
								if ( this.content )
									{	component.removeChild(this.content);
									}; // if ( this.content )

								// Create an iterator to access the data.
								suggestions = new SuggestionIterator(xml);

								// The suggestion headwords.
								var values = new Array();

								// Get all the suggestions.
								while ( suggestions.hasMoreElements() )
									{	var suggestion					= suggestions.next();
										values[values.length]			= {};
										values[values.length - 1].title	= suggestion.title;
										values[values.length - 1].url	= suggestion.url;
									}; // while ( suggestions.hasMoreElements() )

								// Reset the suggestions.
								suggestions.reset();

								// Set the current suggestion.
								component.suggestions	= values;
								component.curr_index	= -1;

								// The content.
								var content = false;
								
								// Create the suggestions view.
								if ( suggestions.hasMoreElements() )
									{	// This method selects the next suggestion.
										component.nextSuggestion = function ()
											{	this.peer.setEnabled(false);												
												this.curr_index = ++this.curr_index >= this.suggestions.length ? 0 : this.curr_index;												
												this.link		= this.suggestions[this.curr_index].url;
												//this.peer.value = this.suggestions[this.curr_index].title.replace(/\s*\([^\)]*\)\s*$/, "");
												this.peer.setEnabled(true);
												if ( this.peer.content )
													{	var className				= this.peer.content.className;
														className					= className.replace(/((^|\s+)suggestion_\d+)?(\s+|$)/, " suggestion_" + this.curr_index + "$3");
														className					= className.replace(/^\s+|\s+$/g, "");
														this.peer.content.className	= className;
													}; // if ( this.peer.content )
											}; // component.nextSuggestion 

										// This method selects the previous suggestion.
										component.prevSuggestion = function ()
											{	this.peer.setEnabled(false);
												this.curr_index = --this.curr_index < 0 ? Math.max(0, this.suggestions.length - 1) : this.curr_index;
												this.link		= this.suggestions[this.curr_index].url;
												//this.peer.value = this.suggestions[this.curr_index].title.replace(/\s*\([^\)]*\)\s*$/, "");
												this.peer.setEnabled(true);
												if ( this.peer.content )
													{	var className				= this.peer.content.className;
														className					= className.replace(/((^|\s+)suggestion_\d+)?(\s+|$)/, " suggestion_" + this.curr_index + "$3");
														className					= className.replace(/^\s+|\s+$/g, "");
														this.peer.content.className	= className;
													}; // if ( this.peer.content )
											}; // component.prevSuggestion 
											
										// Create the view.
										content = this.createSuggestionsView(component, value, xml, suggestions);
									} // if ( suggestions.hasMoreElements() )

								// Create the no suggestions view.
								else if ( xml.getElementsByTagName("error").length == 0 )
									{	content = this.createNoSuggestionsView(component, value, xml);
									} // else if ( xml.getElementsByTagName("error").length == 0 )

								// Create the error view.
								else
									{	content = this.createErrorView(component, value, xml);
									}; // else

								// Add the content.
								component.appendChild(this.content = content);				

								// Set the component's class name.
								component.className = component.className + " view_" + ref_id;

								// Set the component.
								this.component = component;

								// Get the iframe.
								var auto_complete_iframe = document.getElementById("auto_complete_iframe");

								// Determine if this is IE 6 or under.
								var is_IE_6 = false;
								
								// This appears to be Internet Explorer.
								if ( navigator.appVersion.indexOf("MSIE") != -1 )
									{	var temp	= navigator.appVersion.split("MSIE");
										var version	= parseFloat(temp[1]);
										is_IE_6		= version < 7.0 && version > 0;
									}; // if ( navigator.appVersion.indexOf("MSIE") != -1 )

								// Resize and position it as needed.
								if ( is_IE_6 && auto_complete_iframe )
									{	var pos = this.getAbsPos(component);
										auto_complete_iframe.style.left			= pos.left + "px";
										//auto_complete_iframe.style.top			= ( pos.top + 10 ) + "px";
										auto_complete_iframe.style.height		= Math.max(1, component.clientHeight - 10) + "px";
										auto_complete_iframe.style.width		= component.clientWidth + "px";
										auto_complete_iframe.style.display		= "block";
									}; // if ( is_IE_6 && auto_complete_iframe )
							}; // if ( component )
					}; // auto.createView = function (component, ref_id, value, xml)

				// This method creates the window's footer.
				auto.createWindowFooter = function (component)
					{	// Create the footer element.
						var element				= document.createElement("div");
						element.style.textAlign	= "right";

						// Create the diable button.
						/**
						var anchor				= document.createElement("a");
						anchor.popup			= component;
						anchor.peer				= this;
						anchor.href				= "";
						anchor.onclick			= function () { this.peer.setEnabled(false); this.popup.style.display = "none"; return false; };
						anchor.innerHTML		= "Disable";
						element.appendChild(anchor);
						**/
						
						// Create the close button.
						var anchor					= document.createElement("a");
						anchor.popup			= component;
						anchor.peer				= this;
						anchor.href				= "";
						anchor.onclick			= function () 
							{	this.popup.style.display = "none"; 
								
								var auto_complete_iframe = document.getElementById("auto_complete_iframe");

								// Determine if this is IE 6 or under.
								var is_IE_6 = false;
								
								// This appears to be Internet Explorer.
								if ( navigator.appVersion.indexOf("MSIE") != -1 )
									{	var temp	= navigator.appVersion.split("MSIE");
										var version	= parseFloat(temp[1]);
										is_IE_6		= version < 7.0 && version > 0;
									}; // if ( navigator.appVersion.indexOf("MSIE") != -1 )								

								// Hide the iframe.
								if ( is_IE_6 && auto_complete_iframe )
									{	auto_complete_iframe.style.display = "none";
									}; // if ( is_IE_6 && auto_complete_iframe )
								
								return false;
							};
						anchor.innerHTML		= "<img src=\"" + SITE_DOMAIN + "images/search_bar/button_close.jpg\" alt=\"Close\" />";
						element.appendChild(anchor);

						return element;
					}; // auto.createWindowFooter = function (component)

				// This method returns the absolute position of an element.
				auto.getAbsPos = function (element)
					{	var offsetTrail	= element;
						var offsetLeft	= 0;
						var offsetTop	= 0;

						while ( offsetTrail )
							{	offsetLeft	+= offsetTrail.offsetLeft;
								offsetTop	+= offsetTrail.offsetTop;
								offsetTrail	= offsetTrail.offsetParent;
							}; // while ( offsetTrail ) 
						
						if ( navigator.userAgent.indexOf('Mac') != -1 && typeof document.body.leftMargin != 'undefined' )
							{	offsetLeft	+= document.body.leftMargin;
								offsetTop	+= document.body.topMargin;
							}; // if ( navigator.userAgent.indexOf('Mac') != -1 && typeof document.body.leftMargin != 'undefined' ) 

						return {left:offsetLeft,top:offsetTop};
					}; // list.getAbsPos = function (element)

				// This method returns the ids of the suggestions which are currently selected.
				auto.getSelected = function ()
					{	// The selected suggestions.
						var selected = new Array();

						// Get all the inputs.
						var inputs = this.component.getElementsByTagName("input");

						// Add all the selected inputs.
						for ( var index = 0; index < inputs.length; index++ )
							{	// Add the input.
								if ( inputs.item(index).checked )
									{	selected[selected.length] = inputs.item(index).value;
									}; // if ( inputs.item(index).checked )
							}; // for ( var index = 0; index < inputs.length; index++ )

						return selected;
					}; // auto.getSelected = function ()

				// This method returns the ids of the suggestions which are currently selected in query format.
				auto.getSelectionQuery = function ()
					{	// The selected suggestions.
						var selected = this.getSelected();

						// The query value.
						var value = "";

						// Append each value.
						for ( var index = 0; index < selected.length; index++ )
							{	value += ( value != "" ? "&" : "" ) + "id[]=" + selected[index];
							}; // for ( var index = 0; index < selected.length; index++ )

						return value;
					}; // auto.getSelectionQuery = function ()

				// This method handles all AJAX success events.
				auto.onAJaxSuccess = function (http_request, callback_object, data) 
					{	// Get the reference id.
						var ref_id = data[0];
			
						// Get the auto-complete UI component.
						var component		= document.getElementById(this.display_id + "_" + ref_id);
						component			= !component ? document.getElementById(this.display_id) : component;
						this.component		= component;

						// A component exists.
						if ( component )
							{	// Get the XML data.
								var xml	= http_request.responseXML;

								// Display the content.
								this.createView(component, data[0], data[1], xml.documentElement);
							}; // if ( component )	
					}; // this.onAJaxSuccess = function (http_request, callback_object) 

				// This method handles all AJAX failure events.
				auto.onAJaxFailure = function (http_request, callback_object, data) 
					{	
					};

				// This method handles all AJAX update events.
				auto.onAJaxUpdate = function (http_request, callback_object, data) { };

				// This method handles all 0 result suggestion events.
				auto.onZeroSuggestions = function (value)
					{	// Get the auto-complete UI component.
						var component = document.getElementById(this.display_id);

						// Create the view.
						if ( component )
							{	// Display the component.
								component.style.display = "inline";
							
								// Create the popup background.
								var bkg				= document.createElement("div");
								bkg.className		= "bkg";

								// Create the content view.
								var content			= this.createZeroContent(value);

								// Clear the existing compoent content.
								component.innerHTML = "";

								// Set the new component content.
								component.appendChild(bkg);
								component.appendChild(content);
							}; // if ( component )
					}; // auto.onZeroSuggestions = function (value)				

				// This function opens a popup window to playback the pronunciation of a word.
				auto.openTarget = function (the_url, target, width, height)
					{	var aWindow = window.open(the_url, target, "toolbar=no,scrollbars=yes,status=no,resizable=yes,menubar=no,width=" + width + ",height=" + height);
					}; // function popWin (the_url)

				// This function processes a url via AJax.
				auto.process = function (the_url, query)
					{	// Make the AJAX call.
						makeAJaxRequest(the_url, "get", this, new Array(this.ref_id, query));
					}; // auto.process = function (the_url, query)

				// This method enables the auto-complete functionality.
				auto.setEnabled = function (enabled)
					{	// Flag this control as being enabled or disabled.
						this.enabled = enabled;

						// Hide this component.
						//if ( !enabled && this.component )
						//	{	this.component.style.display = "none";
						//	}; // if ( !enabled && this.component )
					}; // auto.setEnabled = function (enabled)

				// This method sets the reference id to grab suggestions from.
				auto.setReference = function (ref_id)
					{	// Set the new reference id.
						this.ref_id = ref_id;

						// Auto-complete on the new reference.
						if ( this.enabled )
							{	this.autoComplete(this.value);
							}; // if ( this.enabled )
					}; // auto.setReference = function (ref_id)

				// This method sets the URL to grab suggestions from for a particular reference.
				auto.setReferenceURL = function (ref_id, ref_url)
					{	this.ref_urls[ref_id] = ref_url;
					}; // auto.setReferenceURL = function (ref_id, ref_url)
			}; // if ( auto )

		return auto;
	}; // function setupAutoComplete (auto_id)

// ----------------------------------------------------------------------------------------------------------------

// This function sets a search reference.
function setSearchReference (ref, data)
	{	// Get the reference id.
		var search_ref_id = data[0];

		// Get the search reference input variable.
		var search_ref = document.getElementById(search_ref_id);

		// Set the new value.
		if ( search_ref )
			{	search_ref.value = ref.replace(/^tab_/, "");
			}; // if ( search_ref )

		// Set the search term input field's reference.
		if ( data[1] )
			{	// Get the input field.
				var input = document.getElementById(data[1]);

				// Set its reference.
				if ( input )
					{	input.setEnabled(true);
						input.setReference(ref.replace(/^tab_/, ""), true);
						input.focus();
					}; // if ( input )
			}; // if ( data[1] )
	}; // function setSearchReference (ref, data)

// ----------------------------------------------------------------------------------------------------------------

// This function sets up the search bar tabs.
function setupSearchBarTabs (tab_id, callback, callback_data)
	{	// Get the containing element.
		var component = document.getElementById(tab_id);

		// Set the tab events.
		if ( component )
			{	// Get each tab.
				var tabs = component.getElementsByTagName("li");

				// Get the next tab.
				for ( var index = 0; tabs && index < tabs.length; index++ )
					{	// Get the next tab.
						var tab = tabs.item(index);

						// This is a tab.
						if ( tab && tab.className && tab.className.indexOf("tab_") == 0 )
							{	// Get the tab link.
								var tab_links	= tab.getElementsByTagName("a");
								var tab_link	= tab_links.length > 0 ? tab_links.item(0) : false;

								// Set the link's event handler.
								if ( tab_link )
									{	tab_link.tab_bar		= component;
										tab_link.tab_name		= tab.className;
										tab_link.callback		= callback;
										tab_link.callback_data	= callback_data;
										tab_link.onclick		=
											function ()
												{	// Display the tab in selected mode.
													this.tab_bar.className = "tabs " + this.tab_name;

													// Invoke the callback function.
													this.callback(this.tab_name, this.callback_data);

													// Stop the browser from trying to load a page.
													return false;
												};
									}; // if ( tab_link )
							}; // if ( tab && tab.className && tab.className.indexOf("tab_") == 0 )
					}; // for ( var index = 0; tabs && index < tabs.length; index++ )
			}; // if ( component )
	}; // function setupSearchBarTabs (tab_id, callback, callback_data)

// ----------------------------------------------------------------------------------------------------------------

// This function initializes the page.
function initPage ()
	{	// Setup the flashcard app.
		initFlashcards();

		// Get the search bar form.
		var search_bar = document.getElementById("search_bar");

		// Initialize the search bar form.
		if ( search_bar )
			{	// Set the search bar's	query input id.
				search_bar.query_id	= "search_term";

				// Set the search bars submit event handler.
				search_bar.onsubmit = 
					function () 
						{	document.location = "/search/" + document.getElementById(this.query_id).value; 
							return false;
						};
			}; // if ( search_bar )
	
		// Setup the auto-complete form.
		var auto = setupAutoComplete("search_term", "auto_complete");

		// Override the method that creates the content for 0 result queries.
		auto.createNoSuggestionsView = function (component, value, xml)
			{	// Sanitize the value.
				value = value.replace(/</g, "&lt;");
				value = value.replace(/>/g, "&gt;");	
				value = value.replace(/^\s+|\s+$/g, "");
			
				var content			= document.createElement("div");
				content.className	= "content no_results";

				// Add the window footer.
				content.appendChild(this.createWindowFooter(component));

				// Create the title.
				var element			= document.createElement("div");
				element.className	= "title";

				// Set the title for the Learner's Dictionary.
				if ( this.ref_id == "learners" )
					{	element.innerHTML = "<h2>Search Suggestions</h2>";
					} // if ( this.ref_id == "learners" )

				// Set the title for My Dictionary.
				else if ( this.ref_id == "mydict" )
					{	element.innerHTML = "<h2>Words in &quot;My Dictionary&quot;</h2>";
					} // else if ( this.ref_id == "mydict" )

				// Set the title for the Search History.
				else if ( this.ref_id == "search_history" )
					{	element.innerHTML = "<h2>My Search History...<p>(add to &quot;My Dictionary&quot;)</p></h2>";
					} // else if ( this.ref_id == "search_history" )

				// Set the title for the 3,000 Words list.
				else if ( this.ref_id == "words3k" )
					{	element.innerHTML = "<h2>&quot;3,000 Words&quot; List<p>(add to &quot;My Dictionary&quot;)</p></h2>";
					}; // else if ( this.ref_id == "words3k" )

				content.appendChild(element);

				// The blurb to add.
				var blurb = "";
				
				// Set the blurb content for the Learner's Dictionary.
				if ( this.ref_id == "learners" )
					{	blurb = "There are no words in the Learner's Dictionary that match \"" + value + "\".";
					} // if ( this.ref_id == "learners" )

				// Set the blurb content for My Dictionary.
				else if ( this.ref_id == "mydict" )
					{	blurb = 
							( value == "" ?
								"There are no words saved in My Dictionary." : 
								"There are no words saved in My Dictionary that match \"" + value + "\"."
							);
					} // else if ( this.ref_id == "mydict" )

				// Set the blurb content for the Search History.
				else if ( this.ref_id == "search_history" )
					{	blurb = 
							( value == "" ?
								"There are no words in your Search History.</p>" : 
								"There are no words in your Search History that match \"" + value + "\"."
							);
					} // else if ( this.ref_id == "search_history" )

				// Set the blurb content for the 3,000 Words list.
				else if ( this.ref_id == "words3k" )
					{	blurb = "There are no words in the 3,000 Words list that match \"" + value + "\".";
					}; // else if ( this.ref_id == "words3k" )

				// Add the blurb.
				element				= document.createElement("p");
				element.className	= "blurb";
				element.innerHTML	= blurb;
				content.appendChild(element);

				// Add the window footer.
				//content.appendChild(this.createWindowFooter(component));

				return content;
			}; // auto.createNoSuggestionsView = function (component, value, xml)

		// Setup the reference URLs.
		auto.setReferenceURL("learners", SITE_DOMAIN + "suggestions/suggestions.php?query={query}");
		auto.setReferenceURL("mydict", SITE_DOMAIN + "term_suggest.php?src=mydict&query={query}");
		auto.setReferenceURL("search_history", SITE_DOMAIN + "term_suggest.php?src=search_history&query={query}");
		auto.setReferenceURL("words3k", SITE_DOMAIN + "term_suggest.php?src=3kwords&query={query}");

		// Set the current reference.
		auto.setReference("learners");

		// Enable the control.
		auto.setEnabled(true);

		// Setup the search bar tabs.
		setupSearchBarTabs("search_bar_tabs", setSearchReference, Array("search_ref", "search_term"));

		// Add menu items when a user is logged in.
		if ( my_dict_logged_in )
			{	// Get the menu item to add menus to the right of.
				var menu_item = document.getElementById("right_nav_item");

				// Add each menu item.
				if ( menu_item )
					{	// Create a new menu item.
						var item	= document.createElement("li");
						var anchor	= document.createElement("a");
						anchor.href	= "/register/term_view.php";
						var img		= document.createElement("img");
						img.src		= "/register/images/menu_bar/button_my_dict.jpg";
						img.alt		= "My Dictionary";
						anchor.appendChild(img);
						item.appendChild(anchor);
						menu_item.parentNode.insertBefore(item, menu_item);
					}; // if ( menu_item )				
			}; // if ( my_dict_logged_in ))

		// Hide the promo.
		if ( !my_dict_logged_in )
			{	document.getElementsByTagName("body").item(0).className = "logged_out";
			}; // if ( !my_dict_logged_in )
	}; // function initPage ()

// This function initializes the flashcard application.
function initFlashcards ()
	{	// Initialize the flashcards.
		if ( document.getElementById("flashcard") )
			{	document.getElementById("flashcard").init();

				if ( DropClass )
					{	DropClass.createDropObject(document.getElementById("flashcard"));
					}; // if ( DropClass )
			}; // if ( document.getElementById("flashcard") )

		// Create the drop object.
		if ( DropClass )
			{	// Create the draggable objects.
				createDraggableObjects();
			}; // if ( DropClass )
	}; // function initFlashcards ()

// This function initialzes the page.
function createDraggableObjects ()
	{	// Get all the page links.
		var page_links = document.getElementsByTagName("a");

		// Create the transform to be applied.
		var transform = new SnapToTransform(10);

		// Modify all the draggable ones.
		for ( var index = 0; index < page_links.length; index++ )
			{	// Get the link.
				var link = page_links.item(index);

				// Modify it.
				if ( link.className == "word" )
					{	// Set the object's onclick event.
						link.onclick = function (event) { this.parentNode.removeChild(this); document.location.href = this.href; return true; };

						// Setup the on drag released.
						link.onDragReleased = function ()
							{	// Get any transform the drag object may have defined.
								var transform = this.getDragProperties().getTransform();

								// Apply the transform.
								if ( transform )
									{	// Reset the transform.
										transform.reset();

										// Set the node to be transformed.
										transform.setNode(this);

										// Now tell it to start transforming the drag object.
										transform.start();
									}; // if ( transform )
							};

						// Set the on drop event.
						link.onDropTarget = function (drop_target)
							{	this.parentNode.removeChild(this);
							}; // link.onDropTarget = function (drop_target)

						link.onEndTransform = function (transform)
							{	this.parentNode.removeChild(this);
							}; 

						// Create the drag object.
						DragClass.createDragObject(link, new DragProperties(false, .5, true, transform, 10));

						// Add the drag value.
						link.getDragValue = function () { return this.rel; };
					}; // if ( link.className == "word" )
			}; // for ( var index = 0; index < page_links.length; index++ )
	}; // function createDraggableObjects ()	

			// This function plays an audio pron.
			function playAudio (filename, word)
				{	var aWindow = 
						window.open
							(	"/pron_listen.php?audio=" + escape(filename) + "&word=" + escape(word), 
								"pron_window",
								"toolbar=no,scrollbars=yes,status=no,resizable=yes,menubar=no,width=650,height=440"
							);
				}; // function playAudio (filename, word)

// This function opens a popup window to playback the pronunciation of a word.
function popWin (the_url, target, width, height)
		{	var aWindow = window.open(the_url, target, "toolbar=no,scrollbars=yes,status=no,resizable=yes,menubar=no,width=" + width + ",height=" + height);
		}; // function popWin (the_url)


// *** Signin Code *** //
// A set of browser utility functions.
			var BrowserUtils = 
				{	// This method returns the document's height.
					getDocumentHeight: function ()
						{	// Get the template's height.
							var height		= this.getStyle(document.getElementById("template"), "height");
							height			= height.replace(/px$/, "");	
							height			= height == "auto" && document.body.clientHeight ? document.body.clientHeight : height; 
							height			= document.body.clientHeight && document.body.clientHeight > height ? document.body.clientHeight : height;

							// Get the window's height.
							var win_height = this.getWindowHeight();

							// Get the maximum of the two.
							var doc_height	= height > win_height ? height : win_height;

							return doc_height;
						}, // function getDocumentHeight ()

					// This method returns the document's width.
					getDocumentWidth: function ()
						{	// Get the template's width.
							var width		= this.getStyle(document.getElementById("template"), "width");
							width			= width.replace(/px$/, "");					
							width			= width == "auto" && document.body.clientWidth ? document.body.clientWidth : width; 
							width			= document.body.clientWidth && document.body.clientWidth > width ? document.body.clientWidth : width;

							// Get the window's width.
							var win_width	= this.getWindowWidth();

							// Get the maximum of the two.
							var doc_width	= width > win_width ? width : win_width;

							return doc_width;
						}, // function getDocumentWidth ()
				
					// This method returns the height of an XHTML element.
					getElementHeight: function (element)
						{	// Get the style.
							var dimension = this.getStyle(element, "height").replace(/px$/i, "");

							// The style is set to auto so get the actual value.
							dimension		= dimension == "auto" ? element.offsetHeight : dimension;

							return dimension;
						}, // function getElementHeight (element)
				
					// This method returns the width of an XHTML element.
					getElementWidth: function (element)
						{	// Get the style.
							var dimension = this.getStyle(element, "width").replace(/px$/i, "");

							// The style is set to auto so get the actual value.
							dimension		= dimension == "auto" ? element.offsetWidth : dimension;

							return dimension;
						}, // function getElementWidth (element)
				
					// This method returns the window's left scroll position.
					getScrollLeft: function () 
						{	return document.documentElement.scrollLeft;
						}, // function getScrollLeft() 

					// This method returns the window's top scroll position.
					getScrollTop: function () 
						{	return document.documentElement.scrollTop;
						}, // function getScrollTop () 

					// This method returns a computed CSS style attribute value for a specified XHTML element.
					getStyle: function (element, style_attrib)
						{	// The CSS style attribute value.
							var strValue = "";

							if ( element )
								{	if ( document.defaultView && document.defaultView.getComputedStyle )
										{	strValue = document.defaultView.getComputedStyle(element, "").getPropertyValue(style_attrib);
										} // if ( document.defaultView && document.defaultView.getComputedStyle )

									else if ( element.currentStyle )
										{	attribute	= style_attrib.replace(/\-(\w)/g, function (strMatch, p1) {return p1.toUpperCase();});
											strValue	= element.currentStyle[attribute];
										}; // else if ( element.currentStyle )
								}; // if ( element )

							return strValue;
						}, // function getStyle (element, attribute)
				
					// This method returns the height of the browser window.
					getWindowHeight: function () 
						{	return window.innerHeight ? window.innerHeight : document.documentElement.clientHeight;
						}, // function getClientHeight () 

					// This method returns the width of the browser window.
					getWindowWidth: function () 
						{	return window.innerWidth ? window.innerWidth : document.documentElement.clientWidth;
						}, // function getClientWidth (),

					// This function returns the viewport.						
					getViewport: function ()
						{	// Get the window dimensions.
							var win_width	= this.getWindowWidth();
							var win_height	= this.getWindowHeight();

							// Get the scroll position.
							var scroll_x	= this.getScrollLeft();
							var scroll_y	= this.getScrollTop();

							// Create the viewport structure.
							var viewport = { left: scroll_x, top: scroll_y, right: scroll_x + win_width, bottom: scroll_y + win_height, width: win_width, height: win_height };

							return viewport;
						} // function getViewport ()
				}; 		

		// Constructor for the WindowOverlayGadget object class.
		function WindowOverlayGadget (gid, config)
			{	// Create the window.
				var peer = document.createElement("div");

				// Initialize it.
				peer.id		= gid;
				peer.dialog	= null;

				// Add it to the document.
				document.getElementsByTagName("body").item(0).appendChild(peer);

				// This method hides the overlay.
				peer.hide = function ()
					{	// Hide ourself.
						this.style.display = "none";

						// Hide the dialog.
						if ( this.dialog != null )
							{	// Remove the dialog from its parent.
								if ( this.dialog.parentNode )
									{	this.dialog.parentNode.removeChild(this.dialog);
									}; // if ( this.dialog.parentNode )

								// Hide the dialog.
								this.dialog.style.display = "none";
							}; // if ( this.dialog != null )

						// Clear the dialog.
						this.dialog	= null;
					}; // peer hide ()

				// This method sets the dialog appearing on the overlay.
				peer.setDialog = function (dialog)
					{	// Save the dialog.
						document.getElementsByTagName("body").item(0).appendChild(this.dialog = dialog);

						// Place it on top of the overlay.						
						dialog.style.position	= ( BrowserUtils.getStyle(this, "position") != "fixed" ) ? "absolute" : "fixed";
						var zIndex				= BrowserUtils.getStyle(this, "z-index");
						zIndex					= zIndex == "undefined" ? "10000" : zIndex;
						dialog.style.zIndex		= zIndex + 1;
						dialog.style.display	= "block";

						// Update the overlay.
						this.update();
					}; // function setDialog (dialog)

				// This method shows the overlay.
				peer.show = function ()
					{	// Update this component.
						this.update();

						// Display it.
						this.style.display = "block";
					}; // peer show ()

				// This method updates the window's dimensions.
				peer.update = function ()
					{	// Set the new dimensions.
						if ( BrowserUtils.getStyle(this, "position") != "fixed" )
							{	this.style.height	= BrowserUtils.getDocumentHeight() + "px";
								this.style.width	= BrowserUtils.getDocumentWidth() + "px";
							}; // if ( BrowserUtils.getStyle(this, "position") != "fixed" )

						// Move the dialog accordingly.
						if ( this.dialog != null )
							{	// Get the viewport.
								var viewport	= BrowserUtils.getViewport();

								// Clear the viewport top-left-most coordinates since a fixed position is being used.
								if ( BrowserUtils.getStyle(this, "position") == "fixed" )
									{	viewport.left	= 0;
										viewport.top	= 0;
									}; // if ( BrowserUtils.getStyle(this, "position") == "fixed" )

								// Get the dialog dimension.
								var dia_width	= BrowserUtils.getElementWidth(this.dialog);
								var dia_height	= BrowserUtils.getElementHeight(this.dialog);

								// Compute the new coordinates.
								var x	= viewport.left + Math.floor((viewport.width - dia_width) / 2.0);
								var y	= viewport.top + Math.floor((viewport.height - dia_height) / 2.0);

								// Set the new dimensions.
								this.dialog.style.left	= x + "px";
								this.dialog.style.top	= y + "px";
							}; // if ( this.dialog != null )
					}; // peer update ()

				// Get the current window event handlers.
				var resize_handler	= window.onresize;
				var scroll_handler	= window.onscroll;

				// Set the new window resize handler.
				window.onresize = function ()
					{	// Update the window overlay component.
						peer.update();

						// Call the existing handler.
						if ( resize_handler )
							{	return resize_handler();
							} // if ( resize_handler )

						// Return success.
						else
							{	return true;
							}; // else
					}; // function onresize ()

				// Set the new window scroll handler.
				window.onscroll = function ()
					{	// Update the window overlay component.
						peer.update();

						// Call the existing handler.
						if ( scroll_handler )
							{	return scroll_handler();
							} // if ( scroll_handler )

						// Return success.
						else
							{	return true;
							}; // else
					}; // function onscroll ()

				return peer;
			}; // function WindowOverlayGadget (gid, config)

		// Constructor for the the WindowOverlay static object class.
		var WindowOverlay =
			{	// This method returns the overlay component.
				getOverlay: function ()
					{	// Get the component.
						var component = document.getElementById("window_overlay");

						// No component exists yet; therefore, create it now.
						if ( !component )
							{	component = new WindowOverlayGadget("window_overlay");
							}; // if ( !component )

						return component;
					}, // function getOverlay ()

				// This method hides the overlay.
				hide: function ()
					{	// Get the overlay.
						var overlay = WindowOverlay.getOverlay();

						// Tell it to hide itself.
						overlay.hide();
					}, // function hide ()

				// This method displays the overlay.
				show: function ()
					{	// Get the overlay.
						var overlay = WindowOverlay.getOverlay();

						// Tell it to show itself.
						overlay.show();
					} // function show ()
			}; // class WindowOverlay


		// This function opens a SignInDialogGadget static object class.
		var SignInDialogGadget =
			{	// The peer.
				peer: null,

				// The redirect URL.
				redirect: null,
			
				// This method returns the dialog component.
				getComponent: function ()
					{	// Get the existing window.
						var dialog = SignInDialogGadget.peer != null ? SignInDialogGadget.peer : document.getElementById("signin_win_form");

						// No window exists; therefore, create it now.
						if ( !dialog )
							{	// Create the signin dialog.
								dialog = document.createElement("div");

								// Set the form's id.
								dialog.id = "signin_win_form";

								// This method handles all successful logins.
								dialog.onLogin = function ()
									{	if ( SignInDialogGadget.getRedirect() != null )
											{	document.location = SignInDialogGadget.getRedirect();
											} // if ( SignInDialogGadget.getRedirect() != null )
										else
											{	document.location.reload(true);
											}; // else										
									};

								// This method handles all failed logins.
								dialog.onLoginError = function ()
									{	alert("Invalid username or password. Please re-enter the values and try again.");
									}, // function onLoginError

								// Set its content.
								dialog.innerHTML = 
									'<form action="/signin.php" method="post" enctype="multipart/form-data" target="signin_frame">' +
										'<div class="interface">' +
											'<input type="image" value="Cancel" src="/images/hdr_box_log_in_in_closex.png" style="float:right;padding:10px 20px 10px 0;" onclick="SignInDialogGadget.hide(); return false;" />' +
										'</div>' + 
										'<div class="inputs" align="center">' +
											'<dl>' +
												'<dt><label for="signin_email">Email:</label></dt>' +
												'<dd><input id="signin_email" name="username" type="text" value="" class="text_field" /></dd>' +
												'<dt><label for="signin_password">Password:</label></dt>' +
												'<dd><input id="signin_password" name="password" type="password" value="" class="text_field" /></dd>' +
											'</dl>' +
											//'<input name="url" type="hidden" value="' + document.location + '" />' +
											//'<a href="/signup.php" style="float: right; padding-right: 10px;" ><img src="/images/button_join.gif" /></a>' + \
											'<div style="margin:-8px 0 0 60px;width:200px;">' +
												'<input type="image" value="Login" src="/images/btn_registration_ok.gif" /> ' + 
												'<p>Not yet a member? <a style="color:#3366cc;" href="/signup.php">Sign up now</a></p>' +
											'</div>' +
										'</div>' +
									'</form>' + 
									'<iframe id="signin_frame" name="signin_frame" style="border: 0; display: block; height: 0; width: 0;"></iframe>';
							}; // if ( !dialog )

						// Set the peer.
						SignInDialogGadget.peer = dialog;

						return dialog;
					}, // function getComponent ()

				// This method returns the redirect URL.
				getRedirect: function ()
					{	return SignInDialogGadget.redirect;
					}, // function getRedirect (url)
			
				// This method hides the sign-in dialog.
				hide: function ()
					{	// Show the window overlay.
						WindowOverlay.hide();

						// Reset the redirect.
						SignInDialogGadget.setRedirect(null);
					}, // function hide ()

				// This method sets the redirect URL.
				setRedirect: function (url)
					{	SignInDialogGadget.redirect = url;
					}, // function setRedirect (url)

				// This method shows the sign-in dialog.
				show: function ()
					{	// Log the user out.
						if ( my_dict_logged_in )
							{	document.location = "/loginout.php";
								return;
							}; // if ( my_dict_logged_in )
					
						// Show the window overlay.
						WindowOverlay.show();
					
						// Get the existing window.
						var dialog = SignInDialogGadget.getComponent();

						// Get the overlay.
						var overlay = WindowOverlay.getOverlay();

						// Add the our dialog.
						overlay.setDialog(dialog);	
					} // function show ()

			}; // class SignInGadget


// This function asserts that the user is currently logged in.
function assertLogin (href)
	{	if ( !my_dict_logged_in ) 
			{	SignInDialogGadget.setRedirect(href); 
				SignInDialogGadget.show(); 
				return false; 
			} 
		else 
			{	return true; 
			};
	}; // function assertLogin (href)

