/*
#   Drag and drop functions
#
#   VARIABLES PROVIDED:
#       - Documention inline
#
#   FUNCTIONS PROVIDED:
#       RemoveTrailingDelimiter(Text, Delimiter)
#           - Removes a trailing delimiter from Text
#       KeyIsAlpha(Key)
#           - Determines if Key is within alpha-numeric range
#       RemoveCustomResultStyle(Result)
#           - Removes any appended classes from the result
#       RemoveCustomInputStyle(Input)
#           - Removes any appended classes from the input box
#       IsWasteful(Text)
#           - Determines if Text would be a wasteful query
#       DisableOnSubmit(Element)
#           - Disables submission
#       HandleResponseText(Response)
#           - Takes delimited response and makes it an array
#       FormatResults(Results)
#           - Takes the results array and properly formats it with HTML
#       ClearResults
#           - Clears results from the results container
#       GetMainForm
#           - Gets the containing form
#       Suggest(Element)
#           - Called to provide possible options for input
#       HandleAJAXResponse(Response, Element, Code, FieldName)
#           - Handles AJAX response from Suggest, continues Suggest function
#       SetClassification(Classification, Element, Position, FieldName)
#           - Sets the classification for the given input, show/hides respective elements
#
#   Part of the Scout Portal Toolkit
#   Copyright 2004 Internet Scout Project
#   http://scout.wisc.edu
*/
var DD_TypeAhead     = true; // (De)Activates the type ahead functionality
var DD_Delay         = true; // (De)Activates the typing delay
var DD_SuggestDelay  = 650;  // The delay (milliseconds) between presses before request sent
var DD_MinimumLength = 2;    // The minimum length allowed for a search query
var DD_BorderWidth   = 1;    // The border width of the results layer
var DD_Url           = "index.php"; // Url to send AJAX request
var DD_ResultPrefix      = "D_DD_"; // Prefix applied to the ids of results 
var DD_DropdownContainer = "DD_DropdownContainer"; // Contains all drop down elements
var DD_ResultsContainer  = "DD_ResultsContainer";  // Container of the results
var DD_Result            = "DD_Result";            // Individual result
var DD_SelectedResult    = "DD_SelectedResult";    // Selected or hovered result
var DD_Bottom            = "DD_Bottom";            // Bottom container
var DD_ErrorContainer    = "DD_ErrorContainer";    // Error container
var DD_Error             = "DD_Error";             // Error text
var DD_WarningDisplay    = "DD_WarningDisplay";    // Class for warning styles
var DD_ErrorDisplay      = "DD_ErrorDisplay";      // Class for error styles
var DD_Input             = "DD_Input";             // Class for inputs
var DD_Text              = "DD_Text";              // Class for text displays
var DD_Structure = "<ul id='"+DD_ResultsContainer+"'></ul><div id='"+DD_Bottom+"'>" +
                   "<div id='"+DD_ErrorContainer+"'>" +
                   "<img src='images/icon_warning.gif' alt='!!!'" +
                   " style='position:relative;bottom: 1px;' />" +
                   " <span id='" + DD_Error + "'></span></div></div>"; // Structure for dropdown


///// Nothing below this line should need editing -----
var DD_PreviousTime  = null; // Stores the last time the suggest function was called
var DD_HaltSafari    = null; // Fixes the Safari bug, which duplicates the navigation event
var DD_MainForm      = null; // The main form
var DD_DelayTimeout  = null; // Holds the delay timeout
var DD_CurrentResult = null; // The currently selected result
var DD_OriginalValue = null; // Store the orginal user input

// Append the div to the page
var DD_Layer = document.createElement("div");
DD_Layer.id = DD_DropdownContainer;
DD_Layer.innerHTML = DD_Structure;
document.body.appendChild(DD_Layer);
delete DD_Layer;
delete DD_Structure;

// Apply suggest actions to inputs
var DD_InputElements = new Object();
DD_InputElements = new GetElementsByClass(DD_Input);
for (var i in DD_InputElements)    
{           
    DD_InputElements[i].onkeyup = function(event){
        GetKeyCode(event);
        Suggest(this);
    };
}
delete DD_InputElements;

// Apply text functions to text class
var DD_TextElements = new Object();
DD_TextElements = GetElementsByClass(DD_Text);
for (var i in DD_TextElements)    
{           
    DD_TextElements[i].onclick = function(){
        var InputElement = new GetElement(this.id.replace(/_Text/gi, ""));
        InputElement.value = this.innerHTML;
        HideElement(this);
        ShowElement(InputElement);
        InputElement.focus();
        InputElement.select();
    };
}
delete DD_TextElements;

// Compatible key code functions
WindowEvent = window.Event ? true : false;
if (WindowEvent)
{
    window.captureEvents(Event.KEYDOWN);
    window.onkeydown = GetKeyCode;
}
else
{
    document.onkeydown = GetKeyCode;
}

function RemoveTrailingDelimiter(Text, Delimiter)
{
    if (Text.lastIndexOf(Delimiter) == Text.length - Delimiter.length)
    {
        return Text.substring(0, Text.length - Delimiter.length);
    }
    return Text;
}

function KeyIsAlpha(Key)
{
    if ((Key > 46 && Key < 112) || Key > 123)
    {
        return true;
    }
    return false;
}

function RemoveCustomResultStyle(Result)
{
    Result.className = DD_Result;
}

function RemoveCustomInputStyle(Input)
{
    Input.className = "";
}

function IsWasteful(Text)
{
    if (Text === "" || Text.length <= DD_MinimumLength)
    {
        return true;
    }
    return false;
}

function DisableOnSubmit(Element)
{
    Element.onsubmit = function(){return false;};
}

function HandleResponseText(Response)
{
    var ResponseArray = RemoveTrailingDelimiter(Response, "+|").split("+|");
    for (var i = 0; i < ResponseArray.length; i++)
    {
        ResponseArray[i] = RemoveTrailingDelimiter(ResponseArray[i], "|").split("|");
    }
    return ResponseArray;
}

function FormatResults(Response)
{
    // Return if no results
    if (parseInt(Response.numresources) < 1)
    {
        return "";
    }

    // Show the user's original input
    Final = "<li id='" + DD_ResultPrefix + "OrginalInput' class='" +
            DD_Result + "'>" + DD_OriginalValue + "</li>";

    // Give each response proper formatting
    for (var i = 0; i < parseInt(Response.numresources); i++)
    {
        if (Response.resources[i].value !== "")
        {
            Final += "<li id='" + DD_ResultPrefix + i + "' class='" +
                     DD_Result + "'>" + Response.resources[i].value + "</li>";
        }
    }
    return Final;
}

function ClearResults()
{
    GetElement(DD_ResultsContainer).innerHTML = "";
}

function GetMainForm(Element)
{
    var FormElement = Element.parentNode;
    while (FormElement.tagName != "FORM")
    {
        FormElement = FormElement.parentNode;
    }
    return FormElement;
}

function Suggest(Element)
{
    // Get all of the necessary variables
    var FieldName = Element.getAttribute("FieldName");
    var Position = Element.getAttribute("Position");
    var Code = KeyCode; // To preserve the original key code value
    var DropdownContainer = new GetElement(DD_DropdownContainer);

    // Get the main form if not set
    if (DD_MainForm === null)
    {
        DD_MainForm = GetMainForm(Element);
    }
    
    // Disables form submit on ENTER, if not already applied. For Macs
    if (DD_MainForm.onsubmit === null || DD_MainForm.onsubmit === undefined)
    {
        DisableOnSubmit(DD_MainForm);
    }
    
    // Apply the onfocus function, if not already applied
    if (Element.onfocus === undefined)
    {
        Element.onfocus = function(){
            if (Trim(Element.value) !== "")
            {
                DisableOnSubmit(DD_MainForm);
            }
        };
    }

    // Apply the onblur function to re-enable the form
    Element.onblur = function(){                                                        
        // Hide the results and re-allow form submissions
        HideElement(DD_DropdownContainer);
        DD_MainForm.onsubmit = null;
    };
    
    // If ENTER or any navigation buttons are pressed
    if (Code == 13 || (Code > 36 && Code < 41))
    {
        // Fix for Safari navigation bug
        if (DD_HaltSafari === true){return false;}
        DD_HaltSafari = true;
        setTimeout(function(){DD_HaltSafari = false;}, 1);
        
        if (Code === 13 && IsWasteful(Trim(Element.value)) === false) // ENTER pressed
        {
            // Set the classification and reset the selected result
            if (GetElement(DD_DropdownContainer).style.display == "none" || DD_CurrentResult === null)
            {
                SetClassification(Element.value, Element, Position, FieldName);
            }
            else
            {
                SetClassification(DD_CurrentResult.innerHTML, Element, Position, FieldName);
            }
            DD_CurrentResult = new GetElement(DD_ResultPrefix + "0");
        }
        else if (Code === 38) // Up arrow pressed
        {
            // If a lower position (closer to top of page) result exists
            if (DD_CurrentResult.previousSibling)
            {
                // Remove custom styles and set the new current result
                RemoveCustomResultStyle(DD_CurrentResult);
                DD_CurrentResult = DD_CurrentResult.previousSibling;

                // Set class of new selected result
                DD_CurrentResult.className += " " + DD_SelectedResult;
                Element.value = DD_CurrentResult.innerHTML;
            }
            
            // Position the cursor at the end. For proper positioning on Macs
            Element.select();
        }
        else if (Code === 40) // Down arrow
        {
            // If a higher position (closer to bottom of page) result exists
            if (DD_CurrentResult.nextSibling)
            {
                // Remove custom styles and set the new current result
                RemoveCustomResultStyle(DD_CurrentResult);
                DD_CurrentResult = DD_CurrentResult.nextSibling;

                // Set class of new selected result
                DD_CurrentResult.className += " " + DD_SelectedResult;
                Element.value = DD_CurrentResult.innerHTML;
            }
            
            // Position cursor at end
            Element.select();
        }
        return;
    }
    else if (IsWasteful(Trim(Element.value)) === true) // Check for wasteful queries
    {
        // Hide the results and remove the class of the input box
        HideElement(DD_DropdownContainer);
        RemoveCustomInputStyle(Element);
        return;
    }
    // If the current value, minus padding whitespace, is not equal to the previous value
    else if (Trim(Element.value) != DD_OriginalValue)
    {
        // To reduce useless AJAX requests, run only after a delay if enabled
        if (DD_Delay === true)
        {
            clearTimeout(DD_DelayTimeout);
            var Now = new Date();
            if ((DD_PreviousTime + DD_SuggestDelay) > Now.getTime())
            {
                DD_DelayTimeout = setTimeout(function(){Suggest(Element);}, DD_SuggestDelay);
                return;
            }
            DD_PreviousTime = Now.getTime();
        }
        
        // Remember the original input
        DD_OriginalValue = Element.value;
        
        // Set parameters and send AJAX request
        var Parameters = {P:"AJAXDropdown", Action:"Classification", Argument:Element.value, FieldId:Element.getAttribute("FieldId")};
        SendAJAXRequest(DD_Url, Parameters, function(Response){HandleAJAXResponse(Response, Element, Code, FieldName);});
    }
}

function HandleAJAXResponse(Response, Element, Code, FieldName)
{
    // Save original value and get response array
    var OriginalValue = Element.value;
    var Response = eval('('+Response+')');
    
    // If type-ahead is enabled and a letter is pressed
    if (DD_TypeAhead !== false && KeyIsAlpha(Code) && parseInt(Response.numresources) > 0)
    {
        var Length = Element.value.length;
        
        // Determines if the first result and what is typed are similar
        if (Element.value.substr(0, Length) == Response.resources[0].value.substr(0, Length))
        {
            // Set the input equal to the first result
            Element.value = Response.resources[0].value;
                            
            // Select the additions
            SelectInputText(Element, Length, Element.value.length);
        }
                        
        // Stops the cursor from repositioning to the end of the input box
        DD_TypeAhead = false;
        setTimeout(function(){DD_TypeAhead = true;}, DD_SuggestDelay);
    }
    
    // Clear old results, format new results and put in results container
    ClearResults();
    GetElement(DD_ResultsContainer).innerHTML = FormatResults(Response);
    
    // Get the first result, current selected result, and dropdown container
    var DropdownContainer = GetElement(DD_DropdownContainer);
    
    // Add functions to results
    if (parseInt(Response.numresources) > 0)
    {
        DD_CurrentResult = GetElement(DD_ResultPrefix + "0");
        
        // Set mouse actions for the results
        var ResultElements = new Object();
        ResultElements = GetElementsByClass(DD_Result);
        for (var i in ResultElements)    
        {           
            ResultElements[i].onmousedown = function(){
                SetClassification(this.innerHTML, Element, Element.getAttribute("Position"), FieldName);
            };
        
            ResultElements[i].onmouseover = function(){
                this.className += " " + DD_SelectedResult;
            };
         
            ResultElements[i].onmouseout = function(){
                if (this.innerHTML != DD_CurrentResult.innerHTML)
                {
                    RemoveCustomResultStyle(this);
                }
            };
        }
        
        // Set the class of the first result
        DD_CurrentResult.className += " " + DD_SelectedResult;
    }
                    
    // Set the position/width (equal to the input box) and show the results container
   var Position = GetElementPosition(Element);
   var Size = GetElementSize(Element);
   DropdownContainer.style.width = (Size.Width - DD_BorderWidth * 2) + "px";
   DropdownContainer.style.top = (Position.Top + Size.Height) + "px";
   DropdownContainer.style.left = Position.Left + "px";
   ShowElement(DropdownContainer);
   
   // Reset class and set value
   Element.className = RemoveCustomInputStyle(Element.className);
   
   // Apply warning/error classes to input box
   if (Response.type !== "ok")
   {
       ShowElement(GetElement(DD_Bottom));
       if (Response.type == "warning")
       {
           Element.className += " " + DD_WarningDisplay;
       }
       else if (Response.type == "error")
       {
           Element.className += " " + DD_ErrorDisplay;
       }
       GetElement(DD_Error).innerHTML = Response.message;
   }
   else
   {
       HideElement(GetElement(DD_Bottom));
   }
}


function SetClassification(Classification, Element, Position, FieldName)
{
    // Set the input box value. Get the text container and set its properties
    var TextContainer = new GetElement(DD_ResultPrefix + FieldName + Position + "_Text");    
    Element.value = Classification;
    TextContainer.innerHTML = Classification;
    
    // Hide the input box and show the text container
    HideElement(Element);
    HideElement(DD_DropdownContainer);
    TextContainer.style.display = "block"; // can't use ShowElement here
    
    // Make the next input 
    var FieldHidden = new GetElement("D_" + FieldName + "_Hidden");
    if (FieldHidden.value == Position)
    {
        FieldHidden.value = parseInt(FieldHidden.value) + 1;
        ShowElement(GetElement(DD_ResultPrefix + FieldName + FieldHidden.value));
    }
    
    // Re-enable form submission and focus the next input
    DD_MainForm.onsubmit = null;
    GetElement(DD_ResultPrefix + FieldName + FieldHidden.value).focus();
}

(function(s){var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};s.parseJSON=function(filter){var j;function walk(k,v){var i;if(v&&typeof v==='object'){for(i in v){if(Object.prototype.hasOwnProperty.apply(v,[i])){v[i]=walk(i,v[i])}}}return filter(k,v)}if(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(this.replace(/\\./g,'@').replace(/"[^"\\\n\r]*"/g,''))){j=eval('('+this+')');return typeof filter==='function'?walk('',j):j}throw new SyntaxError('parseJSON');};s.toJSONString=function(){if(/["\\\x00-\x1f]/.test(this)){return'"'+this.replace(/[\x00-\x1f\\"]/g,function(a){var c=m[a];if(c){return c}c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16)})+'"'}return'"'+this+'"'}})(String.prototype);
