// Display the short calendar in the proper area of the home page
// --NumEntries: number of calendar entries to retrieve
function init_ShortCalendar(NumEntries) {

    // Create new request object in newer browsers
    if (window.XMLHttpRequest) {
        var request = new XMLHttpRequest();
    }

    // Fallback for IE6
    else {
        var request = new ActiveXObject("Microsoft.XMLHTTP");
    }

    // Add a prefix for the non-secure www site
    CalendarPrefix = ((document.URL.charAt(4) == "s") ? "" : "/Academics");

    // Define the parameters of the asynchronous request (the timestamp is not used by the server; it just keeps IE from caching)
    request.open("GET", CalendarPrefix + "/Calendar/AjaxShortCalendar.php?Timestamp=" + new Date().getTime() +"&NumEntries=" + NumEntries, true);

    // Define a function that is run when the state of the request changes
    request.onreadystatechange = function() {

        // Insert placeholder text and graphics
        document.getElementById("placeholder").innerHTML = "<div class='loading'>Loading calendar...</div>";

        // When the request is complete, then populate the placeholder div with the calendar content
        if (request.readyState == 4) {

            // If the request completed successfully, then retrieve the response
            if (request.status == 200) {
                document.getElementById("placeholder").innerHTML = request.responseText;
            }

            // If the request was uncessful, then retrieve the error
            else {
                document.getElementById("placeholder").innerHTML = "<p>" + request.status + ": " + request.statusText +"</p>";
            }
        }
    }

    // Send the request
    request.send(null);
}


// Popup window for Application and RFI
function app_window(url) { 
    window.open(url, 'appWin', 'toolbar=no, directories=no, location=no, menubar=no, resizable=yes, scrollbars=auto, status=yes, width=750, height=486');
}


// Call the sort table routine from a clicked header column
// --column: table header node that was clicked on
function sort_table_by_header(column) {

    // Get the table_id and column index
    table_id = column.parentNode.parentNode.parentNode.parentNode.id;
    index    = column.parentNode.cellIndex;

    // Sort the table
    return sort_table(table_id, index);
}


// Sort a table given the table's id and the index of the header column to sort by
// --table_id: id of table to sort
// --index: index of column heading that was clicked on (first column is 0, second is 1, etc.)
function sort_table(table_id, index) {

    // Exit if the the table isn't being shown for some reason
    if (!document.getElementById(table_id)) {
        return true;
    }

    // If the order variable hasn't been defined, then define it
    if (typeof(order) == "undefined") {
        order = {}
    }

    // If the order variable hasn't been set for this table, then set it
    if (typeof(order[table_id]) == "undefined") {
        order[table_id] = {"up": "", "a_node" : ""}
    }

    // Find the table and table header nodes
    var table_node = document.getElementById(table_id);
    var th_node    = table_node.getElementsByTagName("th")[index];
    var a_node     = th_node.firstChild;

    // Remove the old sort arrow if it exists
    if (order[table_id]["a_node"]) {
        order[table_id]["a_node"].removeChild(order[table_id]["a_node"].firstChild.nextSibling);
    }

    // Toggle the arrow if we are sorting by the same column; otherwise default to ascending
    order[table_id]["up"] = ((a_node == order[table_id]["a_node"]) ? !order[table_id]["up"] : true);

    // Set the new global column header node
    order[table_id]["a_node"] = a_node;

    // Create an indicator node to hold the sort arrow
    var indicator = document.createElement("span");
    indicator.className = "indicator";
    indicator.appendChild(document.createTextNode(order[table_id]["up"] ? "\u25B2" : "\u25BC"));
    a_node.appendChild(indicator);

    // Find the table row nodes of the table body
    var tr_nodes = table_node.getElementsByTagName("tbody")[0].getElementsByTagName("tr");

    // Define value function for a numeric column
    if (th_node.className.indexOf("sort_numval") > -1) {
        get_val = function(k) {
            val = parseFloat(tr_nodes[k].getElementsByTagName("td")[index].firstChild.firstChild.nodeValue);
            val = (isNaN(val) ? 0 : val);
            return val;
        }
    }

    // Define value function for a time column
    else if (th_node.className.indexOf("sort_numclass") > -1) {
        get_val = function(k) {
            val = parseFloat(tr_nodes[k].getElementsByTagName("td")[index].firstChild.className.replace(/.*sort_/, ""));
            val = (isNaN(val) ? 0 : val);
            return val;
        }
    }

    // Define value function for all other columns
    else {
        get_val = function(k) {
            if (tr_nodes[k].getElementsByTagName("td")[index].lastChild.firstChild) {
                return tr_nodes[k].getElementsByTagName("td")[index].lastChild.firstChild.nodeValue.toLowerCase();
            } else {
                return " ";
            }
        }
    }

    // Perform insertion sort
    for (var i = 0; i < tr_nodes.length; i++) {

        // If this item is set to ignore the sort, then skip it
        if (tr_nodes[i].className.match(/ignoresort/)) {
            continue;
        }

        // Get the value of the element i
        i_val = get_val(i);

        // The inner loop moves left-to-right instead of right-to-left as in a standard insertion sort; makes reverse sorting much quicker
        for (var j = 0; j < i; j++) {

            // Get the current value to compare
            j_val = get_val(j);

            // Perform the comparison and insertion, reversing the conditions if we are going in descending order
            if ((order[table_id]["up"] && (i_val < j_val)) || (!order[table_id]["up"] && (i_val > j_val))) {
                tr_nodes[i].parentNode.insertBefore(tr_nodes[i], tr_nodes[j]);
                break;
            }
        }
    }

    // Initialize count for odd/even rows
    OddEvenRow = 0;

    // Step through each sorted row
    for (var i = 0; i < tr_nodes.length; i++) {

        // Only process this row if it is visible
        if (tr_nodes[i].style.display != "none") {

            // Change the class name row to properly reflect being odd or even
            tr_nodes[i].className = tr_nodes[i].className.replace(/even|odd/, (OddEvenRow % 2 ? "even" : "odd"));

            // Increment the odd/even row count
            OddEvenRow++;
        }
    }

    return false;
}


// Show a particular tab, hiding its siblings
// --TabGroupName: tab group to set
// --TabName: tab to show (or 0 for first, -1 for last)
// --HideSingleTab: whether to hide a single tab
// --SwitchHeading: whether to switch the h3 heading at the top of the page to the h5 text for the tab
function switch_tab(TabGroupName, TabName, HideSingleTab, SwitchHeading) {

    // Prepend the proper identifier to the tab group name
    FullTabGroupName = "tabs_" + TabGroupName;

    // If the tab group doesn't exist, return false;
    if (!document.getElementById(FullTabGroupName)) {
        return false;
    }

    // If the tab doesn't exist, default to the first
    if ((TabName !== 0) && (TabName !== -1) && !document.getElementById("div_tab_" + TabGroupName + "_" + TabName)) {
        TabName = 0;
    }


    // Get the parent of the tab
    TabParent = document.getElementById(FullTabGroupName).parentNode;

    // Construct an array to hold the tabs as they are found
    TabSet = new Array ();

    // Step through each child of the parent node, finding the tabs and adding them to the list
    for (TabIndex in TabParent.childNodes) {
        if (TabParent.childNodes[TabIndex].id && (TabParent.childNodes[TabIndex].id.substr(0, 8) == "div_tab_")) {
            TabSet.push(TabParent.childNodes[TabIndex]);
        }
    }

    // Step through each tab in the set
    for (TabIndex in TabSet) {

        // Unconditionally hide the heading
        document.getElementById(TabSet[TabIndex].id.replace("div_tab_", "h5_tab_")).style.display = "none";

        // Determine whether this is the requested tab
        if ((TabSet[TabIndex].id == "div_tab_" + TabGroupName + "_" + TabName) ||
          ((TabName == 0) && (TabIndex == 0)) ||
          ((TabName == -1) && (TabIndex == (TabSet.length - 1)))) {
            isTab     = true;
            isTabever = true;
        } else {
            isTab = false;
        }

        // Highlight the current tab if this is the one requested
        document.getElementById(TabSet[TabIndex].id.replace("div_tab_", "li_tab_")).className = (isTab ? "active" : "");

        // Show or hide this tab based on whether it is the one requested
        TabSet[TabIndex].style.display = (isTab ? "block" : "none");

        // Switch the heading if that was requested
        if (isTab && SwitchHeading) {
            document.getElementById("headline").getElementsByTagName("h3")[0].firstChild.nodeValue
              = document.getElementById(TabSet[TabIndex].id.replace("div_tab_", "h5_tab_")).firstChild.nodeValue;
        }
    }

    // If the function was called to hide the tab on a single-tab craig, then do so
    if (HideSingleTab && (TabSet.length == 1)) {
        document.getElementById(FullTabGroupName).style.display = "none";
    }

    return false;
}

