// General global variables for the searches.
var layerInformation = new Hash();
var openSectors = new Array();
var MAX_ITEMS_IN_PAGE = 20;

// Global variables controlling the appearance of the search results.
var activeSortButtonId;

var SearchResultsUtils = new function () {
    // This function is a utility function to expand the results from a given
    // sector. This functionality only comes into play if a search is performed 
    // across multiple sectors and there are a lot of results to see. Only one
    // sector is opened up at any given time.
    this.expandSector = function(sectorName) {
        // Close all the other sectors that are open (alongwith paginations).
        for(var i = 0; i < openSectors.length; i++) {
            var openSectorName = openSectors[i];
            
            if (openSectorName != sectorName) {
                // Hide the current open sector.
                Effect.SlideUp(openSectorName);
                
                // Not all every result set will have a pagination line.
                var sectionPaginationToHide = $(openSectorName + "_paging");
                if (sectionPaginationToHide) {
                    sectionPaginationToHide.style.display = "none";
                }
                
                // Replace the static sector heading by the hyperlinked version.
                var sectorExpanderHTML = "<a href=\"#\" onclick=\"javascript:SearchResultsUtils.expandSector('" + 
                    openSectorName +  "')\">";
                sectorExpanderHTML += "<strong>Sector: " +  openSectorName + " (" + 
                    layerInformation.get(openSectorName) + ")</strong>";
                sectorExpanderHTML += "</a>";
                $('sector-' + openSectorName).innerHTML = sectorExpanderHTML; 
            }
        }        
    
        // Now open up the sector requested and mark the sector as open.
        Effect.SlideDown(sectorName);
        
        openSectors.clear();
        openSectors.push(sectorName);
        
        // Also show the pagination line for that sector, if available
        var sectorPaginationToDisplay = $(sectorName + "_paging");
        if (sectorPaginationToDisplay) {
            sectorPaginationToDisplay.style.display = "inline";
        }
        
        // Since this is the current sector that is being viewed remove the
        // hyperlink from the sector heading and replace with static text.
        $('sector-' + sectorName).innerHTML = "<strong>Sector: " +  sectorName + 
            " (" + layerInformation.get(sectorName) + ")</strong>";   
    };

    // This function is used to display a page of data. An AJAX call is executed on
    // the server side which fetches the data for the requestedpage. Once the response
    // comes back the table displaying the data is regenerated.
    this.showPage = function(layerName, contextName, pageNumber, totalNumberOfPages) {
        var params = activeSearcher.getUserInputs();
        params.push("pageNumber=" + pageNumber);
        
        // Since only a new page of data for the currently open layer is to be 
        // shown, the entire search (specially for the All Sectors case) need 
        // not be done. This is why a different reponse handler is being used.
        var responseHandler = new ResponseHandler();
        responseHandler.getResponseProcessor = function() {
            return function (xh) {
                // Do the following only if the call was successful, otherwise ignore.
                if (xh != null && xh.readyState == 4 && xh.status == 200) {
                    // Dispose the wait panel.
                    waitPanel.hide();
                            
                    // Process the actual response. The idea is to convert the XML into
                    // a table with each row of the table corresponding to a record.
                    var responseXML = xh.responseXML;
                    
                    // In the case of pagination there should be only 1 layer. 
                    var allLayers = responseXML.getElementsByTagName("layer");
                    
                    // If no layer is passed then it is an error situation.     
                    if (allLayers != null) {    
                        // Render the results table only if there is data in the layer.
                        var allRecords = allLayers.item(0).getElementsByTagName("record");
                        
                        if (allRecords != null && allRecords.length > 0) {
                            // If there is data, then generate the results table and
                            // plug it in the results table div element. The id of
                            // the div element is the same as the layer name.
                            $(layerName).innerHTML = SearchResultsUtils.generateResultsTable(
                                layerName, allRecords);
                        }       
                    }
                    
                    // Redo the paging table to highlight the page clicked.
                    $(layerName + "_paging").innerHTML = 
                        SearchResultsUtils.generatePagingTable(layerName, contextName, 
                            pageNumber, totalNumberOfPages);

                    // If a sort button was clicked previously then show the background 
                    // color as white. If no button was clicked then ignore.
                    if ($(activeSortButtonId)) {
                        $(activeSortButtonId).setStyle({backgroundColor: "#FFFFFF"});
                    }
                }
            };
        };
        
        var waitMessage = "Fetching data for page " + pageNumber + ", please wait...";
        
        GCROUtils.performCommand(activeSearcher.serverHandler, activeSearcher.doGet, 
            activeSearcher.name, contextName, params, responseHandler, waitMessage);
    };
    
    // This function is used to sort the data. The search is performed one more
    // time, this time with the sorting parameters specified by the user and the 
    // results redisplayed.
    this.sortResults = function(sortBy, sortOrder) {
        // Figure out the current layer. If 'All Sectors' is selected then find
        // out which one is the currently viewed one. If any other sector is
        // active then fetch it directly from the 'currentViewId'.
        var layerName = openSectors.first();
        if (layerName == undefined) {
            layerName = viewLabels[currentViewId];
        }
        
        // Recreate the original search request and add additional request 
        // parameters to control the sorting operation.
        var params = activeSearcher.getUserInputs();
        params.push("sortBy=" + sortBy);
        params.push("sortOrder=" + sortOrder);
        params.push("openSector=" + layerName);
        
        // Reset the background color of the previous sorting button, if any one
        // of them was clicked, if no sorting was performed, ignore. 
        if ($(activeSortButtonId)) {
            $(activeSortButtonId).setStyle({backgroundColor: "#BFDAFF"});
        }
        
        // Set the background color of the sorting button to white, just as a
        // visual cue to the user.
        var sortButtonId = layerName + "-" + sortBy.gsub(' ', '') + "-" + sortOrder;
        $(sortButtonId).setStyle({backgroundColor: "#FFFFFF"});
        activeSortButtonId = sortButtonId;

        // Since the data for the currently open layer is to be sorted and
        // shown, the entire search (specially for the All Sectors case) need 
        // not be done. This is why a different reponse handler is being used.
        var responseHandler = new ResponseHandler();
        responseHandler.getResponseProcessor = function() {
            return function (xh) {
                // Do the following only if the call was successful, otherwise ignore.
                if (xh != null && xh.readyState == 4 && xh.status == 200) {
                    // Dispose the wait panel.
                    waitPanel.hide();
                            
                    // Process the actual response. The idea is to convert the XML into
                    // a table with each row of the table corresponding to a record.
                    var responseXML = xh.responseXML;
                    
                    // In the case of pagination there should be only 1 layer. 
                    var allLayers = responseXML.getElementsByTagName("layer");
                    
                    // If no layer is passed then it is an error situation.     
                    if (allLayers != null) {    
                        // Render the results table only if there is data in the layer.
                        var allRecords = allLayers.item(0).getElementsByTagName("record");
                        
                        if (allRecords != null && allRecords.length > 0) {
                            // If there is data, then generate the results table and
                            // plug it in the results table div element. The id of
                            // the div element is the same as the layer name.
                            $(layerName).innerHTML = SearchResultsUtils.generateResultsTable(
                                layerName, allRecords);
                        }       
                    }

                    // If a sort button was clicked previously then show the background 
                    // color as white. If no button was clicked then ignore.
                    if ($(activeSortButtonId)) {
                        $(activeSortButtonId).setStyle({backgroundColor: "#FFFFFF"});
                    }
                }
            };
        };
        
        // The message to be displayed while the search is being performed.
        var waitMessage = "Sorting data, please wait...";
        
        // Perform the actual search.
        GCROUtils.performCommand(activeSearcher.serverHandler, activeSearcher.doGet, 
            activeSearcher.name, currentViewId, params, responseHandler, 
            waitMessage);
    };

    // This function is a convenience function to generate the paging table. It is
    // called both during the initial result preparation and during paging.
    this.generatePagingTable = function(layerName, contextName, pageNumberViewed, totalNumberOfPages) {
        var pagingTableHTML = "<table width=\"100%\">";
        pagingTableHTML += "<tr>";
        pagingTableHTML += "<td align=\"center\">";
        pagingTableHTML += "<div style=\"text-align: center;\">";
        
        for (var pageNumber = 1; pageNumber <= totalNumberOfPages; pageNumber++) {
            pagingTableHTML += "<span style=\"padding: 2px;\">";
            
            // Do not show a link for the page being currently viewed.
            if (pageNumberViewed != pageNumber) {
                pagingTableHTML += "<a href=\"#\" ";
                pagingTableHTML += "onclick=\"javascript:SearchResultsUtils.showPage("; 
                pagingTableHTML += "'" + layerName + "', ";
                pagingTableHTML += "'" + contextName + "', ";
                pagingTableHTML += pageNumber + ", ";
                pagingTableHTML += totalNumberOfPages;
                pagingTableHTML += ")\">";
                pagingTableHTML += pageNumber;
                pagingTableHTML += "</a>";
            } else {
                pagingTableHTML += "<strong>" + pageNumber + "</strong>";
            }
            
            pagingTableHTML += "</span>";
        }
        
        pagingTableHTML += "</div>";
        pagingTableHTML += "</td>";
        pagingTableHTML += "</tr>";
        pagingTableHTML += "</table>";
        
        return pagingTableHTML;
    };
    
    // This function produces a results table out of the records passed in. This
    // function is written in a way so that it can be reused across pages.
    this.generateResultsTable = function(layerName, allRecords, searchType) {
        // Results table start.
        var resultsTableHTML = "<table class=\"searchResultsTable\">";
        
        // Results table header start.
        resultsTableHTML += "<tr class=\"searchResultsTable-header-row\">";
        
        // The first record is arbitrarily chosen. The columns in that record
        // are used to generate the header. However, the X and Y are ignored
        // and a column called 'Tools' is used.
        var firstRecord = allRecords.item(0);
        var firstRecordColumns = firstRecord.getElementsByTagName("column");
        for (var q = 0; q < (firstRecordColumns.length - 3); q++) {
            var column = firstRecordColumns.item(q);
            var key = column.getElementsByTagName("key");
            
            var fieldName = key.item(0).childNodes.item(0).nodeValue;
            var cleansedFieldName = fieldName.gsub(' ', '');
            resultsTableHTML += "<th>";
            resultsTableHTML += "<table>";
            resultsTableHTML += "<tr>";
            resultsTableHTML += "<td>";
            resultsTableHTML += fieldName;
            resultsTableHTML += "</td>";
            if (allRecords.length > 1 && searchType == "Default") {
                resultsTableHTML += "<td>";
                resultsTableHTML += "<table>";
                resultsTableHTML += "<tr>";
                resultsTableHTML += "<td id=\"" + layerName + "-" + cleansedFieldName + "-asc\">";
                
                resultsTableHTML += "<a href=\"#\" onclick=\"javascript:SearchResultsUtils.sortResults(";
                resultsTableHTML += "'" + fieldName + "', 'asc')\">";
                resultsTableHTML += "<img src=\"images/dt-arrow-up.png\" " + 
                    "alt=\"Sort ascending by " + fieldName + "\" " + 
                    "title=\"Sort ascending by " + fieldName + "\" " + 
                    "class=\"esriImageToolbarDefault\"/>";
                resultsTableHTML += "</a>";
                
                resultsTableHTML += "</td>";
                resultsTableHTML += "</tr>";
                resultsTableHTML += "<tr>";
                resultsTableHTML += "<td id=\"" + layerName + "-" + cleansedFieldName + "-desc\">";
                
                resultsTableHTML += "<a href=\"#\" onclick=\"javascript:SearchResultsUtils.sortResults(";
                resultsTableHTML += "'" + fieldName + "', 'desc')\">";
                resultsTableHTML += "<img src=\"images/dt-arrow-dn.png\" " + 
                    "alt=\"Sort descending by " + fieldName + "\" " + 
                    "title=\"Sort descending by " + fieldName + "\" " + 
                    "class=\"esriImageToolbarDefault\"/>";
                resultsTableHTML += "</a>";
                
                resultsTableHTML += "</td>";
                resultsTableHTML += "</tr>";
                resultsTableHTML += "</table>";
                resultsTableHTML += "</td>";
            }
            resultsTableHTML += "</tr>";
            resultsTableHTML += "</table>";
            resultsTableHTML += "</th>";
        }
                
        // Instead of showing the headers for X and Y, the header 'Tools' is shown.
        resultsTableHTML += "<th colspan=\"2\">";
        resultsTableHTML += "Tools";
        resultsTableHTML += "</th>";
        
        // Results table header end.        
        resultsTableHTML += "</tr>";
        
        // The records are to be processed as rows.
        for (var i = 0; i < allRecords.length; i++) {
            var record = allRecords.item(i);
            
            // Record start.
            resultsTableHTML += "<tr>";
            
            // Pull the columns for this record.
            var allColumns = record.getElementsByTagName("column");
            
            // This string will store the X and Y coordinates in the form X,Y.
            var locationString = "";
            
            var objectId = "";
    
            for (var j = 0; j < allColumns.length ; j++) {
                var column = allColumns.item(j);
                
                // For each column pull out the 'key' and 'value' elements
                // and the text nodes for each of key and value. IE7 does
                // not handle the situation of a text node being null well
                // enough, thus the need for the null checks.
                var keyTag = column.getElementsByTagName("key");                
                var keyTagChildren = keyTag.item(0).childNodes;
                var keyTagFirstChild = null;
                if (keyTagChildren != null) {
                    keyTagFirstChild = keyTagChildren.item(0);
                }
                var key = "";
                if (keyTagFirstChild != null) {
                    key = keyTagFirstChild.nodeValue;
                }
                
                var valueTag = column.getElementsByTagName("value");                
                var valueTagChildren = valueTag.item(0).childNodes;
                var valueTagFirstChild = null;
                if (valueTagChildren != null) {
                    valueTagFirstChild = valueTagChildren.item(0);
                }
                var value = "";
                if (valueTagFirstChild != null) {
                    value = valueTagFirstChild.nodeValue;
                }
                
                // Do not create cells for X and Y. Instead a string (locationString)
                // will be created (in the form X,Y) that will be used elsewhere.
                if (key != "X" && key != "Y" && key != "Object id") {
                    // Data column for this record.
                    // Alternate row coloring.
                    if (i % 2 == 0) {
                        resultsTableHTML += "<td>";
                    } else {
                        resultsTableHTML += "<td class=\"searchResultsTable-data-row\">";
                    }
                    resultsTableHTML += value;
                    resultsTableHTML += "</td>";
                } else {
                    if (key == "X") {
                        locationString += value + ",";
                    } else if (key == "Y") {
                        locationString += value;
                    } else if (key == "Object id") {
                        objectId += value;
                    }
                }
            }
            
            // Now that all cells have been processed, it is time to use the
            // X,Y coordinates. In this case, a bunch of tools that require X
            // and Y are shown in the column with the header 'Tools'. The
            // following produces a table for the tools column with image links
            // for the actual tools. Each link has JS associated with it.
    
            // Cell containing tools table start.
            // Alternate row coloring.
            if (i % 2 == 0) {
                resultsTableHTML += "<td colspan=\"2\">";
            } else {
                resultsTableHTML += "<td class=\"searchResultsTable-data-row\" colspan=\"2\">";
            }
            
            // Tools table start.
            resultsTableHTML += "<table>";
            
            // Tools.
            resultsTableHTML += "<tr>";
            resultsTableHTML += "<td>";
            resultsTableHTML += "<a href=\"#\" onclick=\"SearchResultsUtils.zoomTo(" + locationString + ", " + objectId + ", '" + layerName + "')\"><img src=\"images/tasks/maptools/zoomin.png\" alt=\"Zoom To\" title=\"Zoom To\" class=\"esriImageToolbarDefault\"/></a>";
            resultsTableHTML += "</td>";
            resultsTableHTML += "<td>";
            resultsTableHTML += "<a href=\"#\" onclick=\"SearchResultsUtils.info(" + objectId + ", '" + layerName + "')\"><img src=\"images/tasks/maptools/identify.png\" alt=\"Marker Info\" title=\"Marker Info\" class=\"esriImageToolbarDefault\"/></a>";
            resultsTableHTML += "</td>";
            resultsTableHTML += "</tr>";
            
            // Tools table end.
            resultsTableHTML += "</table>";
            
            // Cell containing tools table end.
            resultsTableHTML += "</td>";
            
            // Record end.
            resultsTableHTML += "</tr>";
        }
        
        // Results table end.
        resultsTableHTML += "</table>";
        
        return resultsTableHTML;
    };
    
    // Function to zoom in to a feature selected from the results table. An AJAX
    // call is made which is handled by a PhaseListener on the server side. The
    // response is handled by the standard ESRI JavaScript-based response handler.
    // In that handler the map is refreshed.
    this.zoomTo = function(x, y, objectId, layerName) {
        var requestParameters = new Array();
        requestParameters.push("objectId=" + objectId);
        requestParameters.push("x=" + x);
        requestParameters.push("y=" + y);
        requestParameters.push("layerName=" + layerName);
        requestParameters.push("zoomFactor=0.005");
    
        var waitMessage = "Performing operation, please wait...";
        
        GCROUtils.performCommand("composite.jsf", true, "zoomToXY", currentViewId, 
            requestParameters, MapUpdateResponseHandler, waitMessage);
    };
    
    this.info = function(objectId, layerName) {
        var requestParameters = new Array();
        requestParameters.push("objectId=" + objectId);
        requestParameters.push("layerName=" + layerName);
        
        var responseHandler = new ResponseHandler();
        responseHandler.getResponseProcessor = function () {
            return function (xmlHttp) {
                // Create an instance of the hover tips window.
                var hoverTipsWindow = new HoverTipsWindow("200px", "12px");
                
                // Display the window.
                hoverTipsWindow.generateHoverTipsContent(xmlHttp);
            };
        };
    
        var waitMessage = "Performing operation, please wait...";
        
        GCROUtils.performCommand("composite.jsf", true, "info", currentViewId, 
            requestParameters, responseHandler, waitMessage);
    };        
};

function SearchResultsHandler(searcher) {
    this.searcher = searcher;
};
SearchResultsHandler.prototype = new ResponseHandler();
SearchResultsHandler.prototype.getResponseProcessor =  function () {
    return function (xh) {
        // Do the following only if the call was successful, otherwise ignore.
        if (xh != null && xh.readyState == 4 && xh.status == 200) {
            // Dispose the wait panel.
            waitPanel.hide();
                    
            // Process the actual response. The idea is to convert the XML into
            // a table with each row of the table corresponding to a record. The X
            // and Y are not to be shown as data, instead various tools are provided
            // that will use the X and Y as parameters.
            var responseXML = xh.responseXML;
            
            // The search might be against multiple layers of data. The data comes
            // back organized in layers. So pull out the layers first. 
            var allLayers = responseXML.getElementsByTagName("layer");
            
            // This is the HTML that will be displayed.
            var responseHTML = "";
            
            // Total number of records across all layers.
            var totalNumberOfRecordsAcrossAllLayers = 0;
    
            // If no layer is passed then it is an error situation.     
            if (allLayers != null) {        
                for (var layerNum = 0; layerNum < allLayers.length; layerNum++) {
                    var layer = allLayers.item(layerNum);
                    
                    // Render the results table only if there is data in the layer.
                    var allRecords = layer.getElementsByTagName("record");          
                    if (allRecords != null && allRecords.length > 0) {
                        var layerName = layer.getAttribute("name");
                        var contextName = layer.getAttribute("contextName");
                        var totalNumberOfRowsInLayer = layer.getAttribute("totalRecordsInLayer");
    
                        // Update total number of records count.
                        totalNumberOfRecordsAcrossAllLayers += new Number(totalNumberOfRowsInLayer).valueOf();
                        
                        // If there are multiple layers then the bodies are not to
                        // be shown. To control that behavior we need a script that
                        // can be activated by clicking. Start the markup for that.
                        responseHTML += "<div id='sector-" + layerName + "'>";
                        if (allLayers.length > 1) {
                            responseHTML += "<a href=\"#\" onclick=\"javascript:SearchResultsUtils.expandSector('" + layerName +  "')\">";
                            layerInformation.set(layerName, totalNumberOfRowsInLayer);
                        }
                        
                        // Layer name and number of records in parentheses.
                        responseHTML += "<strong>Sector: " +  layerName + " (" + totalNumberOfRowsInLayer + ")</strong>";
                        
                        // Close the href for the expansion script.
                        if (allLayers.length > 1) {
                            responseHTML += "</a>";                 
                        }
                        responseHTML += "</div>";
                        
                        // Determine if pagination is necessary or not. If there are
                        // more than a predefined number of rows in a layer then
                        // pagination is necessary. The variable MAX_ITEMS_IN_PAGE
                        // determines what the size of the page is to be.
                        if (totalNumberOfRowsInLayer > MAX_ITEMS_IN_PAGE) {
                            var totalNumberOfPages = Math.ceil(totalNumberOfRowsInLayer / MAX_ITEMS_IN_PAGE);
                                            
                            // The pagination line will contain the listing of pages
                            // with scripts associated with each page number that
                            // will trigger off a JavaScript call to a routine. If
                            // there is only one layer then no need to hide this.
                            if (allLayers.length > 1) {
                                responseHTML += "<div id=\"" + layerName + "_paging\" style=\"display: none;\">";
                            } else {
                                responseHTML += "<div id=\"" + layerName + "_paging\">";
                            }
                            responseHTML += SearchResultsUtils.generatePagingTable(layerName, contextName, 1, totalNumberOfPages);
                            responseHTML += "</div>";
                        }
                        
                        // The div that will hold the results table. If there is
                        // only one layer then no need to hide it initially.
                        if (allLayers.length > 1) {
                            responseHTML += "<div id=\"" + layerName + "\" style=\"display: none\"\">";
                        } else {
                            responseHTML += "<div id=\"" + layerName + "\">";
                        }                                   
                        responseHTML += SearchResultsUtils.generateResultsTable(layerName, allRecords, activeSearcher.searchType);
                        responseHTML += "</div>";
                        
                        responseHTML += "<br />";
                    }
                }
            } else {
                searchResultsPanel.setBody(responseXML.getElementsByName("result").item(0));
            }
            
            // Set the contents of the panel - header.
            searchResultsPanel.setHeader("Results of search (" + totalNumberOfRecordsAcrossAllLayers + ")");
                    
            // Set the contents of the panel - body.
            searchResultsPanel.setBody(responseHTML);
            
            // Set the contents of the panel - footer.
            searchResultsPanel.setFooter("<strong>Your search returned " + totalNumberOfRecordsAcrossAllLayers + " records</strong>");
            
            // Render and show the panel.
            searchResultsPanel.show();
    
            // If a sort button was clicked previously then show the background 
            // color as white. If no button was clicked then ignore.
            if ($(activeSortButtonId)) {
                SearchResultsUtils.expandSector(openSectors.first());
                $(activeSortButtonId).setStyle({backgroundColor: "#FFFFFF"});
            }
        
            // If a map update action has been specified then perform it. This
            // comes in handy for spatial searches where extents need to be shown.
            if (activeSearcher.mapUpdateAction != "") {
                var requestParameters = activeSearcher.getUserInputs();
                var waitMessage = "Orienting map, please wait...";
            
                GCROUtils.performCommand("composite.jsf", true, activeSearcher.mapUpdateAction, 
                    currentViewId, requestParameters, MapUpdateResponseHandler, 
                    waitMessage);
            }
 
            // As part of the map refresh, the tools associated with it are
            // also refreshed. The keyword search tool is the current tool item
            // that is active. As a result of the toolbar refresh, the current
            // tool gets activated again. This in turn causes the dialog panel
            // to show up at the end of the zoom. This can happen for any 
            // command or tool that requires a map refresh. To prevent this from
            // happening, the current tool marker is cleared so as to trick the
            // ESRI JavaScript into not activating the search tool item. 
            GCROUtils.getMap().clearCurrentToolItem();
        }
    };
};

function Searcher() {
    this.serverHandler = "composite.jsf";
    this.doGet = false;
    this.name = "Default";
    this.responseHandler = new SearchResultsHandler(this);
    this.waitMessage = "Fetching data, please wait...";
    this.mapUpdateAction = "";
    this.searchType = "Default";
    
    var prepareRequestParameters = function(paramsArray) {
        if (paramsArray) {
            var requestParameterString = "?ignore=ignore";
            paramsArray.each(
                function (param) {
                    requestParameterString += "&" + param;
                }
            );
            
            var map = GCROUtils.getMap();
            var mapId = map.id;
            var formId = map.formId;
            
            requestParameterString += "&mapId=" + mapId;
            requestParameterString += "&formId=" + formId;
            requestParameterString += "&contextName=" + currentViewId;
            requestParameterString += "&" + EsriUtils.buildRequestParams(formId);
            
            return requestParameterString;
        }
    };
    
    this.doAfterInit = function () {
    };
    
    this.handleSubmit = function () {
        // Set the active searcher.
        activeSearcher = this;
        
        // Validate the user inputs and return true if all are correct.
        if (this.validateUserInputs()) {
            // Fetch the user input.
            var params = this.getUserInputs();
            
            // Perform the actual search.
            GCROUtils.performCommand(this.serverHandler, this.doGet, this.name, 
                currentViewId, params, this.responseHandler, this.waitMessage);
                                    
            // Dispose this dialog panel.
            dialogPanel.cancel();
        }
    };
    
    this.handleCancel = function () {
        // Reset the active searcher.
        activeSearcher = null;
        
        dialogPanel.cancel();        
    };
    
    this.validateUserInputs = function () {
        return true;
    };
    
    this.getUserInputs = function () {
        return new Array();
    };
}
