﻿// Suggestion Menu functionality
var Suggest =
{
    // This javascript file requires the Prototype library //

    // Available options 
    // placeholderDivId - div to drop the other divs in
    // 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
    // selectCallback - a callback function to be called a suggestion is selected. 
    //      The suggestion will be passed to the callback function.

    // The Suggestion Menu class (still a work in progress)
    SuggestBox: function(textBox, options) {
        var me = this;

        // Public variables
        me.options = options;
        me.active = false;

        // 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, options);
            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 anddown arrow keys and the tab key. 
    						    if (event.keyCode == Event.KEY_DOWN || event.keyCode == Event.KEY_UP || event.keyCode == Event.KEY_TAB)
    						        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 (isSelectionKey(event))
				        Event.stop(event);
				    else
				        suggest();
				}
			);

            Event.observe(textBox, "focus", function(event) { me.active = true; });
            Event.observe(textBox, "blur", function(event) { me.active = false; });

            Event.observe
			(
				textBox,
				"keypress",
				function(event) {

				    // Handle up and down arrow keys.
				    if (event.keyCode == Event.KEY_DOWN || event.keyCode == Event.KEY_UP)
				        menuSelect(event);

				    // Handle the escape key.
				    if (event.keyCode == Event.KEY_ESC) {
				        toggleBox("hidden");
				        textBox.blur();
				    }
				}
			)

            // 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"); });
			                }
						)
        }

        // Returns true if the key that was pressed is a key that selects an item from the menu
        function isSelectionKey(event) {
            return event.keyCode == Event.KEY_RETURN || event.keyCode == Event.KEY_TAB;
        }

        // 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) {
            if (!me.active)
                return;

            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) { add(event); });

					    Event.observe
						(
							itemLink,
							"keypress",
							function(event) {
							    // Handle the return and tab keys. 
							    if (isSelectionKey(event))
							        add(event);
							}
						);

					    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 || event.keyCode == event.KEY_TAB) {
                // check if this is the textbox 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 += ",";

            // If overWriteAll is selected, overwrite the textbox value with the selected item
            if (options.overwriteAll)
                textBox.value = newItem;
            else
                textBox.value = typedWords;

            textBox.focus();
            toggleBox("hidden");

            // Keeps the anchor from going to another page.
            Event.stop(event);

            if (options.selectCallback)
                options.selectCallback(newItem);
        }

        // 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, options) {
            if (options.placeholderDivId) {
                var placeholdDiv = document.getElementById(options.placeholderDivId);
                previousElement.parentNode.insertBefore(insertElement, placeholdDiv);
            }
            else
                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 postBody = "text=" + lastWord;
        if (options.tagTypeId != null)
            postBody += "&tagTypeId=" + options.tagTypeId;

        var ajaxOptions =
		{
		    method: "post",
		    postBody: postBody,
		    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);
    }
}


