/* glacier_photo.js
 * JavaScript functions for the glacier photo search page.
 */

/**************************************
  GLOBALLY USED FUNCTIONS
  *************************************/


/* arrowImg is an object used to store the visibile and hidden arrows */
var arrowImg = {
        visible: '',
        hidden : ''
    };

/* setArrowImages sets the images used for the arrows on the page 
 *  visImg - the URL to the image to use for the "visible" arrow (open div)
 *  hidImg - the URL to the image to use for the "hidden" arrow (closed div)
 */
function setArrowImages(visImg, hidImg) {
    arrowImg.visible = visImg;
    arrowImg.hidden  = hidImg;
}


// stores the min and max years defaulted on the page
var temporalDefaults = {
        minyear: '',
        maxyear: ''
    };


/* setTemporalDefaults sets the min and max year defaults for resetting
 * 
 * minyear - the minimum year default
 * maxyear - the maximum year default
 */
function setTemporalDefaults(minyear, maxyear) {
    temporalDefaults.minyear = parseInt(minyear);
    temporalDefaults.maxyear = parseInt(maxyear);
}


/* toggleArrow toggles or sets the arrow and opens/closes the associated div
 *  imgid - the id of the IMG tag being changed
 *  divid - the id of the DIV tag being opened or closed
 *  force - if null, this will cause the arrow/div to be toggled between open
 *          and closed.  Otherwise, if true, it forces the div to open; false
 *          will close it.
 */
function toggleArrow(imgid, divid, force) {
    var img = dojo.byId(imgid);
    var div = dojo.byId(divid);

    if (force == null) {
        force = (div.className == 'hidden');
    }
    
    if (force) {
        img.src = arrowImg.visible; 
        div.className = 'visible';
    }
    else {
        img.src = arrowImg.hidden;
        div.className = 'hidden';
    }
}


function update_searchtype_divs() {
    var id_div = 'hidden';
    var other_div = 'visible';

    if (dojo.byId('search_type').checked) {
        id_div = 'visible';
        other_div = 'hidden';
    }

    dojo.byId('collection_body_col1').className = other_div;
    dojo.byId('collection_body_col2').className = id_div;
}



/**************************************
  FIELD UPDATE FUNCTIONS
  *************************************/


waiting = false; // True if another call is already waiting for the update
updateSem = false; // Semaphore to prevent calls from colliding
lastChange = ''; // the ID of the last input field changed
/* waitForUpdate is a helper function to ensure only one thread is waiting
 * for the field update to complete
 */
function waitForUpdate() {
    if (!updateSem) {
        waiting = false;
        updateFields();
    }
    else {
        setTimeout('waitForUpdate()', 500);
    }
}

/* updateFields goes through the search fields and sends a request to update
 * all the fields based on what's there.
 *
 * callingFields - the field that was changed to request the update
 */
function updateFields(callingField) {
    if (callingField != null) {
        lastChange = (lastChange == '')?callingField.id:'';
    }
    if (updateSem) {
        if (!waiting) {
            waiting = true;
            waitForUpdate();
        }
        return;
    }
    updateSem = true;
    var minyear = dojo.byId('min_year');
    var maxyear = dojo.byId('max_year');
    var defaults = false;
    if (parseInt(minyear.value) == temporalDefaults.minyear &&
        parseInt(maxyear.value) == temporalDefaults.maxyear) {

        defaults = true;
    }

    if (defaults) {
        minyear.value = '';
        maxyear.value = '';
    }
    dojo.byId('updating_fields_message').style.visibility = 'visible';
    dojo.xhrGet({
            form: dojo.byId("searchform"),
            handleAs: 'xml',
            load: rebuildLists,
            error: function(error) {
                updateSem = false;
                alert("An error has occurred!");
            }
        });
    if (defaults) {
        minyear.value = temporalDefaults.minyear;
        maxyear.value = temporalDefaults.maxyear;
    }
}

/* updateCollection clears all the other select boxes before updating the
 * fields
 * 
 * callingField - the field that is calling for the udpate
 */
function updateCollection(callingField) {
    resetSelectBox('country', true);
    resetSelectBox('state_province', true);
    resetSelectBox('glacier_name', true);
    resetSelectBox('photographer_name', true);

    updateFields(callingField);
}


/* updateCountry clears the glacier and photographer fields before updating the
 * fields.
 *
 * callingField - the field that is calling for the update
 */
function updateCountry(callingField) {
    resetSelectBox('glacier_name', true);
    resetSelectBox('photographer_name', true);

    if (dojo.byId('country').options[0].selected) {
        callingField = null;
    }

    updateFields(callingField);
}


/* getFieldValues returns a list of values for a specific field.
 * 
 * xml - the XML root node
 * fieldRootName - the name of the "root" tag for the field to find values for
 * fieldName - the name of the tag containing the individual value
 */
function getFieldValues(xml, fieldRootName, fieldName) {
    var list = new Array();

    var fieldRoot = xml.getElementsByTagName(fieldRootName);    
    if (fieldRoot == null || fieldRoot.length == 0) {
        return list;
    }
    
    var nodes = fieldRoot[0].getElementsByTagName(fieldName);
    for (var i = 0; i < nodes.length; i++) {
        var value = nodes[i].firstChild.nodeValue;
        if (value != null) list.push(value);
    }

    return list;
}


/* parseListXml parses the xml and returns an associative array of new lists;
 * the keys of the array correspond with the select lists to update
 */
function parseListXml(xml) {
    var list;
    var newlists = new Object();

    var rootnode = xml.getElementsByTagName('fields');

    if (rootnode == null || rootnode.length == 0) {
        return newlists;
    }

    newlists['country'] = getFieldValues(xml, 'countries', 'country');
    newlists['state_province'] = getFieldValues(xml, 'states_provinces', 'state_province');
    newlists['glacier_name'] = getFieldValues(xml, 'glaciers', 'glacier_name');
    newlists['photographer_name'] = getFieldValues(xml, 'photographers', 'photographer_name');
    
    return newlists;
}


/* isSpatialDefault returns true if the spatial fields are in their default
 * state, false if not.
 */
function isSpatialDefault() {
    isDefault =
        dojo.byId('north').value == '90' &&
        dojo.byId('south').value == '-90' &&
        dojo.byId('west').value == '-180' &&
        dojo.byId('east').value == '180';

    return isDefault;
}


/* resetSpatial resets all spatial values to their default state
 * 
 * noUpdate - optional; if true, will not update the other fields
 */
function resetSpatial(noUpdate) {
    dojo.byId('north').value = '90';
    dojo.byId('south').value = '-90';
    dojo.byId('west').value = '-180';
    dojo.byId('east').value = '180';

    if (noUpdate == true) return;

    updateFields(dojo.byId('north'));
}


/* resetTemporal resets the min and max years to the default values
 *
 * noUpdate - optional; if true, will not update the other fields
 */
function resetTemporal(noUpdate) {
    dojo.byId('min_year').value = temporalDefaults.minyear;
    dojo.byId('max_year').value = temporalDefaults.maxyear;

    if (noUpdate == true) return;
    
    updateFields(dojo.byId('min_year'));
}
        

/* resetSelectBox clears all the selections in the specified select box
 * 
 * boxId - the ID of the box to clear
 * noUpdate - optional; if true, will not update the other fields
 */
function resetSelectBox(boxId, noUpdate) {
    var selBox = dojo.byId(boxId);

    for (var j = 0; j < selBox.options.length; j++) {
        selBox.options[j].selected = (j == 0);
    }

    if (noUpdate == true) return;

    updateFields(dojo.byId(boxId));
}


/* rebuildLists is a callback function that parses the XML returned from
 * the list update script and repopulates the select lists based on those
 * results
 *
 * xml - the xml text to build the lists from
 */
function rebuildLists(xml) {
    var selected;
    var list;
    //var ids = new Array('country','state_province',
    //                    'glacier_name','photographer_name');

    var newlists = parseListXml(xml);

    // go through the select lists to repopulate
    for (var id in newlists) {
        if (id == lastChange) {
            continue;
        }
        list = dojo.byId(id);
        selected = new Array();
        // get the selected elements, and remove all options
        while (list.options.length > 1) {
            if (list.options[1].selected) {
                selected.push(list.options[1].value);
            }
            list.remove(1);
        }
        if (!isSpatialDefault() && (id == 'country' || id == 'state_province')){
            continue;
        }
        for (var j = 0; j < newlists[id].length; j++) {
            var value = newlists[id][j];
            var opt = new Option(value, value);
            try {
                list.add(opt, null);
            } 
            catch (e) {
                list.add(opt);
            }
            for (k = 0; k < selected.length; k++) {
                if (value == selected[k]) {
                    list.options[list.length-1].selected = true;
                }
            }
        }

    }

    var temporal = xml.getElementsByTagName('temporal');
    if (temporal.length > 0) {
        var curmin = dojo.byId('min_year');
        var curmax = dojo.byId('max_year');

        var defaultTemporal = false;
        if (parseInt(curmin.value) == temporalDefaults.minyear &&
            parseInt(curmax.value) == temporalDefaults.maxyear) {

            defaultTemporal = true;
        }
        
        var node = temporal[0];
        var minyear = node.getAttribute('min_year');
        var maxyear = node.getAttribute('max_year');
        setTemporalDefaults(minyear, maxyear);

        if (defaultTemporal) {
            curmin.value = minyear;
            curmax.value = maxyear;
        }        
    }

    updateSem = false;
    lastChange = '';
    dojo.byId('updating_fields_message').style.visibility = 'hidden';
}


/* resetAllSearchFields resets all the search fields to their defaults.
 */
function resetAllSearchFields() {
    resetSpatial(true);
    resetTemporal(true);

    var fields = new Array('collection', 'country', 'state_province', 
                           'glacier_name', 'photographer_name');

    for (var i = 0; i < fields.length; i++) {
        resetSelectBox(fields[i], true);
    }

    updateFields('');
}




/**************************************
  RESULTS SECTION FUNCTIONS
  *************************************/

var sortImg = {
        asc  : '/images/triangle_up.png',
        desc : '/images/triangle_down.png'
    };


/* newSearch clears the search fields and results to start a new search.
   Previously ordered results are unaffected
 */
function newSearch() {
    resetAllSearchFields();
    dojo.byId('query_summary').innerHTML = '';
    rebuildResults(null);
    
    toggleArrow('search_arrow','search_body',true);
    toggleArrow('results_arrow','results_body',false);
    toggleArrow('order_arrow','order_body',false);
}

/* buildSummaryFromList creates an html string for a hidden input field,
 * and updates the summary section for the specified list in the search section
 *
 * listId - the ID of the list element
 * label - the label to use with the summary
 */
function buildSummaryFromList(listId, label) {
    var list = dojo.byId(listId);
    var inputs = '';
    var found = false;
    if (list == null) return '';
    dojo.byId('query_summary').innerHTML += '<b>' + label + '</b> : ';

    for (var i = 0; i < list.options.length; i++) {
        if (list.options[i].selected) {
            if (list.options[i].value != '') {
                if (found) dojo.byId('query_summary').innerHTML += ', ';
                found = true;
                var newtext = list.options[i].value;
                if (listId == 'photographer_name') {
                    newtext = '"' + newtext + '"';
                }
                dojo.byId('query_summary').innerHTML += newtext;
            }
            inputs += '<input type="hidden" name="' + listId + '" ' + 
                        'id="hid_' + listId + '" ' +
                        'value="' + list.options[i].value + '" />\n';
        }
    }

    if (!found) {
        dojo.byId('query_summary').innerHTML += '(Any values)';
    }

    dojo.byId('query_summary').innerHTML += '<br>';

    return inputs;
}


/* buildSummaryFromText creates an html string for a hidden input field
 * and updates the summary section for the specified input field in the search
 * section
 *
 * textId - the ID of the text element
 * label - the label to use with the summary
 */
function buildSummaryFromText(textId, label) {
    var text = dojo.byId(textId);
    var input = '';
    
    dojo.byId('query_summary').innerHTML += '<b>' + label + '</b> : ';
    if (text == null) {
        dojo.byId('query_summary').innerHTML += '(none entered)<br>';
        return '';
    }
    else {
        dojo.byId('query_summary').innerHTML += text.value + '<br>';
        input = '<input type="hidden" name="' + textId + '" ' +
                    'value="' + text.value + '" />\n';
        return input;
    }
}
     

/* buildLastSearch goes through the Search section and builds the search
 * summary, as well as creating the elements used for executing the query
 * by the pagination code.
 */
function buildLastSearch() {
    var inputs = '';
    dojo.byId('query_summary').innerHTML = '';

    if (!dojo.byId('search_type').checked) {
    
        inputs += buildSummaryFromList('collection', 'Collections');
        inputs += buildSummaryFromList('country', 'Countries');
        inputs += buildSummaryFromList('state_province', 'States/Provinces');
        inputs += buildSummaryFromList('glacier_name', 'Glacier Names');
        inputs += buildSummaryFromList('photographer_name', 'Photographer Names');

        dojo.byId('query_summary').innerHTML += '<br><b>Spatial Criteria:</b><br>';
        inputs += buildSummaryFromText('north', 'North');
        inputs += buildSummaryFromText('west', 'West');
        inputs += buildSummaryFromText('east', 'East');
        inputs += buildSummaryFromText('south', 'South');

        dojo.byId('query_summary').innerHTML += '<br><b>Temporal Criteria:</b><br>';
        inputs += buildSummaryFromText('min_year', 'Minimum Year');
        inputs += buildSummaryFromText('max_year', 'Maximum Year');
    
        var minyear = dojo.byId('min_year');
        var maxyear = dojo.byId('max_year');
        var defaults = false;
        if (parseInt(minyear.value) == temporalDefaults.minyear &&
            parseInt(maxyear.value) == temporalDefaults.maxyear) {

            defaults = true;
        }

        if (defaults) {
            inputs = inputs.replace(/name="min_year" value=".*?"/, 'name="min_year" value=""');
            inputs = inputs.replace(/name="max_year" value=".*?"/, 'name="max_year" value=""');
        }
    }
    else {
        var photos = dojo.byId('photo_id_field').value;
        var photolist = photos.split('\n');
        dojo.byId('query_summary').innerHTML += '<b>Photo IDs</b> : ';
        for (var i = 0; i < photolist.length; i++) {
            if (i > 0) {
                dojo.byId('query_summary').innerHTML += ', ';
            }
            dojo.byId('query_summary').innerHTML += '"' + photolist[i] + '"';

            inputs += '<input type="hidden" name="photo_id" ' +
                        'value="' + photolist[i] + '" />\n';
        }
    }

    dojo.byId('last_search_info').innerHTML = inputs;
}

/* doSearch executes a new search, and opens the results section
 */
function doSearch(resetPages) {
    buildLastSearch();
    if (resetPages) {
        dojo.byId('cur_page').value = '1';
    } 
    dojo.byId('cur_page').value = '1';
    dojo.byId('offset').value = '0';
    dojo.byId('sort').value = 'photo_id';
    dojo.byId('sortdir').value = 'asc';
        
    dojo.byId('glacier_name_head').className = '';
    dojo.byId('photographer_name_head').className = '';
    dojo.byId('date_head').className = '';
    dojo.byId('photo_id_head').className = '';
    
    var sortImgSrc = sortImg.asc;
    if (dojo.byId('hid_collection') != null &&
        dojo.byId('hid_collection').value == 'repeat') {
        sortImgSrc = '';
    }
    else {
        dojo.byId('photo_id_head').className = 'sorted_column';
    }
    
    dojo.byId('glacier_name_sort').src = sortImgSrc;
    dojo.byId('photographer_name_sort').src = sortImgSrc;
    dojo.byId('date_sort').src = sortImgSrc;
    dojo.byId('other_glacier_sort').src = sortImgSrc;
    dojo.byId('photo_id_sort').src = sortImgSrc;

    getResultsPage();
    toggleArrow('search_arrow','search_body',false);
    toggleArrow('results_arrow','results_body',true);
}

/* getResultsPerPage simply finds the current value of the LIMIT field,
 * which represents the number of results to be returned per page.
 */
function getResultsPerPage() {
    var perPageList = dojo.byId('limit');
    var perpage = parseInt(perPageList.options[perPageList.selectedIndex].value);
    return perpage;
}

/* firstPage causes the results to jump to the first page of the query
 */
function firstPage() {
    var curpage = parseInt(dojo.byId('cur_page').value);
    
    if (curpage > 1) {
        dojo.byId('cur_page').value = '1';
        dojo.byId('offset').value = '0';
        getResultsPage();
    }
}

/* prevPage causes the results list to move to the previous page
 */
function prevPage() {
    var curpage = parseInt(dojo.byId('cur_page').value);
    var offset  = parseInt(dojo.byId('offset').value);

    if (curpage > 1) {
        dojo.byId('cur_page').value = curpage - 1;
        dojo.byId('offset').value = offset - getResultsPerPage();
        getResultsPage();
    }
}

/* nextPage causes the results list to move to the next page
 */
function nextPage() {
    var curpage = parseInt(dojo.byId('cur_page').value);
    var maxpage = parseInt(dojo.byId('num_pages').value);
    var offset  = parseInt(dojo.byId('offset').value);

    if (curpage < maxpage) {
        dojo.byId('cur_page').value = curpage + 1;
        dojo.byId('offset').value = offset + getResultsPerPage();
        getResultsPage();
    }
}

/* lastPage causes the results list to jump to the last page of the query
 */
function lastPage() {
    var curpage = parseInt(dojo.byId('cur_page').value);
    var maxpage = parseInt(dojo.byId('num_pages').value);

    if (curpage < maxpage) {
        dojo.byId('cur_page').value = maxpage;
        dojo.byId('offset').value = (maxpage-1) * getResultsPerPage();
        getResultsPage();
    }
}


/* getResultsPage executes the query for the current page information, and
 * sets up the AJAX info necessary to recieve the results
 */
function getResultsPage() {
    dojo.byId('updating_results_message').style.visibility = 'visible';
    dojo.xhrGet({
            form: dojo.byId("result_pager"),
            handleAs: 'xml',
            load: rebuildResults,
            error: function(error) {
                updateSem = false;
                alert("An error has occurred: " + error);
            }
        });
}


/* rebuildResults is the AJAX callback when a results page has been returned
 * by the query code 
 *
 * xml - The XML object to parse
 */
function rebuildResults(xml) {
    var table = dojo.byId('result_table');
    while (table.rows.length > 1) {
        table.deleteRow(1);
    }

    if (xml == null) {
        return;
    }

    var rootnode = xml.getElementsByTagName('results');
    
    if (rootnode == null || rootnode.length == 0) {
        return;
    }

    // get total hits
    var numHits = parseInt(rootnode[0].getAttribute('total_hits'));

    if (numHits != parseInt(dojo.byId('num_results').innerHTML)) {
        dojo.byId('num_results').innerHTML = numHits; 
        rebuildLimitList();
    }
                   
    // calculate the number of pages
    var perPage = getResultsPerPage(); 

    var numPages;
    if (perPage != null && !isNaN(perPage)) {
        numPages = Math.ceil(numHits / perPage);
    }
    else {
        numPages = 1;
    }
    dojo.byId('num_pages').value = numPages;
                
    var pageInfo = 'Page ' + dojo.byId('cur_page').value + ' of ' + numPages;
    dojo.byId('page_info').innerHTML = pageInfo;
    dojo.byId('page_info_top').innerHTML = pageInfo;

    // parse the photos
    var photos = rootnode[0].getElementsByTagName('photos');
    if (photos == null || photos.length == 0) {
        return;
    }
    buildResultTable(table, photos[0]);

    checkSelectAll();
    
    dojo.byId('updating_results_message').style.visibility = 'hidden';
};


/* buildResultTable builds the HTML for the results table based on the current
 * page results.
 *
 * table - the table object to put the results into
 * photoroot - The node indicating the "root" of the photos list
 */
function buildResultTable(table, photoroot) {
    var photos = photoroot.childNodes;
    var collection_hid = dojo.byId('hid_collection');
    var collection = 'all';
    if (collection_hid != null) {
        collection = collection_hid.value;
    }
    var rowclass = 'norm';
    var prev_repeat = '';

    for (var i = 0; i < photos.length; i++) {
        if (photos[i].nodeName != 'photo') {
            continue;
        }
        
        var id = photos[i].getAttribute('photo_id');;
        var detail = photos[i].getAttribute('detail_url');
        var img = photos[i].getAttribute('thumbnail_url');;
        var glacier = photos[i].getAttribute('glacier_name');
        var photographer = photos[i].getAttribute('photographer_name');
        var date = photos[i].getAttribute('date');
        var other = '';
        var repeat = photos[i].getAttribute('repeat_id');

        var other_root = photos[i].getElementsByTagName('other_glaciers');
        if (other_root != null && other_root.length > 0) {
            var other_glaciers = other_root[0].getElementsByTagName('other_glacier');
            if (other_glaciers != null) {
                for (var j = 0; j < other_glaciers.length; j++) {
                    if (other != '') other += '<br>';
                    var value = other_glaciers[j].firstChild.nodeValue;
                    other += value;
                }
            }
        }
                    
        if (collection == 'repeat') {
            if (repeat != prev_repeat) {
                if (rowclass == 'repeat_0') {
                    rowclass = 'repeat_1';
                }
                else {
                    rowclass = 'repeat_0';
                }
            }
            prev_repeat = repeat;
        }
        
        buildResultRow(table, id, img, detail, glacier, photographer, date, other, rowclass);
    }
}

/* buildResultRow generates the HTML for a single photo in the results table
 *
 * table - the table object to write to
 * id - the photo id value
 * img - the URL to the thumbnail image
 * detail - the URL of the page for detailed information on the photo
 * glacier - the name of the glacier
 * photographer - the name of the photographer
 * date - the date of the photo
 * other - An HTML string of other glaciers seen in the photo
 * rowclass - the class name to use for this row
 */
function buildResultRow(table, id, img, detail, glacier, photographer, date, other, rowclass) {
    var newRow = table.insertRow(table.rows.length);
    newRow.className = rowclass;
    newRow.id = id + '_row';

    var checkCell = newRow.insertCell(0);
    var checkbox = document.createElement('input');
    checkbox.type = "checkbox";
    checkbox.id = id;
    checkbox.value = id;
    checkbox.className = 'photo_id_class';
    dojo.connect(checkbox, 'onclick', function(e) { 
            toggleResultSelect(e.target.id) }
        );
    checkCell.appendChild(checkbox);
    checkCell.className = 'checkboxColumn';
    var selIndex = photoRowIndex('selected_photo', id);
    checkbox.checked = (selIndex >= 0);

    var imgCell = newRow.insertCell(1);
    var image = document.createElement('img');
    image.src = img;
    image.title = 'Click for more information on this image';
    image.alt = 'image name';
    var atag = document.createElement('a');
    //atag.href = detail;
    atag.href = '/cgi-bin/gpd_deliver_jpg.pl?' + id;
    atag.target = '_blank';
    atag.appendChild(image);
    imgCell.className = 'imageColumn';
    imgCell.appendChild(atag);

    var glacierCell = newRow.insertCell(2);
    glacierCell.innerHTML = glacier;
    glacierCell.className = 'glacierNameColumn';

    var photographerCell = newRow.insertCell(3);
    photographerCell.innerHTML = photographer;
    photographerCell.className = 'photogNameColumn';

    var dateCell = newRow.insertCell(4);
    dateCell.innerHTML = date;
    dateCell.className = 'dateColumn';

    var otherCell = newRow.insertCell(5);
    otherCell.innerHTML = other;
    otherCell.className = 'otherGlacierColumn';

    var idCell = newRow.insertCell(6);
    idCell.innerHTML = id;
    idCell.className = 'photo_id_column';
}


/* rebuildLimitList rebuilds the list for the number of results per page.
 */
function rebuildLimitList() {
    var numresults = parseInt(dojo.byId('num_results').innerHTML);

    var listArray = new Array(50,100,500,1000);
    var la_i = 0;

    var limitList = dojo.byId('limit');
    
    for (var i = 0; i < limitList.options.length; i++) {
        var opt = limitList.options[i];
        var optval = parseInt(opt.value);

        if (optval == 20) {
            // 20 is the lowest, always ignore it
            continue;
        }
        else {
            // if it's another value, check if it should be removed, and update
            // the pointer to listARray
            if (optval > numresults) {
                limitList.remove(i);
                i--;
            }
            else {
                while (la_i < listArray.length && optval >= listArray[la_i]) {
                    la_i++;
                }
            }
        } // end if/else block
    } // end for loop
        
    // add all values that haven't been added yet.
    while (la_i < listArray.length) {
        var newval = listArray[la_i];
        // exit if the new value is higher than the number of results
        if (newval > numresults) {
            break;
        }
        // add the new option
        var newopt = new Option(newval, newval);
        try {
            limitList.add(newopt, null); // standards complant
        } catch(ex) {
            limitList.add(newopt); // IE only
        }

        la_i++;
    }
    
    var limitTop  = dojo.byId('limit_top');
    while (limitTop.options.length > 0) {
        limitTop.remove(0);
    }

    for (var i = 0; i < limitList.options.length; i++) {
        var opt = limitList.options[i];
        var optval = parseInt(opt.value);

        var newopt = new Option(optval, optval);
        try {
            limitTop.add(newopt, null); // standards complian
        } catch(ex) {
            limitTop.add(newopt); // IE only
        }

        if (limitList.selectedIndex == i) {
            limitTop.selectedIndex = i;
        }
    }

}


/* changeLimit is called when the user changes the number of results per page
 */
function changeLimit() {
    dojo.byId('cur_page').value = '1';
    dojo.byId('offset').value = '0';
    
    var limitBox = dojo.byId('limit');
    var limit = limitBox.options[limitBox.selectedIndex].value;

    var limitBox = dojo.byId('limit_top');
    for (var i = 0; i < limitBox.options.length; i++) {
        if (limitBox.options[i].value == limit) {
            limitBox.selectedIndex = i;
            break;
        }
    }

    getResultsPage();
}


/* changeLimitTop is called when the TOP limit box is changed.  It makes
   sure the two lists are in synch, and then calles the main changeLimit
   function
 */
function changeLimitTop() {
    var limitBox = dojo.byId('limit_top');
    var limit = limitBox.options[limitBox.selectedIndex].value;

    var limitBox = dojo.byId('limit');
    for (var i = 0; i < limitBox.options.length; i++) {
        if (limitBox.options[i].value == limit) {
            limitBox.selectedIndex = i;
            break;
        }
    }

    changeLimit();
}


/* toggleResultsSelect is a listener called when the checkbox for a photo is clicked
 *
 * photoId - the ID of the photograph that was clicked
 */
function toggleResultSelect(photoId) {
    if (dojo.byId(photoId) == null)
        return;

    if (dojo.byId(photoId).checked)
    {
        addPhotoToOrder(photoId);
    }
    else {
        removePhotoFromOrder(photoId);
    }    
}


/* photoRowIndex finds the index in the Selected Photos list of the photo matching
 * the specified input
 *
 * tableBase - the base name for the table and the rows of the table
 * photoId - the photoId to look for
 *
 * returns: the integer index in the selected photo list (starting with 0), or -1 if it is
 *          not in the list
 */
function photoRowIndex(tableBase, photoId) {
    var table = dojo.byId(tableBase + '_list');

    for (var i = 0; i < table.rows.length; i++) {
        if (table.rows[i].id == tableBase + '_' + photoId) {
            return i;
        }
    }

    return -1; // not found
}


/* createDeleteImage creates the delete image for an entry
 *
 * photoId - the image that should be deleted if pressed
 */
function createDeleteImage(photoId) {
    var image = document.createElement('img');
    image.src = '/images/delete_sm.jpg';
    image.title = 'Remove this photo from the list.';
    image.alt = 'delete';
    dojo.connect(image, 'onclick', function(e) { removePhotoFromOrder(photoId) });

    return image;
}

/* getImageInfoFromResults gets the image info from the results table
 *
 * photoId - the ID of the photo to get info for
 * 
 * returns: an object with the following fields:
 *    * image - the URL of the thumbnail image
 *    * name  - the glacier name
 *    * photographer - the photographer name
 *    * date - the date of the photo
 *    * other - the names of other glaicers
 *    * id - the photo id
 */
function getImageInfoFromResults(photoId) {
    var info = {};

    var row = document.getElementById(photoId + '_row');
    if (row != null) {
        var cells = row.getElementsByTagName('td');
        for (var i = 0; i < cells.length; i++) {
            switch (cells[i].className) {
                case 'imageColumn' :
                    var imgs = cells[i].getElementsByTagName('img');
                    if (imgs.length > 0) {
                        info.image = imgs[0].src;
                    }
                    break;
                case 'glacierNameColumn' :
                    info.name = cells[i].innerHTML;
                    break;
                case 'photogNameColumn' :
                    info.photographer = cells[i].innerHTML;
                    break;
                case 'dateColumn' :
                    info.date = cells[i].innerHTML;
                    break;
                case 'otherGlacierColumn' :
                    info.other = cells[i].innerHTML;
                    break;
                case 'photo_id_column' :
                    info.id = cells[i].innerHTML;
                    break;
            }
        }
    }

    return info;
}


/* addPhotoToTable adds the photo row to the specified table
 *
 * tableBase - the base name for the table and its rows
 * photoId - the ID of the photo to add
 * hidFieldName - optional.  If specified, adds a hidden input field to
 *                the row
 */
function addPhotoToTable(tableBase, photoId, hidFieldName) {
    var table = dojo.byId(tableBase + '_list');

    if (photoRowIndex(tableBase, photoId) >= 0)
        return;

    var newRow = table.insertRow(table.rows.length);
    newRow.id = tableBase + '_' + photoId;

    var image = createDeleteImage(photoId);

    // create the ID text
    var text = document.createTextNode(' ' + photoId);

    // add the photo to the search section list
    var newCell = newRow.insertCell(0);
    newCell.appendChild(image);
    newCell.appendChild(text);

    if (hidFieldName) {
        var hidInput = document.createElement('input');
        hidInput.type = 'hidden';
        hidInput.name = hidFieldName;
        hidInput.value = photoId;
        newCell.appendChild(hidInput);
    }
}


/* addFullPhotoToTable adds the photo row to the specified table with
 * all the information from the results table
 *
 * tableBase - the base name for the table and its rows
 * photoId - the ID of the photo to add
 * hidFieldName - optional.  If specified, adds a hidden input field to
 *                the row
 */
function addFullPhotoToTable(tableBase, photoId, hidFieldName) {

    var info = getImageInfoFromResults(photoId);
    if (info.image == null) return;

    var table = dojo.byId(tableBase + '_list');

    if (photoRowIndex(tableBase, photoId) >= 0)
        return;

    var newRow = table.insertRow(table.rows.length);
    newRow.id = tableBase + '_' + photoId;
    
    var delCell = newRow.insertCell(0);
    var delImg = createDeleteImage(photoId);
    delCell.className = 'deleteColumn';
    delCell.appendChild(delImg);
    
    var imgCell = newRow.insertCell(1);
    var image = document.createElement('img');
    image.src = info.image;
    image.title = 'Click for more information on this image';
    image.alt = 'image name';
    image.className = 'smallThumb';
    imgCell.className = 'smallImageColumn';
    imgCell.appendChild(image);

    var glacierCell = newRow.insertCell(2);
    glacierCell.innerHTML = info.name;
    glacierCell.className = 'glacierNameColumn';
    
    var photogCell = newRow.insertCell(3);
    photogCell.innerHTML = info.photographer;
    photogCell.className = 'photogNameColumn';

    var dateCell = newRow.insertCell(4);
    dateCell.innerHTML = info.date;
    dateCell.className = 'dateColumn';

    var otherCell = newRow.insertCell(5);
    otherCell.innerHTML = info.other;
    otherCell.className = 'otherGlacierColumn';

    var idCell = newRow.insertCell(6);
    idCell.innerHTML = info.id;
    idCell.className = 'photo_id_column';

    if (hidFieldName) {
        var hidInput = document.createElement('input');
        hidInput.type = 'hidden';
        hidInput.name = hidFieldName;
        hidInput.value = photoId;
        idCell.appendChild(hidInput);
    }


}


/* addPhotoToOrder adds the specified photo to the selected photos list
 *
 * photoId - the photo ID to add
 */
function addPhotoToOrder(photoId) {
    addPhotoToTable('selected_photo', photoId);
    addFullPhotoToTable('ordered_photo', photoId, 'request');

    checkSelectAll();
    updatePhotosInOrderCount();
}


/* removePhotoFromOrder will remove the photo from the selected list
 *
 * photoId - the photo to remove from the list
 */
function removePhotoFromOrder(photoId) {
    // remove from search section table
    var selected_table = dojo.byId('selected_photo_list');
    var index = photoRowIndex('selected_photo', photoId);

    if (index >= 0) {
        selected_table.deleteRow(index);
    }

    // remove from order summary table
    var ordered_table = dojo.byId('ordered_photo_list');
    index = photoRowIndex('ordered_photo', photoId);
    
    if (index >= 0) {
        ordered_table.deleteRow(index);
    }
    
    
    // uncheck in results list
    if (dojo.byId(photoId) != null) {
        dojo.byId(photoId).checked = false;
    } 
    checkSelectAll();
    updatePhotosInOrderCount();
}


/* selectAllPhotos will cause all currently shown photos to be selected.
 * If all were already selected, this will cause them all to be deselected instead.
 */
function selectAllPhotos() {
    var selectmode = dojo.byId('selectall').checked;

    var boxes = dojo.byId('result_table').getElementsByTagName('input');
    for (var i = 0; i < boxes.length; i++) {
        if (boxes[i].type != 'checkbox' || boxes[i].id == 'selectall') {
            continue;
        }
        boxes[i].checked = selectmode;
        toggleResultSelect(boxes[i].id);
    }
}


/* checkSelectAll checks to see if all currently shown photos have been selected.
 * If not, the select all checkbox is unchecked; otherwise, it will be checked.
 */
function checkSelectAll() {
    var boxes = dojo.byId('result_table').getElementsByTagName('input');
    for (var i = 0; i < boxes.length; i++) {
        if (boxes[i].type != 'checkbox' || boxes[i].id == 'selectall') {
            continue;
        }
        if (!boxes[i].checked) {
            dojo.byId('selectall').checked = false;
            return;
        }
    }

    dojo.byId('selectall').checked = true;
}


/* removeAllPhotos removes all selected photographs from the list
 */
function removeAllPhotos() {
    var table = dojo.byId('selected_photo_list');
    while (table.rows.length > 0) {
        var rowid = table.rows[0].id;
        removePhotoFromOrder(rowid.replace(/^selected_photo_/,''));
    }

}
   

/* updatePhotosInOrderCount updates the Span that shows the total number
 * of photos being ordered.
 */
function updatePhotosInOrderCount() {
    var table = dojo.byId('selected_photo_list');
    var ordercount = table.rows.length + ' photo';
    if (table.rows.length != 1) ordercount += 's';
    dojo.byId('num_photos_ordered').innerHTML = ordercount; 

    var selectcount = table.rows.length + ' Selected Photo';
    if (table.rows.length != 1) selectcount += 's';
    dojo.byId('num_photos_selected').innerHTML = selectcount;
}


/* doSort causes the results to be sorted on the selected column
 * It will default to ascending, but will go to descending if you 
 * click on it again.
 *
 * sortColumn - the name of the column to sort by
 */
function doSort(sortColumn) {
    if (dojo.byId('hid_collection') != null &&
        dojo.byId('hid_collection').value == 'repeat') {
        return;
    }

    var sortable = new Array('glacier_name', 'photographer_name', 'date', 'other_glacier', 'photo_id');

    for (var i = 0; i < sortable.length; i++) {
        if (sortable[i] == sortColumn) {
            if (dojo.byId('sort').value == sortColumn) {
                if (dojo.byId('sortdir').value == 'asc') {
                    dojo.byId('sortdir').value = 'desc';
                } 
                else {
                    dojo.byId('sortdir').value = 'asc';
                }
            }
            else {
                dojo.byId('sort').value = sortColumn;
                dojo.byId('sortdir').value = 'asc';
            }
            dojo.byId(sortColumn + '_head').className = 'sorted_column';
            var sortImgUrl = sortImg.asc;
            if (dojo.byId('sortdir').value == 'desc') {
                sortImgUrl = sortImg.desc;
            }
            dojo.byId(sortColumn + '_sort').src = sortImgUrl;
        }
        else {
            dojo.byId(sortable[i] + '_head').className = '';
            dojo.byId(sortable[i] + '_sort').src = sortImg.asc; 
        }
    }

    dojo.byId('cur_page').value = '1';
    dojo.byId('offset').value = '0';

    getResultsPage();
}


/* placeOrder moves to the Order section
 */
function placeOrder() {
    toggleArrow('search_arrow', 'search_body', false);
    toggleArrow('results_arrow', 'results_body', false);
    toggleArrow('order_arrow', 'order_body', true);
}
    


/**************************************
  ORDER SECTION FUNCTIONS
  *************************************/

/* toggleRegister shows or hides the full registration information, depending
 * on whether the register box was checked.
 * 
 * regBox - the object for the register checkbox
 */
function toggleRegister(regBox) {
    var inputVis = regBox.checked ? '' : 'none';

    var registerFields = document.getElementsByTagName('tr');

    for (var i = 0; i < registerFields.length; i++) {
        if (registerFields[i].getAttribute('name') != 'register_only') continue;
        registerFields[i].style.display = inputVis;
    }    
}



/* trim will clear off any whitespace from the beginnin and end of the string
 *
 * stringToTrim - any string
 * 
 * returns - a string that has no whitespace at the beginning or end.
 */
function trim(stringToTrim) {
    return stringToTrim.replace(/^\s+|\s+$/g,"");
}


/* checkRequiredText returns true if the specified text field has a value,
 * false otherwise.
 *
 * textId - the ID of the text field to check
 */
function checkRequiredText(textId) {
    var textBox = dojo.byId(textId);

    if (trim(textBox.value) == '') {
        return false;
    }
    else {
        return true;
    }
}


/* checkRequiredRadio checks to make sure that an option for the radio
 * specified is checked.
 *
 * radioName - the name of the various radio buttons
 */
function checkRequiredRadio(radioName) {
    var radios = document.getElementsByName(radioName);

    for (var i = 0; i < radios.length; i++) {
        if (radios[i].type == 'radio' && radios[i].checked) {
            return true;
        }
    }

    return false;
}


/* submitOrder processes the fields to make sure they are filled in,
 * and building the photo requests, then sends the order.
 */
function submitOrder() {
    var register = dojo.byId('register_checkbox').checked;
    var ok = true;

    var reqTextFields = new Array('first_name', 'last_name', 'email');

    if (register) {
        reqTextFields.push('organization');
        reqTextFields.push('country');
        reqTextFields.push('phone');
        reqTextFields.push('project_title');
    }
    else {
        dojo.byId('req_organization').value = 'n/a';
        dojo.byId('req_country').value = 'n/a';
        dojo.byId('req_phone').value = 'n/a';
        dojo.byId('req_project_title').value = 'n/a';
    }

    // check the required text fields
    for (var i = 0; i < reqTextFields.length; i++) {
        if (!checkRequiredText('req_' + reqTextFields[i])) {
            ok = false;
            break;
        }
    }

    if (register) {
        var reqRadio = new Array('category', 'type');

        for (var i = 0; i < reqRadio.length; i++) {
            if (!checkRequiredRadio(reqRadio[i])) {
                ok = false;
                break;
            }
        }
    } else {
        dojo.byId('req_cat_usa').checked = true;
        dojo.byId('req_type_other').checked = true;
    }

    if (!ok) {
        alert('You must fill in all required fields to proceed!');
        return;
    }

    if (!dojo.byId('req_email').value.
            match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i)) {

        alert('The email address is not in a valid format.');
        return;
    }

    var photosInOrder = false;
    var inputs = document.getElementsByTagName('input');
    for (var i = 0; i < inputs.length; i++) {
        if (inputs[i].name == 'request') {
            photosInOrder = true;
            break;
        }
    }
    if (!photosInOrder) {
        alert('You must select at least one photo to order!');
        return;
    }

    dojo.byId('orderform').submit();
}



/* resetOrderInfo resets all the order information
 */
function resetOrderInfo() {
    var fields = dojo.byId('orderform').getElementsByTagName('input');

    for (var i = 0; i < fields.length; i++) {
        if (fields[i].type == 'text') {
            fields[i].value = '';
        }
        else if (fields[i].type == 'radio') {
            fields[i].checked = false;
        }
    }

    dojo.byId('message_question_comment').value = '';
    dojo.byId('project_summary').value = '';
}


// OnLoad Event

dojo.addOnLoad(function () {
    toggleRegister(dojo.byId('register_checkbox'));
    });
