/**
 * Script:  C3DropDownList.js
 * Desc:    Client-Side Javascript functions used by the C3DropDownList Control.
 */

var cnstProp_DGContainer = "_DGContainer";
var cnstProp_SelTextContainer = "_SelTextContainer";
var cnstProp_SelTextImage = "_SelTextImage";
var cnstProp_SelText = "_SelText";
var cnstProp_SelIndex = "_SelIndex";
var cnstProp_SelValue = "_SelValue";
var cnstProp_SelTextCol = "_SelTextColumn";
var cnstProp_SelValueCol = "_SelValueColumn";


// Attach event listener to fire BEFORE element activation occurs.
document.attachEvent('onbeforeactivate',C3DropDownList_OnBeforeActivate);


function C3DropDownList_OnBeforeActivate() {

    // Set element references.
    var oElm = document.activeElement;
    if (!oElm) return;

    // If the object losing focus is a dropdown list then we will check the display
    // status of the list.
    if (oElm.C3ClientID) {

        // If the element gaining focus is in our table (ie user clicked on a table row),
        // then we will not do anything, as the OnClick event handler will toggle the display.
        if (event.srcElement.tagName == 'TD') {
            var oTbl = C3DropDownList_GetParent(event.srcElement,'TABLE');
            if(oTbl.id==oElm.C3ClientID) return true;
        }

        // If the element gaining focus is an element related to our control (ie. input,
        // dropdown image, etc), then we will not do anything.
        if (event.srcElement.C3ClientID == oElm.C3ClientID) return true;

        // If the dropdown list is displayed, then hide it.
        var oDivDD = document.getElementById(oElm.C3ClientID+cnstProp_SelTextContainer);
        if (oDivDD) {
            if (oDivDD.C3DisplayState == '1') C3DropDownList_DisplayToggle(oDivDD);
        }
    }

    // Bubble the event.
    return true;
}


function C3DropDownList_DisplayToggle(oElm) {

    // Set element references.
    var oDivDD = document.getElementById(oElm.C3ClientID+cnstProp_SelTextContainer);
    var oDivLI = document.getElementById(oElm.C3ClientID+cnstProp_DGContainer);

    // Set listitem position.
    oDivLI.style.posLeft = oDivDD.offsetLeft;
    oDivLI.style.posTop = oDivDD.offsetTop + oDivDD.style.posHeight;

    // Toggle listitem display state.
    if (oDivDD.C3DisplayState == '0') {

        // Show listitems container.
        oDivDD.C3DisplayState = '1';
        oDivLI.setActive();
        oDivLI.style.display = '';

        // If not enough items to fill container, then adjust container height to table height.
        if (oDivLI.scrollHeight < oDivLI.offsetHeight) {
            oDivLI.style.overflow='visible';
            oDivLI.style.height='';
        }

        // Scroll selected item into view.
        var oIdx = document.getElementById(oElm.C3ClientID+cnstProp_SelIndex);
        var nIdx = Number(oIdx.value);
        if (nIdx > -1) {
            var oTbl = document.getElementById(oElm.C3ClientID);
            if (nIdx < oTbl.rows.length) oTbl.parentNode.scrollTop = oTbl.rows(nIdx).offsetTop;
        }

    } else {

        // Hide listitems container.
        oDivLI.style.display = 'none';
        oDivDD.C3DisplayState = '0';
    }
}


function C3DropDownList_RowMouseEnter(oTR,sDivDD) {

    // Set element references.
    var oDivDD = document.getElementById(sDivDD);

    // Save current style settings.
    oDivDD.C3MouseEnterCssTextSave = oTR.style.cssText;
    oDivDD.C3MouseEnterCssClassSave = oTR.className;

    // Set new style settings.
    oTR.style.cssText = oDivDD.C3MouseEnterCssText;
    oTR.className = oDivDD.C3MouseEnterCssClass;
}


function C3DropDownList_RowMouseLeave(oTR,sDivDD) {

    // Set element references.
    var oDivDD = document.getElementById(sDivDD);

    // Restore saved style settings.
    oTR.style.cssText = oDivDD.C3MouseEnterCssTextSave;
    oTR.className = oDivDD.C3MouseEnterCssClassSave;
}


function C3DropDownList_RowClick(oTR,sDivDD,nColText,nColValue,bPostback) {

    // Set element references.
    var oDivDD = document.getElementById(sDivDD);
    var oTxt = document.getElementById(oDivDD.C3ClientID+cnstProp_SelText);
    var oVal = document.getElementById(oDivDD.C3ClientID+cnstProp_SelValue);
    var oIdx = document.getElementById(oDivDD.C3ClientID+cnstProp_SelIndex);

    var nRowIndex = oTR.rowIndex;

    // Set selected text, value and index values from selected item.
    oIdx.value = nRowIndex;
    oTxt.value = oTR.cells(nColText).innerText;
    oVal.value = oTR.cells(nColValue).innerText;

    // Reset keypress buffer settings.
    oTxt.C3KeyPressBuffer = ''; 
    oTxt.C3KeyPressFoundIndex = '0'; 

    // Reset style and display settings since row was selected.
    C3DropDownList_RowMouseLeave(oTR,sDivDD);
    C3DropDownList_DisplayToggle(oDivDD);

    // If postback allowed then make it so.
    if (bPostback) __doPostBack(oDivDD.C3ClientID,'SelectionChanged');
}


function C3DropDownList_OnKeyDown(oTxt,bCaseSensitive,nColText,nColValue,bPostback,bAllowNewItemEntry) {

    // Ignore specified keys.
    var sKeys = ' 9; 16; 17; 18; 20; 27; 33; 34; 35; 36; 37; 38; 39; 40; 45;';
    if (sKeys.indexOf(' '+event.keyCode+';')>-1) {
        return;
    }

    // Set element references.
    var oVal = document.getElementById(oTxt.C3ClientID+cnstProp_SelValue);
    var oIdx = document.getElementById(oTxt.C3ClientID+cnstProp_SelIndex);

    // Convert key pressed to displayable char.
    var key = String.fromCharCode(event.keyCode); 

    switch (true) { 

        // If DELETE key, then reset keypress buffer / stored values and exit.
        case (event.keyCode == 46):
            oTxt.value = '';
            oVal.value = '';
            oIdx.value = '-1';
            oTxt.C3KeyPressBuffer = ''; 
            oTxt.C3KeyPressFoundIndex = '0'; 
            event.returnValue = false;
            return; 

        // If ENTER key, then check for postback.
        case (event.keyCode == 13):
            var oDivDD = document.getElementById(oTxt.C3ClientID+cnstProp_SelTextContainer);
            var oDivDG = document.getElementById(oTxt.C3ClientID+cnstProp_DGContainer);
            oDivDG.style.display = 'none';
            oDivDD.C3DisplayState = '0';
            var oRange = oTxt.createTextRange();
            oRange.select();
            if (bPostback) __doPostBack(oDivDD.C3ClientID,'SelectionChanged');
            event.returnValue = false;
            return; 

        // If BACKSPACE key, then remove previous char from keypress buffer.
        case (event.keyCode == 8):
            oTxt.C3KeyPressBuffer = oTxt.C3KeyPressBuffer.substring(0,oTxt.C3KeyPressBuffer.length-1); 
            oTxt.C3KeyPressFoundIndex = '0'; 
            var key = ""; 
            break;

        // If KeyDown event then we are done!  This will return True for
        // the Event, which will allow the onKeyPress event to fire.
        // Internet Explorer returns the UPPER-CASE char in the event
        // keyCode property for the onKeyDown Event, but returns the correct
        // char (case-sensitive) for the onKeyPress event.
        // Note that the BACKSPACE test above does a BREAK statement which
        // causes this case evaluation to be ignored and processing to continue, 
        // even though it occured in the KeyDown event!
        case (event.type == 'keydown'):
            event.returnValue = true;
            return; 
            break;

        // If maxLength reached then we are done!
        case (oTxt.maxLength != 'undefined'):
            if (oTxt.C3KeyPressBuffer.length >= oTxt.maxLength) {
                event.returnValue = true;
                return; 
            }
    }

    // Handle case-sensitive search.
    var sC3KeyPressBuffer;
    if (!bCaseSensitive) {
        sC3KeyPressBuffer = oTxt.C3KeyPressBuffer.toLowerCase();
        sC3KeyPressBuffer += key.toLowerCase();
    } else {
        sC3KeyPressBuffer = oTxt.C3KeyPressBuffer;
        sC3KeyPressBuffer += key;
    }

    // Set element references and previously found entry index.
    var oTbl = document.getElementById(oTxt.C3ClientID);
    var nTblIdxStart = Number(oTxt.C3KeyPressFoundIndex);
    var nRowCnt = oTbl.rows.length; 

    // Search listitems for items matching key buffer contents.
    for (var n=nTblIdxStart; n < nRowCnt; n++) { 

        // Set element references.
        var oTR = oTbl.rows(n); 
        var sRowText = oTR.cells(nColText).innerText; 

        // If not case-sensitive then convert item text to lowercase for comparison.
        if (!bCaseSensitive) {
            sRowText = sRowText.toLowerCase();
        }

        // Do we have a match?
        if (sRowText.indexOf(sC3KeyPressBuffer,0) == 0) { 

            // Yes - store selected text, value, and index values.
            var nRowIndex = oTR.rowIndex;
            if (oTxt.C3HeaderFlag=='true') nRowIndex = nRowIndex-1;
            oIdx.value = nRowIndex;
            oTxt.value = oTR.cells(nColText).innerText;
            oVal.value = oTR.cells(nColValue).innerText;

            // If listitems are displayed, then scroll the item into view.
            oTbl.rows(n).scrollIntoView(false); 

            // Store found index to use as starting position for next time around.
            // There's no sense searching previous entries since they don't match!
            oTxt.C3KeyPressFoundIndex = oTR.rowIndex; 
            oTxt.C3KeyPressBuffer += key;

            // Hi-lite text typed thus far to indicate what was matched.
            if (sC3KeyPressBuffer.length>0) {
                var oRange = oTxt.createTextRange();
                oRange.findText(sC3KeyPressBuffer);
                oRange.select();
            } 

            // Inform KeyPress event to ignore the keypress since we already handled
            // displaying the char in the above logic.
            event.returnValue = false;
            return; 
        } 
    } 

    // Add key pressed to buffer.
    oTxt.C3KeyPressBuffer += key;

    // At this point, no listitems matched the entered text!

    // Are new entries allowed?
    if (bAllowNewItemEntry) {

        // New entries ARE allowed - retain stored values and buffers.
        oTxt.value = oTxt.C3KeyPressBuffer;
        oVal.value = oTxt.value;
        oIdx.value = '-2';
        oTxt.C3KeyPressFoundIndex = String(oTxt.value.length); 
        event.returnValue = false;
        return; 

    } else {

        // New entries ARE NOT allowed - reset stored values and buffers.
        oTxt.value = '';
        oVal.value = '';
        oIdx.value = '-1';
        oTxt.C3KeyPressBuffer = ''; 
        oTxt.C3KeyPressFoundIndex = '0'; 
        event.returnValue = false;
        return; 
    }
} 


function C3DropDownList_GetParent(el, pTagName) {

    if (el == null) return null;
    else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())	// Gecko bug, supposed to be uppercase
        return el;
    else
        return C3DropDownList_GetParent(el.parentNode, pTagName);
}

