/*
    Filename:   customSelectElement.js
    Author:     Steve Smith stephen.smith@akqa.com
    Description:    Functions specific to the custom
                    select element used in forms across the 
                    F149 site.
                    Attempts to mimic behaviour of system 
                    select element whilst allowing richer appearance
                    Depends on: displayElementWithTransition() in common.js
                                mootools.js
                    Please ensure any updates maintain document's validity
                    Test validity at http://jslint.com/lint.html
*/

//Sets the value of the input element
//NB: depends on MooTools for $ selector
function setInputElementValue(elementId, elementValue) {
    $(elementId).value = elementValue.trim();
}

//Sets the value of the input element
//NB: depends on MooTools for $ selector
function setElementInnerHTML(elementId, elementValue) {
    $(elementId).innerHTML = '<span>' + elementValue + '</span>';
}

//Handles the show/hide of the custom select drop down
function onCustomSelectItemClick(hiddenInputId, itemValue, itemText, collapsedSelectId, explodedSelectId) {
    setInputElementValue(hiddenInputId, itemValue); 
    setElementInnerHTML(collapsedSelectId, itemText); 
    displayElementWithTransition(explodedSelectId, 'display', 'none', 250); 
    if($(collapsedSelectId)) {
        $(collapsedSelectId).focus();
    }
    return false;
}

//Checks available space below dropdown against required space
function isEnoughSpaceBelowAvaliable(containerElement, element, spaceRequired) {
    var containerHeight = containerElement.getSize().size.y;
    var containerOffsetTop = containerElement.getTop();
    var elementOffsetTop = element.getPosition([containerElement]).y;
    return (containerHeight - (elementOffsetTop - containerOffsetTop)) > spaceRequired;
}

//Displays a specific drop down
function displayExplodedSelect(explodedSelectId) {
    displayElementWithTransition(explodedSelectId, 'display', 'none', 250); 
    if(!isEnoughSpaceBelowAvaliable($("FormContainer"), $(explodedSelectId).getParent().getParent(), 125)) {
        //scroll the container down to expose enough space
        //for exploded drop down
        $("FormContainer").scrollTo(0, $("FormContainer").scrollTop + 125);
    }
}

//Handles the clicking of the custom select item 
function onCollapsedSelectClick(explodedSelectId) {
    displayExplodedSelect(explodedSelectId);
    return false;
}

//Focus on the previous tabindex
function focusOnPreviousTabIndex(item) {
    var currentTabIndex = item.getProperty("tabindex").toInt();
    var previousElement;
    if(!isNaN(currentTabIndex)) {
        previousElement = $$("a, input, select").filterByAttribute("tabindex", "=", currentTabIndex - 1);
        if(previousElement[0]) {
            previousElement[0].focus();
        }
    }
}

//Focus on the next tabindex
function focusOnNextTabIndex(item) {
    var currentTabIndex = item.getProperty("tabindex").toInt();
    var nextElement;
    if(!isNaN(currentTabIndex)) {
        nextElement = $$("a, input, select").filterByAttribute("tabindex", "=", currentTabIndex + 1);
        if(nextElement[0]) {
            nextElement[0].focus();
        }
    }
}

//Handles the press of the down, right, or tab key when focused on the 
//custom select item - mimicking system select behaviour
function onCollapsedSelectKeyDown(event, item) {
    if($(item.rel)) {
        if(event.keyCode == 40 || event.keyCode == 39 ) {
            if($(item.rel).style.display != "block") {
                $(item.rel).setStyle("display", "block");
                $$("#"+ item.rel +" a")[0].focus();
                $$("#"+ item.rel +" a")[0].addClass("hover");
            }
        }
        //tab key
        else if(event.keyCode == 9) {
            if(event.shiftKey) {
                focusOnPreviousTabIndex(item);
            }
            else {
                focusOnNextTabIndex(item);
            }
        }
    }
    return false;
}

//Handles the selecting of an item in the dropdown
function onCustomSelectItemSelected(itemRel) {
    if(itemRel !== "") {
        anchorRelValues = itemRel.split(" | ");
        //add click event to item
        if(anchorRelValues.length >= 5) {
            onCustomSelectItemClick(anchorRelValues[0], anchorRelValues[1], anchorRelValues[2], anchorRelValues[3], anchorRelValues[4]);
        }
    }
}

//Handles the user action when focused on the 
//custom select item - mimicking system select behaviour
function setUpCustomSelectorItems(explodedSelectId) {
    var collectionOfItems = $$("#"+ explodedSelectId +" a");
    var anchorRelValues;
    var stopEvent;
    for(var n = 0; n < collectionOfItems.length; n++) {
        collectionOfItems[n].addEvent("click", function(evt){
            //cancel event and do our own stuff
            stopEvent = new Event(evt).stop();
            onCustomSelectItemSelected(this.rel);
        }); 
        collectionOfItems[n].addEvent("keydown", function(evt){
            //cancel event and do our own stuff
            stopEvent = new Event(evt).stop();
            if(evt.keyCode == 40 || evt.keyCode == 39) { 
                //down or right cursor, so move to next item if exists
                if(this.getParent().getNext() && this.getParent().getNext().getFirst()) {
                    this.getParent().getFirst().removeClass("hover");
                    this.getParent().getNext().getFirst().focus();
                    this.getParent().getNext().getFirst().addClass("hover");
                }
            }
            else if(evt.keyCode == 38 || evt.keyCode == 37) {
                //up or left cursor, so move to next item if exists
                if(this.getParent().getPrevious() && this.getParent().getPrevious().getFirst()) {
                    this.getParent().getFirst().removeClass("hover");
                    this.getParent().getPrevious().getFirst().focus();
                    this.getParent().getPrevious().getFirst().addClass("hover");
                }
                //first item, so collapse select and focus on select item
                else if(this.getParent().getParent().getParent().getPrevious()){
                    $(explodedSelectId).setStyle('display', 'none');
                    this.getParent().getParent().getParent().getPrevious().focus();
                }
            }
            else if(evt.keyCode == 13) {
                //return or enter hit, so behave the same as click event
                onCustomSelectItemSelected(this.rel);  
            }
            else if(evt.keyCode == 9) {
                //tab hit, so close select and focus on next field
                onCustomSelectItemSelected(this.rel);  
            }
        });
    }
}

//Handles the events of 'custom selectors'
function setUpCustomSelectors() {
    var collectionOfSelectors = $$(".collapsedSelect");
    //iterate through collection of custom selectors
    //attaching click events as we go
    for(var i = 0; i < collectionOfSelectors.length; i++) {
        if(collectionOfSelectors[i].rel !== "") {
            //attach click event
            collectionOfSelectors[i].addEvent("click", function(evt){
                stopEvent = new Event(evt).stop();
                onCollapsedSelectClick(this.rel);
            });
            //attach keydown event
            collectionOfSelectors[i].addEvent("keydown", function(evt){
                stopEvent = new Event(evt).stop();
                onCollapsedSelectKeyDown(evt, this);
            });  
            //iterate through this selectors items
            //and add events
            setUpCustomSelectorItems(collectionOfSelectors[i].rel.split("|")[0].trim());
        }
    }
}

//Loops through and hides all exploded drop downs
function hideAllExplodedSelectContainers() {
    var collectionOfExplodedSelectContainers = $$(".explodedSelectContainer"); 
    for(var i = 0; i < collectionOfExplodedSelectContainers.length; i++) {
        collectionOfExplodedSelectContainers[i].getFirst().setStyle('display', 'none');
    }
}

//Hides all custom dropdowns when container is scrolled
//NB: currently unused
function addOnScrollEventToContainer() {
    var collectionOfCustomScrollers = $$(".closeSelectsOnScroll");
    for(var i = 0; i < collectionOfCustomScrollers.length; i++) {
        collectionOfCustomScrollers[i].addEvent("scroll", function(){
            hideAllExplodedSelectContainers();
        });
    }
}

//Hides all custom dropdowns when a new item is focussed
function configureOnFocusCloseCustomSelects() {
    var collectionOfOnFocusCloseCustomSelects = $$(".onFocusCloseCustomSelects");
        for(var i = 0; i < collectionOfOnFocusCloseCustomSelects.length; i++) {
            collectionOfOnFocusCloseCustomSelects[i].addEvent("focus", function(){
                hideAllExplodedSelectContainers();
            });
    }
}

//Attaches functions onpageload
//NB: Used in place of DomReady due to SwfObject
//causing DOM irregularity
//checks that displayElementWithTransition() is available
//and bails out if it cant be found
window.addEvent('load', function() {
    if(typeof(displayElementWithTransition) != "function") {
        return false;    
    }
    else {
        setUpCustomSelectors();
        //addOnScrollEventToContainer();
        configureOnFocusCloseCustomSelects();
    }
});
