var browserName = navigator.appName;

var colNumber; // the column number of the selected header

/*  function sortTable(theHdr[, compareType])
    This function sorts the table that contains the passed in link. The link is used to
        determine the header that contains it. The sort is performed using the values
        in the column headed by the selected header. The sort order is reversed each
        time a column is selected if no other column was selected in between. The function
        also writes out to a span contained in the header to display a sort arrow indicating
        which way the data will be sorted when clicked.

        Takes an optional input parameter named compareType that is used to specify the name
            of the comparator function to be used for the selected column. This can be used
            when a column can contain numeric or text data but should be sorted as text.

    ** This script assumes that there are only 3 types of rows in the table; the header rows
        that contain the link that triggers the sort, the rows that contain the data to be
        sorted, and, possibly, summary rows. Summary rows must be given a class of 'summary'.
        The script assumes that summary rows are located at the bottom of the table.
    Inputs:
       theHdr - the link selected
       compareType - (optional) the name of the comparator function to be used
           for the selected column. When passed the exact name of the comparator
           function must be specified in the function as an unquoted string.
    Return Value:
        None
   1-3-2004 DV
*/

function sortTable(theHdr, compareType){

    var selCell = theHdr.parentNode; // the <th> cell
    colNumber = selCell.cellIndex;
    var theTable = getParent(selCell,"table"); // the table the cell is in
    if (theTable.rows.length <= 1)
        return;
    // find the data type of the selected column and set the comparator
    comparator = compareType;
    if (comparator == undefined){
        var colData = getInnerText(theTable.rows[1].cells[colNumber]);
        comparator = textCompare;
        if (colData.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/))
            comparator = dateCompare;
        if (colData.match(/^\d\d[\/-]\d\d[\/-]\d\d$/))
            comparator = dateCompare;
        if (colData.match(/^[£$]/))
            comparator = currencyCompare;
        if (colData.match(/^[\d\.]+$/))
            comparator = numberCompare;
    }

    // copy the data rows in the table into a temp array and sort them
    // exclude summary rows by checking the class name of the row
    var newRows = new Array();
    for (j = 1; j < theTable.rows.length; j++){
        if (theTable.rows[j].className.indexOf("summary") == -1){
            newRows[j-1] = theTable.rows[j];
        }
    }
    newRows.sort(comparator);

    // determine number of summary rows and save them in a temp array
    var sumRowsCount = theTable.rows.length - newRows.length - 1;
    var sumStart = theTable.rows.length - sumRowsCount;
    var sumArray = new Array();
    for (i = sumStart; i < theTable.rows.length; i++){
        sumArray[i - sumStart] = theTable.rows[i];
    }

    // check all spans in the same table and clear their arrows
    var allspans = document.getElementsByTagName("span");
    for (var indx = 0; indx < allspans.length; indx++) {
        if (allspans[indx].className == "sortarrow") {
            if (getParent(allspans[indx],"table") == getParent(theHdr,"table")) {
                allspans[indx].innerHTML = "&nbsp;&nbsp;&nbsp;";
            }
        }
    }

    // find the span in the selected header and set the arrow indicator
    var span;
    for (var indx = 0; indx < theHdr.childNodes.length; indx++) {
        if (theHdr.childNodes[indx].tagName && theHdr.childNodes[indx].tagName.toLowerCase() == 'span'){
            span = theHdr.childNodes[indx];
        }
    }

    var sortArrow;
    if (span.getAttribute("sortdir") == "down") {
        sortArrow = "&nbsp;&nbsp;&uarr;";
        newRows.reverse();
        span.setAttribute("sortdir","up");
    } else {
        sortArrow = "&nbsp;&nbsp;&darr;";
        span.setAttribute("sortdir","down");
    }

    span.innerHTML = sortArrow;

    // rebuild the table by inserting the rows back in. Exclude summary rows
    // that are added on the bottom.
    for (i=0; i<newRows.length; i++){
        if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf("summary") == -1))){
            theTable.tBodies[0].appendChild(newRows[i]);
        }
    }

    // put the summary rows back on the bottom
    for (i=0; i<sumArray.length; i++){
        theTable.tBodies[0].appendChild(sumArray[i]);
    }
}


/*  function getParent(elem, parentToFind)
    This function finds the parent of the passed in element that has the
        name that is passed as the second argument.
    Inputs:
       elem - the element whos parent is being found
       parentToFind - the name of the parent to find
    Return Value:
        The parent element that is found or null if one is not found
   12-11-2004 DV
*/
function getParent(elem, parentToFind) {
    if (elem == null){
        return null;
    } else if (elem.nodeType == 1 && elem.tagName.toLowerCase() == parentToFind.toLowerCase())
        return elem;
    else
        return getParent(elem.parentNode, parentToFind);
}

/*  function getInnerText(elem)
    This function takes the passed in element and extracts its innerText. If the passed in
        element has no innertext itself and has child nodes the function will recursively
        extract the inner text from them as well and append it.
    Inputs:
       elem - the element to extract the innerText from
    Return Value:
        A string containing the innerText of the passed in element.
   12-11-2004 DV
*/
function getInnerText(elem) {
    if (typeof elem == "string"){
        return elem;
    } else if (typeof elem == "undefined"){
        return elem;
    } else if (elem.innerText){
        return elem.innerText;
    }

    // check any child nodes
    var theText = "";
    var theKids = elem.childNodes;
    for (var i = 0; i < theKids.length; i++) {
        switch (theKids[i].nodeType) {
            case 1: //ELEMENT_NODE
                theText += getInnerText(theKids[i]);
                break;
            case 3: //TEXT_NODE
                theText += theKids[i].nodeValue;
                break;
        }
    }
    return theText;
}


/* *****************************************************************************************************
                                  COMPARATOR FUNCTIONS
***************************************************************************************************** */

/*  function dateCompare(arr1, arr2)
    This function takes the passed in arrays/rows and extracts the date values from the sortCell.
        Returns 0 or -1 to caller to identify which one should be 'before' the other when sorting.
        It uses the global variable colNumber to determine which cell in the array to use to sort.
    Inputs:
       arr1 - the array/row containing the first date value to be compared
       arr2 - the array/row containing the second date value to be compared
    Return Value:
        -1 - if the first date comes before the second
        0 - if the two dates are the same
        1 - if the second date comes before the first
   12-11-2004 DV
*/
function dateCompare(arr1, arr2) {
    // get the value from inside the cell
    var value1 = getInnerText(arr1.cells[colNumber]);
    var value2 = getInnerText(arr2.cells[colNumber]);

    // determine if 4 digits years are used - parse out the date
    if (value1.length == 10) {
        dt1 = value1.substr(6,4) + value1.substr(0,2) + value1.substr(3,2);
    } else {
        yr = value1.substr(6,2);
        if (parseInt(yr) < 50){
            yr = '20'+yr;
        } else {
            yr = '19'+yr;
        }
        dt1 = yr + value1.substr(0,2) + value1.substr(3,2);
    }

    if (value2.length == 10) {
        dt2 = value2.substr(6,4) + value2.substr(0,2) + value2.substr(3,2);
    } else {
        yr = value2.substr(6,2);
        if (parseInt(yr) < 50){
            yr = '20'+yr;
        } else {
            yr = '19'+yr;
        }
        dt2 = yr + value2.substr(0,2) + value2.substr(3,2);
    }

    if (dt1 == dt2)
        return 0;
    if (dt1 < dt2)
        return -1;
    return 1;
}

/*  function currencyCompare(arr1, arr2)
    This function takes the passed in arrays/rows and extracts the currency values from the sortCell.
        Uses the replace function to remove any non numeric characters (monetary sigs, commas, etc.).
        Returns a value to caller to identify which one should be 'before' the other when sorting.
        It uses the global variable colNumber to determine which cell in the array to use to sort.
    Inputs:
       arr1 - the array/row containing the first value to be compared
       arr2 - the array/row containing the second value to be compared
    Return Value:
        < 0 - indicates the first value comes before the second
        0 - if the two values are the same
        > 0 - if the second value comes before the first
   12-11-2004 DV
*/
function currencyCompare(arr1, arr2) {
    var value1 = getInnerText(arr1.cells[colNumber]).replace(/[^0-9.]/g,'');
    var value2 = getInnerText(arr2.cells[colNumber]).replace(/[^0-9.]/g,'');
    return parseFloat(value1) - parseFloat(value2);
}


/*  function numberCompare(arr1, arr2)
    This function takes the passed in arrays/rows and parses the numeric values from the sortCell.
        Returns a value to caller to identify which one should be 'before' the other when sorting.
        It uses the global variable colNumber to determine which cell in the array to use to sort.
    Inputs:
       arr1 - the array/row containing the first value to be compared
       arr2 - the array/row containing the second value to be compared
    Return Value:
        < 0 - indicates the first value comes before the second
        0 - if the two values are the same
        > 0 - if the second value comes before the first
   12-11-2004 DV
*/
function numberCompare(arr1, arr2) {
    var value1 = parseFloat(getInnerText(arr1.cells[colNumber]));
    if (isNaN(value1))
        value1 = 0;
    var value2 = parseFloat(getInnerText(arr2.cells[colNumber]));
    if (isNaN(value2))
        value2 = 0;

    return value1 - value2;
}

/*  function textCompare(arr1, arr2)
    This function takes the passed in arrays/rows and extracts the text from the sortCell. The
        function converts all text to lowercase so it is a case insensitive sort.
        Returns a value to caller to identify which one should be 'before' the other when sorting.
        It uses the global variable colNumber to determine which cell in the array to use to sort.
    Inputs:
       arr1 - the array/row containing the first value to be compared
       arr2 - the array/row containing the second value to be compared
    Return Value:
        -1 - indicates the first value comes before the second
        0 - if the two values are the same
        1 - if the second value comes before the first
   12-11-2004 DV
*/
function textCompare(arr1, arr2) {
    //alert("'" + getInnerText(arr1.cells[colNumber]).toLowerCase() + "' : '" + getInnerText(arr2.cells[colNumber]).toLowerCase() + "'");
    var value1 = getInnerText(arr1.cells[colNumber]).toLowerCase();
    var value2 = getInnerText(arr2.cells[colNumber]).toLowerCase();
    if (value1 == value2)
        return 0;
    if (value1 < value2)
        return -1;
    return 1;
}
