Common MapTips
Common_MapTips_CSharp\JavaScript\AttributesOnDemand.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>.
 

// **************************************
//     GraphicFeatureGroup Extensions 
// **************************************

// === Public Methods ===

ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.setupMapTipsAttributesOnDemand = function(
retrievingAttributesTemplate, hasAttributesTemplate, uniqueIDField, layerID, resourceName,
callbackFunctionString) {
    /// <summary>Changes MapTips behavior so that full attribute information is retrieved
    ///     when a MapTip is expanded.
    /// <param name="retrievingAttributesTemplate" type="String">The markup to display in
    ///     the MapTip's content area when attribute information is being retrieved</param>
    /// <param name="defaultTemplate" type="String">The markup to apply to the MapTip's
    ///     content area after attribute information has been retrieved.  Placeholders for
    ///     field values should be formatted like {@FIELDNAME}.  If omitted, the default
    ///     content template is used.
    /// <param name="uniqueIDField" type="String">The name of a field that can uniquely
    ///     identify the field</param>
    /// <param name="layerID" type="String">Server-side ID of the layer on which MapTips
    ///     are being shown</param>
    /// <param name="resourceName" type="String">Server-side name of the resource containing
    ///     the layer on which MapTips have been activated</param>
    /// <param name="callbackFunctionString" type="String">Function to issue a callback to
    ///     the server-side control that retrieves attribute data for the expanded MapTip</param>
    this.set_uniqueIDField(uniqueIDField);
    this.set_layerID(layerID);
    this.set_resourceName(resourceName);

    // Loop through the graphic features in the group.  Set the flag for each indicating it doesn't
    // have attributes, associate it with its parent graphicFeatureGroup, and wire the function to
    // set the mapTips content to its mouseOver event
    for (var i = 0; i < this.getFeatureCount(); i++) {
        var graphicFeature = this.get(i);
        graphicFeature.set_hasAttributes(false);
        graphicFeature._graphicFeatureGroup = this;
        graphicFeature.add_mouseOver(graphicFeature._setMapTipsContent);
    }

    // If a template to display while attributes are being retrieved was not passed-in, create a 
    // default template
    if (!retrievingAttributesTemplate)
        retrievingAttributesTemplate = "<div style='white-space:nowrap; font-family:Arial; " +
            "font-style:italic; font-size:10pt; color:gray;'>Retrieving Attribute Data...</div>";

    // Add a hidden div to the template.  This will be populated with a feature's unique ID when that feature's
    // mapTip is displayed.  This enables getting a reference to the feature's unique ID from the mapTip.
    var featureIDDiv = String.format("<div id='uniqueGraphicFeatureID_{0}' style='display:none'>{{@{1}}}</div>",
        this.get_id(), this.get_uniqueIDField());
    retrievingAttributesTemplate += featureIDDiv;

    // Apply the template to the graphicFeatureGroup
    this.set_retrievingAttributesTemplate(retrievingAttributesTemplate);

    // If a template for display attributes that have already been retrieved was not passed-in, 
    // use the default content template
    if (!hasAttributesTemplate)
        hasAttributesTemplate = this.get_mapTips().get_contentTemplate();

    // Add the hidden unique ID div to the template
    hasAttributesTemplate += featureIDDiv;

    // Apply the template to the GraphicFeatureGroup
    this.set_hasAttributesTemplate(hasAttributesTemplate);

    // Add a handler to the graphicFeatureGroup's MapTips control to retrieve attributes when the
    // MapTip is expanded
    this.get_mapTips().add_expanded(this.get_mapTips()._retrieveMapTipsAttributes);

    // Add a reference to the graphicFeatureGroup to the group's callout and mapTips
    this.get_mapTips()._graphicFeatureGroup = this;
    this.get_mapTips().get_callout()._graphicFeatureGroup = this;

    // Use the passed-in callbackFunctionString to set the corresponding property on the graphicFeatureGroup's
    // mapTips control
    this.get_mapTips().set_callbackFunctionString(callbackFunctionString);
}

// Retrieves a graphic feature based on its unique ID.
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.getGraphicFeatureByUniqueID = function(featureID) {
    for (var i = 0; i < this.getFeatureCount(); i++) {
        var currentID = this.get(i).get_attributes()[this.get_uniqueIDField()];
        if (currentID == featureID)
            return this.get(i);
    }
}


// === Public Properties ===

// Defines the unique ID field of the graphicFeatureGroup
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.set_uniqueIDField = function(fieldName) {
    this._uniqueIDField = fieldName;
}

// Returns the unique ID field of the graphicFeatureGroup
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.get_uniqueIDField = function() {
    return this._uniqueIDField;
}

// Stores the ID of the corresponding web tier GraphicsLayer
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.set_layerID = function(id) {
    this._layerID = id;
}

// Returns the ID of the corresponding web tier GraphicsLayer
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.get_layerID = function() {
    return this._layerID;
}

// Stores the name of the web tier resource containing the web tier GraphicsLayer that 
// corresponds to the graphicFeatureGroup
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.set_resourceName = function(resourceName) {
    this._resourceName = resourceName;
}

// Returns the name of the web tier resource containing the web tier GraphicsLayer that 
// corresponds to the graphicFeatureGroup
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.get_resourceName = function() {
    return this._resourceName;
}

// Defines the template to use when displaying MapTips on features for which attributes have not yet
// been retrieved
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.set_retrievingAttributesTemplate = function(template) {
    this._retrievingAttributesTemplate = template;
}

// Returns the template to use when displaying MapTips on features for which attributes have not yet
// been retrieved
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.get_retrievingAttributesTemplate = function() {
    return this._retrievingAttributesTemplate;
}

// Defines the template to use when displaying MapTips on features for which attributes have been retrieved
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.set_hasAttributesTemplate = function(template) {
    this._hasAttributesTemplate = template;
}

// Returns the template to use when displaying MapTips on features for which attributes have been retrieved
ESRI.ADF.Graphics.GraphicFeatureGroup.prototype.get_hasAttributesTemplate = function() {
    return this._hasAttributesTemplate;
}


// === Private Methods ===

// Updates the contents of the feature's maptip based on whether or not attribute data for
// the feature has been retrieved.  Fired when the graphicFeature is moused over.
ESRI.ADF.Graphics.GraphicFeature.prototype._setMapTipsContent = function(graphicFeature) {
    // Make sure the passed-in argument is a GraphicFeature
    if (!ESRI.ADF.Graphics.GraphicFeature.isInstanceOfType(graphicFeature))
        return;

    // Get the title template for the mapTips control associated with the graphic feature
    var titleTemplate = graphicFeature.get_graphicFeatureGroup().get_mapTips().get_hoverTemplate();

    // Create the HTML for the mapTips title by binding the graphic feature's attributes to the title
    // template
    var titleMarkup = ESRI.ADF.System.templateBinder(graphicFeature.get_attributes(), titleTemplate);

    // Check whether or not attributes have already been retrieved for the graphic feature
    if (graphicFeature.get_hasAttributes()) {
        // Create the HTML for the mapTips content by binding the graphic feature's attributes
        // to the feature's hasAttributes template
        var contentMarkup = ESRI.ADF.System.templateBinder(graphicFeature.get_attributes(),
            graphicFeature.get_graphicFeatureGroup().get_hasAttributesTemplate());
    }
    else {
        // Create the HTML for the mapTips content by binding the graphic feature's attributes
        // to the feature's retrievingAttributes template.  Even if no attribute fields are included
        // in this template by the developer, this step is needed to populate the hidden div that
        // stores the associated feature's unique ID.
        var contentMarkup = ESRI.ADF.System.templateBinder(graphicFeature.get_attributes(),
            graphicFeature.get_graphicFeatureGroup().get_retrievingAttributesTemplate());
    }

    // Use the title and content markup to define the display of the mapTips
    var newLineMatch = new RegExp('\\n', 'g');
    contentMarkup = contentMarkup.replace(newLineMatch, '');
    
    var template = graphicFeature.get_graphicFeatureGroup().get_mapTips().get_callout().get_template();
    var tagMatch = new RegExp('\>\<', 'g');
    template = template.replace(tagMatch, '>                             <');
    graphicFeature.get_graphicFeatureGroup().get_mapTips().get_callout().set_template(template);

    graphicFeature.get_graphicFeatureGroup().get_mapTips().setContent(contentMarkup, titleMarkup);
}


// *********************************
//     GraphicFeature Extensions
// *********************************

// === Public Properties ===

// Defines the flag indicating whether the feature's attributes have already been retrieved
ESRI.ADF.Graphics.GraphicFeature.prototype.set_hasAttributes = function(value) {
    this._hasAttributes = value;
}

// Retrieves the flag indicating whether the feature's attributes have already been retrieved
ESRI.ADF.Graphics.GraphicFeature.prototype.get_hasAttributes = function(value) {
    return this._hasAttributes;
}

// Retrieves the graphicFeature's parent graphicFeatureGroup
ESRI.ADF.Graphics.GraphicFeature.prototype.get_graphicFeatureGroup = function() {
    return this._graphicFeatureGroup;
}


// ***************************
//     MapTips Extensions
// ***************************

// === Public Methods ===

// Retrieves the graphic feature on which the current maptip was displayed
ESRI.ADF.UI.MapTips.prototype.getCurrentFeature = function() {
    // Get the mapTip's parent graphicFeatureGroup
    var graphicFeatureGroup = this.get_graphicFeatureGroup();

    // Get the current feature's ID from the hidden unique ID div
    var featureIDDivName = String.format('uniqueGraphicFeatureID_{0}', graphicFeatureGroup.get_id());

    var currentFeatureID = $get(featureIDDivName).innerHTML;

    // parseInt not working with string beginning with "<a>"
    //    currentFeatureID = parseInt(currentFeatureID, 10);
    var firstChar = currentFeatureID.substring(0, 1);
    if (isNaN(firstChar)) {
        currentFeatureID = currentFeatureID.substring(3);
        currentFeatureID = parseInt(currentFeatureID);
    }

    // Retrieve the graphicFeature corresponding to the retrieved ID and return it
    return graphicFeatureGroup.getGraphicFeatureByUniqueID(currentFeatureID);
}

// Applies the passed-in attributes to the graphic feature indicated by the passed-in ID and updates
// the mapTip accordingly
ESRI.ADF.UI.MapTips.prototype.updateAttributes = function(attributes, featureID) {
    // Retrieve the graphicFeature corresponding to the passed-in ID from the mapTip's parent graphicFeatureGroup
    var graphicFeature = this.get_graphicFeatureGroup().getGraphicFeatureByUniqueID(featureID);
    // Update the graphicFeature with the passed-in attributes
    graphicFeature.set_attributes(attributes);
    // Set the flag indicating that the graphic feature has attribute information
    graphicFeature.set_hasAttributes(true);
    // Call private method to update the mapTip's content with the updated graphicFeature's information
    graphicFeature._setMapTipsContent(graphicFeature);
}


// === Public Properties ===

// Defines the callback function to invoke when retrieving attribute information from the server
ESRI.ADF.UI.MapTips.prototype.set_callbackFunctionString = function(functionString) {
    this._callbackFunctionString = functionString;
}

// Returns the callback function that is invoked when retrieving attribute information from the server
ESRI.ADF.UI.MapTips.prototype.get_callbackFunctionString = function() {
    return this._callbackFunctionString;
}

// Sets the graphicFeatureGroup associated with the MapTips control
ESRI.ADF.UI.MapTips.prototype.get_graphicFeatureGroup = function() {
    return this._graphicFeatureGroup;
}

// Returns the graphicFeatureGroup associated with the MapTips control
ESRI.ADF.UI.Callout.prototype.get_graphicFeatureGroup = function() {
    return this._graphicFeatureGroup;
}


// === Private Methods ===

// Issues a callback to retrieve attributes for the current graphic feature
ESRI.ADF.UI.MapTips.prototype._retrieveMapTipsAttributes = function(mapTips) {
    // Make sure the passed-in argument is a MapTips control
    if (!ESRI.ADF.UI.MapTips.isInstanceOfType(mapTips))
        return;

    // Get the MapTip's parent GraphicFeatureGroup
    var graphicFeatureGroup = mapTips.get_graphicFeatureGroup();

    // Make sure the MapTip has an associated graphicFeatureGroup and the graphicFeatureGroup has
    // a template to display while attributes are being retrieved
    if (!graphicFeatureGroup || !graphicFeatureGroup.get_retrievingAttributesTemplate())
        return;

    var contentMarkup = $get(mapTips.get_maptipContentID()).innerHTML;

    // Get the graphicFeature for which a mapTip is currently displayed
    var graphicFeature = mapTips.getCurrentFeature();

    // If the graphicFeature already has attributes, exit the method
    if (graphicFeature.get_hasAttributes())
        return;

    // Get the graphicFeature's unique ID
    var currentFeatureID = graphicFeature.get_attributes()[graphicFeatureGroup.get_uniqueIDField()];

    var context;

    // Construct the argument string to send back to the server.  This string contains the information
    // required by the server to retrieve the feature's attribute data.
    var argument = String.format('EventArg=retrieveMapTipsAttributes&GraphicFeatureGroupID={0}&FeatureID={1}' +
        '&UniqueIDField={2}&LayerID={3}&ResourceName={4}', graphicFeatureGroup.get_id(), currentFeatureID,
        graphicFeatureGroup.get_uniqueIDField(), graphicFeatureGroup.get_layerID(),
        graphicFeatureGroup.get_resourceName());

    // Execute a callback to the server
    eval(mapTips.get_callbackFunctionString());
}