Common Custom tasks
Common_CustomTasks_VBNet\QueryBuilderTask_VBNet\QueryBuilderTask.js
 Copyright 2010 ESRI
 
 All rights reserved under the copyright laws of the United States
 and applicable international laws, treaties, and conventions.
 
 You may freely redistribute and use this sample code, with or
 without modification, provided you include the original copyright
 notice and use restrictions.
 
 See <a href="http://help.arcgis.com/en/sdk/10.0/usageRestrictions.htm">the use restrictions</a>.
 

//====================================================
// QueryBuilderTask client-side control definition
//====================================================

Type.registerNamespace('ESRI.ADF.Samples.CustomTasks');

// Constructor for the QueryBuilderTask, used here to declare member variables.  Since the task
// is implemented as an AJAX component, initialization logic is placed in the initialize function.
ESRI.ADF.Samples.CustomTasks.QueryBuilderTask = function(element) {
    ESRI.ADF.Samples.CustomTasks.QueryBuilderTask.initializeBase(this, [element]);

    this._id = null;
    this._layer = null;
    this._field = null;
    this._operator = null;
    this._sampleValue = null;
    this._fieldCache = null;
    this._valueCache = null;
}
ESRI.ADF.Samples.CustomTasks.QueryBuilderTask.prototype = {

    //===================
    // Initialization 
    //===================

    initialize: function() {
        // initialize instance members that reference child server controls on the task
        this._layerDropDownList = this.get__layerDropDownList();
        this._retrievingLayersDiv = this.get__retrievingLayersDiv();
        this._fieldDropDownList = this.get__fieldDropDownList();
        this._retrievingFieldsDiv = this.get__retrievingFieldsDiv();
        this._operatorDropDownList = this.get__operatorDropDownList();
        this._sampleValueDropDownList = this.get__sampleValueDropDownList();
        this._retrievingSampleValuesDiv = this.get__retrievingSampleValuesDiv();
        this._addToQueryButton = this.get__addToQueryButton();
        this._andButton = this.get__andButton();
        this._orButton = this.get__orButton();
        this._notButton = this.get__notButton();
        this._leftParenthesisButton = this.get__leftParenthesisButton();
        this._rightParenthesisButton = this.get__rightParenthesisButton();
        this._percentButton = this.get__percentButton();
        this._underscoreButton = this.get__underscoreButton();
        this._queryTextBox = this.get__queryTextBox();
        this._clearQueryButton = this.get__clearQueryButton();
        this._doQueryButton = this.get__doQueryButton();
        this._executingQueryDiv = this.get__executingQueryDiv();


        // Specify the task's DOM element (UI) event handlers       
        $addHandler(this._layerDropDownList, 'change', this._onLayerChanged);
        $addHandler(this._fieldDropDownList, 'change', this._onFieldChanged);
        $addHandler(this._addToQueryButton, 'click', this._addToQueryButtonClick);
        $addHandler(this._andButton, 'click', this._operatorButtonClick);
        $addHandler(this._orButton, 'click', this._operatorButtonClick);
        $addHandler(this._notButton, 'click', this._operatorButtonClick);
        $addHandler(this._underscoreButton, 'click', this._operatorButtonClick);
        $addHandler(this._percentButton, 'click', this._operatorButtonClick);
        $addHandler(this._leftParenthesisButton, 'click', this._operatorButtonClick);
        $addHandler(this._rightParenthesisButton, 'click', this._operatorButtonClick);
        $addHandler(this._operatorDropDownList, 'change', this._onOperatorChanged);
        $addHandler(this._sampleValueDropDownList, 'change', this._onSampleValueChanged);
        $addHandler(this._clearQueryButton, 'click', this._clearQueryButtonClick);
        $addHandler(this._doQueryButton, 'click', this._doQueryButtonClick);

        // Specify handlers for server-side method completion events
        this.add_onGetJsonLayersComplete(this._updateLayerDropDown);
        this.add_onGetJsonFieldsComplete(this._updateFieldDropDown);
        this.add_onGetSampleValuesComplete(this._updateValueDropDown);
        this.add_onDoQueryComplete(this._hideQueryingIndicators);

        // Call method to retrieve layers for the current map and resource.  Logic to
        // retrieve fields, operators, and sample values will also fire as a result of
        // the layer being changed.
        this.getLayers();

        // Initialize the base class
        ESRI.ADF.Samples.CustomTasks.QueryBuilderTask.callBaseMethod(this, 'initialize');
    },

    // Array mapping field types to field category (e.g. Text or Numeric)   
    FieldTypes: { 'String': 'Text', 'Char': 'Text', 'Byte': 'Numeric', 'Double': 'Numeric',
        'Float': 'Numeric', 'Long': 'Numeric', 'Int': 'Numeric', 'Int16': 'Numeric',
        'Int32': 'Numeric', 'Int64': 'Numeric', 'Short': 'Numeric', 'Single': 'Numeric'
    },

    // Arrays specifying numeric and text operators
    NumericOperators: ['=', '<', '>', '<=', '>=', '<>'],

    TextOperators: ['=', '<>', 'LIKE', 'IS', 'IS NOT'],

    //============================
    // Public property accessors
    //============================

    // Returns the object's id
    get_id: function() {
        return this._id;
    },

    // Sets the object's id
    set_id: function(value) {
        this._id = value;
    },

    // Returns the currently selected layer
    get_layer: function() {
        return this._layer;
    },

    // Sets the currently selected layer
    set_layer: function(value) {
        this._layer = value;
    },

    // Returns the currently selected field
    get_field: function() {
        return this._field;
    },

    // Sets the currently selected field
    set_field: function(value) {
        this._field = value;
    },

    // Returns the currently selected operator
    get_operator: function() {
        return this._operator;
    },

    // Sets the currently selected operator
    set_operator: function(value) {
        this._operator = value;
    },

    // Returns the currently selected sample value
    get_sampleValue: function() {
        return this._value;
    },

    // Sets the currently selected sample value
    set_sampleValue: function(value) {
        this._value = value;
    },

    //============================
    // Public functions
    //============================

    // Retrieves layers for the current map and resource(s) from the server
    getLayers: function() {
        // Hide the layers drop-down list and show the layer retrieval activity indicator
        this._retrievingLayersDiv.style.display = 'inline';
        this._layerDropDownList.style.display = 'none';

        // Call the server-side task method to retrieve the layers as JSON.  As specified in
        // the initialize method, the _updateLayerDropDown function handles the result that
        // is returned to the client.
        this.GetJsonLayers();
    },

    // Adds the specified JSON field array to the task's field cache.  The other parameters
    // are used as a key.
    addFieldsToCache: function(layerName, mapResourceName, mapID, jsonFieldArray) {
        // Instantiate the cache if it has not been
        if (!this._fieldCache)
            this._fieldCache = new Object();

        // Format the passed-in layer name, map resource name, and map ID into a key
        var fieldIndex = String.format('{0}:{1}:{2}', layerName, mapResourceName, mapID);
        // Store the passed-in JSON string as a property on the fieldCache object    
        this._fieldCache[fieldIndex] = jsonFieldArray;
    },

    // Attempts to retrieve the JSON field array specified by the passed-in parameters
    getFieldsFromCache: function(layerName, mapResourceName, mapID) {
        // Make sure the task's field cache has been instantiated
        if (!this._fieldCache)
            return null;

        // Return the property on the field cache object having a key that matches the passed-in
        // parameters
        var fieldIndex = String.format('{0}:{1}:{2}', layerName, mapResourceName, mapID);
        return this._fieldCache[fieldIndex];
    },

    // Adds the specified JSON value array to the task's value cache.  The other parameters
    // are used as a key.
    addValuesToCache: function(fieldName, layerName, mapResourceName, mapID, jsonValueArray) {
        // Instantiate the cache if it has not been
        if (!this._valueCache)
            this._valueCache = new Object();

        // Format the passed-in field name, layer name, map resource name, and map ID into a key
        var valueIndex = String.format('{0}:{1}:{2}:{3}', fieldName, layerName,
            mapResourceName, mapID);
        // Store the passed-in JSON string as a property on the valueCache object    
        this._valueCache[valueIndex] = jsonValueArray;
    },

    // Attempts to retrieve the JSON value array specified by the passed-in parameters
    getValuesFromCache: function(fieldName, layerName, mapResourceName, mapID) {
        // Make sure the task's value cache has been instantiated
        if (!this._valueCache)
            return null;

        // Return the property on the value cache object having a key that matches the passed-in
        // parameters
        var valueIndex = String.format('{0}:{1}:{2}:{3}', fieldName, layerName,
            mapResourceName, mapID);
        return this._valueCache[valueIndex];
    },

    //=============================
    // DOM Element Event Handlers
    //=============================

    // Fires when the value of the layer drop-down list changes
    _onLayerChanged: function() {
        // Get the client-side task control.  We need to do this because "this" refers to
        // the DOM element that fired the event.
        var task = this.get_task();

        // Clear the query textbox
        task._clearQuery();

        // Get the index of the currently selected item in the layer drop-down
        var layerIndex = task._layerDropDownList.selectedIndex;

        // Get the JSON encapsulating the currently selected layer's properties.  This is stored
        // as the value of items in the layer drop-down.
        var jsonLayer = task._layerDropDownList.options[layerIndex].value;

        // Use the AJAX JavaScriptSerializer to convert the JSON into an object
        var layer = Sys.Serialization.JavaScriptSerializer.deserialize(jsonLayer);

        // Update the task's layer property
        task.set_layer(layer);

        // Attempt to retrieve the layer's field information from the task's cache
        var cachedFields = task.getFieldsFromCache(layer.name, layer.mapResource, layer.map);

        // Check whether fields have already been cached for the layer
        if (cachedFields) {
            // Since fields have already been cached, fire the method that otherwise executes 
            // after fields are retrieved from the server.  We do this because we are essentially
            // substituting field retrieval from the server with retrieval from client-side cache.
            task._onGetJsonFieldsComplete(cachedFields);
        }
        else {
            // Fields for this layer have not been cached, so they need to be retrieved from 
            // the server

            // Show the field retrieval activity indicator
            task._retrievingFieldsDiv.style.display = 'inline';
            task._fieldDropDownList.style.display = 'none';

            // Call the server-side method that retrieves field information.  As specified in 
            // the client-side initialize function, the _updateFieldDropDown function processes
            // the fields that are returned to the client.
            task.GetJsonFields(jsonLayer);
        }
    },

    // Fires when the value of the fields drop-down list changes
    _onFieldChanged: function() {
        // Get the client-side task control.  We need to do this because "this" refers to
        // the DOM element that fired the event.
        var task = this.get_task();

        // Get the index of the item currently selected in the field drop-down
        var fieldIndex = task._fieldDropDownList.selectedIndex;

        // Get the JSON representation of the currently selected field.  This is stored as the
        // value of the drop-down item.
        var jsonField = task._fieldDropDownList.options[fieldIndex].value;

        // Use the AJAX JavaScriptSerializer to convert the JSON to a JavaScript object
        var field = Sys.Serialization.JavaScriptSerializer.deserialize(jsonField);

        // Update the task's field property
        task.set_field(field);

        // Call method to update the list of operators (i.e. change to text or numeric) based on 
        // the current field
        task._updateOperatorList();

        // Retrieve the currently selected layer
        var layer = task.get_layer();

        // Attempt to retrieve sample values for the field from the task's cache
        var cachedValues = task.getValuesFromCache(field.name, layer.name,
            layer.mapResource, layer.map);

        // Check whether values were found in the cache
        if (cachedValues) {
            // Since sample values have already been cached, fire the method that otherwise 
            // executes after values are retrieved from the server.  We do this because we are 
            // essentially substituting sample value retrieval from the server with retrieval from
            // client-side cache.
            task._onGetSampleValuesComplete(cachedValues);
        }
        else {
            // Sample values for this field have not been cached, so they need to be retrieved 
            // from the server

            // Show the sample value retrieval activity indicator
            task._retrievingSampleValuesDiv.style.display = 'inline';
            task._sampleValueDropDownList.style.display = 'none';

            // Call the server-side method that retrieves sample values.  As specified in the task's
            // client-side initialize function, the _updateValueDropDown function processes the 
            // values that are returned to the client.
            task.GetSampleValues(field.name, layer.id, layer.mapResource);
        }
    },

    // Fires when the value of the operator drop-down list changes
    _onOperatorChanged: function() {
        // Get the client-side task control.  We need to do this because "this" refers to
        // the DOM element that fired the event.
        var task = this.get_task();

        // Update the task's operator property with the newly selected value
        var index = task._operatorDropDownList.selectedIndex;
        task.set_operator(task._operatorDropDownList.options[index].text);
    },

    // Fires when the value of the sample value drop-down list changes
    _onSampleValueChanged: function() {
        // Get the client-side task control.  We need to do this because "this" refers to
        // the DOM element that fired the event.
        var task = this.get_task();

        // Update the task's sampleValue property with the newly selected value
        var index = task._sampleValueDropDownList.selectedIndex;
        task.set_sampleValue(task._sampleValueDropDownList.options[index].text);
    },

    // Fires when one of the operator buttons (e.g. And, Or, %, etc.) is clicked
    _operatorButtonClick: function() {
        // Get the client-side task control.  We need to do this because "this" refers to
        // the DOM element that fired the event.
        var task = this.get_task();

        // Add the text of the button to the end of the query
        task._queryTextBox.value += this.value;

        // Move the cursor in the query textbox to the end
        task._moveQueryCursorToEnd();
    },

    // Fires when the Add to Query button is clicked
    _addToQueryButtonClick: function() {
        // Get the client-side task control.  We need to do this because "this" refers to
        // the DOM element that fired the event.
        var task = this.get_task();

        // Construct a query string based on the currently selected field, operator, and
        // sample value
        var query = String.format('[{0}] {1} {2}', task.get_field().alias,
            task.get_operator(), task.get_sampleValue());

        // Add the query string to the end of the query textbox
        task._queryTextBox.value += query;

        // Move the cursor in the query textbox to the end
        task._moveQueryCursorToEnd();
    },

    // Fires when the Clear Query button is clicked
    _clearQueryButtonClick: function() {
        // Get the client-side task control.  We need to do this because "this" refers to
        // the DOM element that fired the event.
        task = this.get_task();

        // Call method to clear the query textbox
        task._clearQuery();
    },

    // Fires when the Execute Query button is clicked
    _doQueryButtonClick: function() {
        // Get the client-side task control.  We need to do this because "this" refers to
        // the DOM element that fired the event.
        var task = this.get_task();

        // Get the query from the query textbox
        var query = task._queryTextBox.value;

        // Retrieve the fields for the current layer
        var layer = task.get_layer();
        var jsonFields = task.getFieldsFromCache(layer.name, layer.mapResource, layer.map);
        var fieldArray = Sys.Serialization.JavaScriptSerializer.deserialize(jsonFields);

        // Place a backslash before single quotes in the query string.  This is needed so the
        // quotes do not prematurely close the callback invocation string.
        var replaceString = "'";
        var replaceRegEx = new RegExp(replaceString, 'g');
        query = query.replace(replaceRegEx, "\\'");

        // Loop through the current layer's fields.  For each, search for the alias in the query
        // string and replace it with the database field name.  We do this because the fields are
        // shown to the user using any aliases specified, but the database field names must be
        // used when executing a query.
        for (var i = 0; i < fieldArray.length; i++) {
            replaceString = String.format('\\[{0}\\]', fieldArray[i].alias);
            replaceRegEx = new RegExp(replaceString, 'g');
            query = query.replace(replaceRegEx, fieldArray[i].name);
        }

        // Show the query execution activity indicator
        task._executingQueryDiv.style.display = 'inline';
        task._doQueryButton.style.display = 'none';

        // Call the server-side method that will execute the query.  This method includes logic
        // to add the query results to the TaskResults container.  As specified in the task's
        // client-side initialize function, the _hideQueryingIndicators function is fired when
        // a result is returned to the client.
        task.DoQuery(query, layer.id, layer.mapResource);
    },

    //================================================
    // Server-Side Method Completion Event Handlers
    //================================================

    // Fires after a call to the server-side GetJsonLayers method has executed
    _updateLayerDropDown: function(jsonLayerArray) {
        // Use the AJAX JavaScriptSerializer to create a JavaScript array from the result
        // returned by GetJsonLayers
        var layerArray = Sys.Serialization.JavaScriptSerializer.deserialize(jsonLayerArray);

        // Set the number of options in the layer drop-down list to match the number of
        // layers in the array
        this._layerDropDownList.options.length = layerArray.length;

        // Iterate through the layers, adding each to the drop-down
        for (var i = 0; i < layerArray.length; i++) {
            var layer = layerArray[i];
            // Set the text of the current drop-down item to be the layer name
            this._layerDropDownList.options[i].text = layer.name;
            // Use the JavaScriptSerializer to revert the current layer to a JSON string
            var jsonLayer = Sys.Serialization.JavaScriptSerializer.serialize(layer);
            // Store the layer's JSON representation as the current drop-down item's value
            this._layerDropDownList.options[i].value = jsonLayer;
        }

        // Set the drop-down's selected item to the first in the list
        this._layerDropDownList.selectedIndex = 0;

        // Turn off layer retrieval activity indicators
        this._retrievingLayersDiv.style.display = 'none';
        this._layerDropDownList.style.display = 'inline';

        // Invoke the _onLayerChanged event handler to simulate a new layer being selected.
        // We invoke the method via ".call" and pass it the layer drop-down so that the
        // drop-down becomes the method's caller (i.e. references to "this" inside the
        // method will refer to the drop-down).
        this._onLayerChanged.call(this._layerDropDownList);
    },

    // Fires after a call to the server-side GetJsonFields method has executed
    _updateFieldDropDown: function(jsonFieldArray) {
        // Use the AJAX JavaScriptSerializer to create a JavaScript array from the result
        // returned by GetJsonFields
        var fieldArray = Sys.Serialization.JavaScriptSerializer.deserialize(jsonFieldArray);

        // Set the number of options in the field drop-down list to match the number of
        // fields in the array
        this._fieldDropDownList.options.length = fieldArray.length;

        // Iterate through the fields, adding each to the drop-down
        for (var i = 0; i < fieldArray.length; i++) {
            var field = fieldArray[i];
            // Set the text of the current drop-down item to be the field alias
            this._fieldDropDownList.options[i].text = field.alias;
            // Use the JavaScriptSerializer to revert the current field to a JSON string
            var jsonField = Sys.Serialization.JavaScriptSerializer.serialize(field);
            // Store the field's JSON representation as the current drop-down item's value
            this._fieldDropDownList.options[i].value = jsonField;
        }

        // Set the drop-down's selected item to the first in the list
        this._fieldDropDownList.selectedIndex = 0;

        // Get the currently selected layer
        var layer = this.get_layer();
        // If the fields have not been cached, cache them now         
        if (!this.getFieldsFromCache(layer.name, layer.mapResource, layer.map))
            this.addFieldsToCache(layer.name, layer.mapResource, layer.map, jsonFieldArray);

        // Turn off field retrieval indicators
        this._retrievingFieldsDiv.style.display = 'none';
        this._fieldDropDownList.style.display = 'inline';

        // Invoke the _onFieldChanged event handler to simulate a new field being selected.
        // We invoke the method via ".call" and pass it the field drop-down so that the
        // drop-down becomes the method's caller (i.e. references to "this" inside the
        // method will refer to the drop-down).
        this._onFieldChanged.call(this._fieldDropDownList);
    },

    // Fires after a call to the server-side GetSampleValues method has executed
    _updateValueDropDown: function(jsonValueArray) {
        // Use the AJAX JavaScriptSerializer to create a JavaScript array from the result
        // returned by GetSampleValues
        var valueArray = Sys.Serialization.JavaScriptSerializer.deserialize(jsonValueArray);

        // Get the currently selected field
        var field = this.get_field();
        // Sort the array, passing the numeric sort function if the type of the current field
        // is numeric
        if (this.FieldTypes[field.type] == 'Text')
            valueArray.sort();
        else if (this.FieldTypes[field.type] == 'Numeric')
            valueArray.sort(this._sortNumber);

        // Set the number of options in the value drop-down list to match the number of
        // values in the array
        this._sampleValueDropDownList.options.length = valueArray.length;

        // Iterate through the values, adding each to the drop-down
        for (var i = 0; i < valueArray.length; i++) {
            // If a text field is currently selected, enclose the value in single quotes
            if (this.FieldTypes[field.type] == 'Text')
                valueArray[i] = String.format("'{0}'", valueArray[i]);

            // Specify the sample value as the current item's text and value    
            this._sampleValueDropDownList.options[i].text = valueArray[i];
            this._sampleValueDropDownList.options[i].value = valueArray[i];
        }

        // Set the drop-down's selected item to the first in the list
        this._sampleValueDropDownList.selectedIndex = 0;

        // Get the current layer
        var layer = this.get_layer();
        // If the values have not been cached, cache them now
        if (!this.getValuesFromCache(field.name, layer.name, layer.mapResource, layer.map))
            this.addValuesToCache(field.name, layer.name, layer.mapResource,
                layer.map, jsonValueArray);

        // Turn off the sample values retrieval activity indicator
        this._retrievingSampleValuesDiv.style.display = 'none';
        this._sampleValueDropDownList.style.display = 'inline';

        // Invoke the _onSampleValueChanged event handler to simulate a new value being 
        // selected.  We invoke the method via ".call" and pass it the sample value drop-down 
        // so that the drop-down becomes the method's caller (i.e. references to "this" inside 
        // the method will refer to the drop-down).
        this._onSampleValueChanged.call(this._sampleValueDropDownList);
    },

    // Fires after a call to the server-side DoQuery method has executed
    _hideQueryingIndicators: function() {
        // Hide query execution activity indicator
        this._executingQueryDiv.style.display = 'none';
        this._doQueryButton.style.display = 'inline';
    },

    //=============================
    // Other Private Functions
    //=============================

    // Updates the operator drop-down based on the type of the currently selected field.  
    // Called from _onFieldChanged.
    _updateOperatorList: function() {
        // Get the currently selected field        
        var selectedField = this.get_field();

        var operatorsArray;
        // Loop through the field types defined in the FieldTypes key-value pair list
        for (fieldType in this.FieldTypes) {
            // Check whether the current field type matches that of the selected field
            if (selectedField.type == fieldType) {
                // Get the category of the current field type (e.g. Text or Numeric)
                var fieldCategory = this.FieldTypes[fieldType];
                // Construct the name of the operators array to use in populating the drop-down
                // based on the field category.  This assumes that the task contains operators
                // arrays named <FieldCategory>Operators
                var operatorsArrayString = String.format('this.{0}Operators', fieldCategory);
                // Get a reference to the operators array
                operatorsArray = eval(operatorsArrayString);
                break;
            }
        }

        // Set the number of items in the operator drop-down to match the size of the 
        // operators array
        this._operatorDropDownList.options.length = operatorsArray.length;
        // Populate the drop-down with the operators contained in the array
        for (var i = 0; i < operatorsArray.length; i++)
            this._operatorDropDownList.options[i].text = operatorsArray[i];

        // Set the first item in the drop-down to be selected
        this._operatorDropDownList.selectedIndex = 0;

        // Invoke the _onOperatorChanged event handler to simulate a new operator being 
        // selected.  We invoke the method via ".call" and pass it the operator drop-down 
        // so that the drop-down becomes the method's caller (i.e. references to "this" 
        // inside the method will refer to the drop-down).
        this._onOperatorChanged.call(this._operatorDropDownList);
    },

    // Clears the query textbox
    _clearQuery: function() {
        this._queryTextBox.value = '';
        this._moveQueryCursorToEnd();
    },

    // Puts the focus on the query textbox and moves the cursor to the end of any text
    // within it
    _moveQueryCursorToEnd: function() {
        // Get the task's DOM element and make sure it is visible
        if (this.get_element().style.display == 'none')
            return;

        // Set the focus to the query textbox                    
        this._queryTextBox.focus();
        // Get the last index in the contents of the query textbox
        endIndex = this._queryTextBox.value.length;

        // Check whether setSelectionRange is supported
        if (this._queryTextBox.setSelectionRange) {
            // Issue a call to setSelectionRange to create a zero-length selction at
            // the end of the query textbox's contents, effectively moving the cursor
            // to the end.
            this._queryTextBox.setSelectionRange(endIndex, endIndex);
        }
        else if (this._queryTextBox.createTextRange) {
            // Since setSelectionRange is not supported, we instead create and
            // manipulate a TextRange object.  The call to createTextRange will
            // create a range that covers the query textbox's contents.
            var textRange = this._queryTextBox.createTextRange();
            // Move the start of the text range to the end of the textbox's contents,
            // creating a zero-length selection
            textRange.moveStart('character', endIndex);
            // Call select to apply the selection, which moves the cursor to the
            // selection location - the end of the query text
            textRange.select();
        }
    },

    // Passed into Array.sort() to sort numbers
    _sortNumber: function(a, b) {
        return a - b;
    }
}

// Register the QueryBuilderTask class, specifying inheritance from ESRI.ADF.UI.FloatingPanel.
// Registration is placed in the AJAX init event to ensure that ADF scripts have loaded prior to
// the call.
Sys.Application.add_init(function registerQueryBuilderTask() {
    ESRI.ADF.Samples.CustomTasks.QueryBuilderTask.registerClass(
        'ESRI.ADF.Samples.CustomTasks.QueryBuilderTask', ESRI.ADF.UI.FloatingPanel);
});