﻿


// Suggestion Menu functionality
var Suggest =
{

	// This javascript file requires the Prototype library //

	// Available options 
	// remotePage - the remote page to query
	// cssClass - the class for the outer div
	// appendComma - adds a comma to the end of the list of words in the textbox
	// minWordLength - the minimum length required before the menu makes a suggestion
	// headerText - the text to display at the top of the suggestion menu

	// The Suggestion Menu class (still a work in progress)
	SuggestBox : function(textBox, options)
	{		    
		// Public variables
		this.options = options;
		
		// Initialization for the textbox. 
		textBox.setAttribute("autocomplete", "off");
		
		// Initialization for the suggestion menu.
		createSuggestionBox();
		styleSuggestionBox();
		addEventListers();
				
		// Creates the inner and outer elements for the floating suggest box.
		function createSuggestionBox()
		{
		
		    // Build the suggest box elements and attach them to the textbox
			var suggestOuter = document.createElement("div");
			var suggestInner = document.createElement("div");
				
			textBox.suggestInner = suggestInner;
			textBox.suggestOuter = suggestOuter;
			insertAfter(textBox.suggestOuter, textBox);
			suggestOuter.appendChild(suggestInner);
			
			// Hide the suggestbox elements before it is displayed
			textBox.suggestInner.style.visibility = "hidden";
			textBox.suggestOuter.style.visibility = "hidden";
	    	
    		// Add key commands to the menu.
    		Event.observe(
    						suggestInner, 
    						"keypress",
    						function(event)
    						{
    							// Handle the the up and down arrow keys. 
    							if(event.keyCode == Event.KEY_DOWN || event.keyCode == Event.KEY_UP)
    							{   
    							    toggleBox("visible");
    								menuSelect(event);
    							}
	    						
    							// Stops the page from scrolling.
    							Event.stop(event);
    						}
    					)
    		
    		// added so that the suggest box doesn't go away if clicked			
    		Event.observe(
    						suggestInner, 
    						"click",
    						function(event)
    						{
    							toggleBox("visible");
    							Event.stop(event);
    						}
    					)
    					
    	}
	    
		// Add styles to the suggestion menu.
		function styleSuggestionBox()
		{
			if (options.cssClass)
				textBox.suggestOuter.className = options.cssClass;
		}
	    
		// Add event listeners to the suggestion menu, and to other elements on the page.
		function addEventListers()
		{   
			// Add event listeners to the textbox
			Event.observe
			(
				textBox, 
				"keyup", 
				function(event)
				{ 
					// Don't make a suggestion if an item was just selected from the suggestion menu.
					if (event.keyCode == Event.KEY_RETURN || event.keyCode == Event.KEY_TAB)
						Event.stop(event);
					else
						suggest(); 
				}
			);
				
			Event.observe
			(
				textBox, 
				"keypress", 
				function(event)
				{ 
					// Handle up and down arrow keys.
					if(event.keyCode == Event.KEY_DOWN || event.keyCode == Event.KEY_UP )
					{
					    try
					    {
						    menuSelect(event);
						}
						
						catch (e) 
						{
						    textBox.focus();
						}
					}
						
					// Handle the escape key.
					if(event.keyCode == Event.KEY_ESC)
					{
						toggleBox("hidden");
						textBox.focus();
					}
				}
			)
			
			// Hide the suggest if the page is clicked
			Event.observe(document,"click", function(event) { toggleBox("hidden"); });
			
			// Hide the suggest if an iframe is clicked (tiny mce editors)
			
			var iframes = $A(document.getElementsByTagName("iframe"));
			iframes.each(
			                function(element)
							{
								var iframeDocument = element.contentWindow || element.contentDocument;
                                if (iframeDocument.document) { iframeDocument = iframeDocument.document; }
                                Event.observe(iframeDocument,"click", function(event) { toggleBox("hidden"); });
							}
						)
		}
	   
		// This function will get the last word from the textbox and
		// call a web service. The tags returned by the web service 
		// will be displayed in the suggestion box created by the
		// JavaScript in this class.
		function suggest()
		{ 
			// Set a minimum length for words to be passed to the suggestion search
			if (options.minWordLength != null)
				var minWordLength = options.minWordLength;
			else
				var minWordLength = 1;
				
			// get the last word from the textbox
			var typedWords = textBox.value;
			
			var separatedWords = typedWords.split(',');
			var lastWord = separatedWords[separatedWords.length - 1];
	        
	        // remove any white spaces from the tag
			while (lastWord.substring(0,1) == ' ') lastWord = lastWord.substring(1, lastWord.length);
	        
			// Make a suggestion if the typed word is greated than the minimum length set by minWordLength
			// Otherwise hide the suggest box
			if (lastWord.length >= minWordLength)
			{        
				// Create a variable for the other words in the box.
				var otherWords = "";
				for (i = 0; i < separatedWords.length - 1; i++) 
					otherWords += separatedWords[i] + ",";
	        	
	        	// Call the web service and send the results to suggestBoxFill
				Suggest.ajaxRequest(lastWord, suggestBoxFill, options);
			}
			
			else
				toggleBox("hidden");
		}

		// Takes the XML response from the web service and creates a UL
		// from the returned suggestions
		function suggestBoxFill(response)
		{	
			var returnedTags = $A(response.responseXML.getElementsByTagName("string"));	
	
			if (returnedTags.length > 0)
			{
				toggleBox("visible");
				textBox.suggestInner.innerHTML = "";
				
				if (options.headerText){
				    var suggestHeader = document.createElement("p");
				    suggestHeader.innerHTML = options.headerText;
				    textBox.suggestInner.appendChild(suggestHeader);
				}
			    
				var suggestionList = document.createElement("ul");
				var headerListItem = document.createElement("li");
				
				returnedTags.each
				(
					function(suggestedWord)
					{
						var suggestedTag = suggestedWord.firstChild.nodeValue;
						
						var listItem = document.createElement("li");
						var itemLink = document.createElement("a");
						
						itemLink.innerHTML = suggestedTag;
						itemLink.href = "#";
						itemLink.title = "Add \"" + suggestedTag + "\"";
						
						// Add event handling.
						Event.observe(
						    itemLink, 
						    "click", 
						    function (event) 
						    { 
						        if (options.callback)
						            options.callback(suggestedWord); 
						            
						        add(event);  
						    });
						
						Event.observe
						(
							itemLink, 
							"keypress",
							function(event)
							{ 
								// Handle the return key. 
								if (event.keyCode == Event.KEY_RETURN && options.callback || event.keyCode == Event.KEY_TAB && options.callback)
								{   
								    options.callback(suggestedWord);
								    
									add(event);
								}
								
								else if (event.keyCode == Event.KEY_RETURN || event.keyCode == Event.KEY_TAB)
								{
								    add(event);
								}
								
								else if (event.keyCode == Event.KEY_ESC) 
								{
								    textBox.focus();
								    toggleBox("hidden");
								}
								
							}
						);
												
						listItem.appendChild(itemLink);
						suggestionList.appendChild(listItem);
					}
				)
				
				textBox.suggestInner.appendChild(suggestionList);
			}
			else
				toggleBox("hidden");
		}
	    
		// Selects items inside the suggestion menu using the arrow keys.
		function menuSelect(event)
		{
			var sender = Event.element(event);
			
			// Handle the arrow down key
			if (event.keyCode == Event.KEY_DOWN)
			{
			    
				// check if this is the next box or not
				if (sender.value)
				{
					// Set the focus to the link in the first list item
					var firstListItem = textBox.suggestInner.getElementsByTagName("li")[0];
					var listItemLink = firstListItem.getElementsByTagName("a")[0];
					listItemLink.focus();
					listItemLink.className = options.highlightedClass;
				}
				else
				{
					var nextListItem = sender.parentNode.nextSibling;
					
					if (nextListItem)
					{
						var listItemLink = nextListItem.getElementsByTagName("a")[0];
						listItemLink.focus();
						
						// Set the menu item class names
						sender.className = "";
						listItemLink.className = options.highlightedClass;
					}
				}
			}
			// Handle the arrow up key
			else
			{
				var listItem = sender.parentNode;
				
				if (listItem.previousSibling)
				{
				        var previousListItemLink = listItem.previousSibling.getElementsByTagName("a")[0];
					    previousListItemLink.focus();
					
					    // Set the menu item class names
					    sender.className = "";
					    previousListItemLink.className = options.highlightedClass;
				}
			}
			
			// Stops the page from scrolling.
			Event.stop(event);
		}
	    
		// Function to add the suggested word to the suggestion box.
		function add(event)
		{   
			var clickedItem = Event.element(event);
	    	
			// Get the words that are currently typed in the textbox.
			var typedWords = textBox.value;
	    	
			// Separate the words and remove the last word.
			var separatedItems = typedWords.split(',');
			typedWords = "";
			for (i = 0; i < separatedItems.length - 1; i++) 
				typedWords += separatedItems[i] + ",";
	    	
			// Get the text for the word that was clicked on.
			var newItem = clickedItem.innerHTML; 
	    	
			// Add the word to the suggestion box.
			if (separatedItems.length > 1) 
				typedWords += " ";		
			typedWords += newItem;
			
			// Add a comma to the end of the word list in the textbox
			if (options.appendComma)
			  typedWords += ",";
			  			           
			textBox.value = typedWords;
	    	
			textBox.focus();
			toggleBox("hidden");
	    	
			// Keeps the anchor from going to another page.
			Event.stop(event);
		}
	    
		// Turns the suggestionbox on or off.
		function toggleBox(state)
		{
		    textBox.suggestOuter.style.visibility = state;
			textBox.suggestInner.style.visibility = state;
		}
	    
		// Insert a node after another node.
		function insertAfter(insertElement, previousElement)
		{
			previousElement.parentNode.insertBefore(insertElement, previousElement.nextSibling);
		}  
	},
	
	// Makes Ajax requests to the given url with parameters added on
	// ajaxResponse must be a function with one parameter that will catch
	// the response from the Ajax request
	ajaxRequest : function(lastWord, handleResponse, options)
	{   
		var parameters = "enteredText=" + lastWord;
		var ajaxOptions =
		{
			method : "GET",
			parameters : parameters,
			onSuccess : handleResponse
		}
		
		// A remote page must be set or the ajax function can't be called
		if (!options.remotePage) 
		{
			throw("A remote page was not set for the suggestBox");
		}
		else
		{
			ajaxRequest = new Ajax.Request(options.remotePage, ajaxOptions);
		}
	}
}

