﻿dojo.provide('GME');

// JScript File for Virtual Earth common functions

dojo.addOnLoad(function()
{ //need to use addOnLoad to be sure dts.ve.Map is already defined
    dojo.declare('GME.Map', dts.ve.Map, //inherits from Map.js in our embedded assembly
{
//===========================
//Constructor
//===========================
constructor: function(service, mapSettings, moduleId, portalId, userId, mapArgs)
{
    //Declare private variables and functions here
    this._map = null; //VE Map Object
    this._featureLayers = null; //will be an array holding ShapeLayers
    this._service = service; //JSON Service
    this._mapArgs = mapArgs; //Arguments passed into the map		
    this._PopupPrefix = "POPUP"; //Popup element Id Prefix
    this._currentpin = null; //Curent PushPin
    this._currentindex = 0; //Supporting clustering, this is the index of the current item in the cluster
    this._editPin = null; //the pushpin who's location is currently being edited
    this._editIndex = 0;  //the index of the current item on the pin who's location is being edited
    this.MapClickDelegate = null; //map click handler for editing point locations
    this.MouseMoveDelegate = null; //mouse move handler for editing point locations - makes sure mouse pointer remains crosshair
    this._defaultEroHide = null; //holds the map's default hide infobox function - we need to override this while editing points
    this.MouseDownDelegate = null; //mouse down handler for editing point locations - reinstates default hide infobox function
    this._moduleId = moduleId; //Current DNN Module Id
    this._portalId = portalId;
    this._userId = userId;
    this._atlasLayers = [];
    this._mapSettings = mapSettings; //Map Settings - center, zoom, criteria & AtlasLayers
    this._callbackCount = 0;
    this._dynamicWMSLayerSuffix = '_dynamic_wms';

    this.rootPath = gmePath;

    //Setup additional properties for tilesourcespec
    VETileSourceSpecification.prototype.IsVisible = false;
    VEShapeLayer.prototype.IsVisible = true;
    VEShapeLayer.prototype.LegendImage = ''; //the legend image filename

    //Setup additional properties for shapes & shapelayers
    VEShape.prototype.Bounds = ""; //bounds of the clustering
    VEShape.prototype.ObjectId = ""; //SDE objectId of the point
    VEShape.prototype.PointLocationIds = ""; //array of point location id's

    this._init();
},

// ===========================================
// M I S C   P R I V A T E   F U N C T I O N S
// ===========================================

// Initialize a new map and hold on to it
_init: function()
{
    //Initialize arrays
    this._uploadedLayers = [];
    this._featureLayers = new Hashtable();
    this._dynamicWMSLayers = new Hashtable();

    this._map = new VEMap(this._mapArgs.DivID);

    //Hide the default VE Dashboard
    this._map.HideDashboard();

    //onLoadMap handler
    this._map.onLoadMap = dojo.hitch(this, this._onLoadMap);

    //Load the map with the map arguments but use the configured centerpoint and zoom level
    var center = new VELatLong(this._mapSettings.CenterPoint.Lat, this._mapSettings.CenterPoint.Lon);
    this._map.LoadMap(center, this._mapSettings.ZoomLevel, this._mapArgs.Style, this._mapArgs.Fixed, this._mapArgs.Mode, false);
    this._map.SetScaleBarDistanceUnit(this._mapArgs.Scale);

    //create the click handler for editing point locations
    this.MapClickDelegate = dojo.hitch(this, this._MapClick);

    //get the mousedowndelegate that will reinstate the default hide infobox function
    this.MouseDownDelegate = dojo.hitch(this, this.reinstateDefaultHideInfoBox);
},

_onLoadMap: function()
{
    ///<summary> Handler for VEMap::onLoadMap </summary>

    //Listen for the callbacks of the getlayers and gettilelayers web methods
    //We'll call _GetPinData and (if necessary) load the stored session there - once we are sure all the atlas and point layers are set up
    dojo.connect(this, '_setupMapLayers', dojo.hitch(this, this._loadMapCallback));
    dojo.connect(this, '_atlasLayersCallback', dojo.hitch(this, this._loadMapCallback));

    //Setup the shapelayers - wait a little to make sure the map is ready and centered
    var setUpMapLayersFunc = dojo.hitch(this, this._setupMapLayers);
    this._service.GetLayers(this._moduleId, setUpMapLayersFunc, Utility.OnFailed);

    //Get the available atlas layers
    this._service.GetTileLayers(this._moduleId, this._portalId, dojo.hitch(this, this._atlasLayersCallback), Utility.OnFailed);

    //turn off the standard popup and attach our custom handler        
    pinHoverDelegate = dojo.hitch(this, this._PinActivate);
    this._map.AttachEvent("onmouseover", pinHoverDelegate);
    this._map.AttachEvent("onclick", pinHoverDelegate);

    //attach an event to the OnEndZoom event, can call updateSlider
    this._map.AttachEvent("onendzoom", dojo.hitch(this, this.UpdateSlider, 'zoomSliderVertical'));

    //Listen for mousemove events to update mouse position
    this._map.AttachEvent("onmousemove", dojo.hitch(this, this.UpdateMousePosition));

    //get the default hide infobox function
    this._defaultEroHide = window.ero.hide;
},

_loadMapCallback: function()
{
    ///<summary> Handler for _setupMapLayers and _atlasLayersCallback. Makes sure both have been called, then loads the map session and makes the first call to _GetPinData </summary>

    this._callbackCount++;
    if (this._callbackCount === 2)
    {
        if (this._mapSettings.Message && this._mapSettings.Message === 'Saved session does not exist.')
        {
            dtsUtility.DisplayUserMessage('Message_Toaster_Topic', this._mapSettings.Message + ' Loading map with default parameters.', 'warning');
        }
        else if (this._mapSettings.Markup || this._mapSettings.AtlasLayers.length > 0 || this._mapSettings.LayerNames.length > 0)
        {
            this._loadMapSessionCallBack(this._mapSettings);
        }

        //Do this here to be sure the layers are setup before we get points
        this._GetPinData();
    }
},

_setupMapLayers: function(layerNames)
{
    ///<summary> sets up shapelayers in an array indexed by their name </summary>
    /// <param name="layerNames">The array of point layer names</param>

    //Remove all the layers from the map	
    for (var layerName in this._featureLayers.hashtable)
    {
        //Get the layer
        var deleteLayer = this._featureLayers.get(layerName);
        if (deleteLayer) this.DeleteShapeLayer(deleteLayer);
    }

    //Clear the hashtable
    this._featureLayers.clear();

    //Now reload the hashtable and add the layers to the map
    for (var lName in layerNames)
    {
        //Create a shapelayer
        var shapeLayer = new VEShapeLayer();
        shapeLayer.SetTitle(lName);
        shapeLayer.LegendImage = layerNames[lName];

        //Add it to the map
        this.AddShapeLayer(shapeLayer);
        //Add it to the hashtable
        this._featureLayers.put(lName, shapeLayer);
    }

    //Create the legend
    this._createLegend();

    //setup the function to get new data whenever the map changes
    this._map.AttachEvent("onchangeview", dojo.hitch(this, this._GetPinData));
},

_createLegend: function()
{
    ///<summary> Creates the legend based on the point layers in this._featureLayers </summary>

    var imgPath, lName, id, shapeLayer, strHtml = '<table><caption>Point Layers</caption>';
    //loop through the hashtable in reverse so the legend is the same order as the layers in the map
    dojo.forEach(this._featureLayers.keys().reverse(), function(lName)
    {
        shapeLayer = this._featureLayers.get(lName);
        id = 'chk_' + lName.replace(' ', '_');
        imgPath = legendImgUrl + shapeLayer.LegendImage;

        strHtml += dojo.string.substitute('<tr><td class="legendItem"><input type="checkbox" id="' + id + '" checked="true" onclick="map._toggleLayerVisibility(\'${0}\', this)" /></td><td class="legendItem">${0}</td></tr>', [lName]);
        strHtml += dojo.string.substitute('<tr><td class="legendImg" colspan="2"><img src="${0}" /></td></tr>', [imgPath]);

        //hook up event handlers so if the layer is turned off some other way, the legend stays in sync
        dojo.connect(shapeLayer, 'Show', this, dojo.hitch(this, this._updateLegend, id, true));
        dojo.connect(shapeLayer, 'Hide', this, dojo.hitch(this, this._updateLegend, id, false));
    }, this);

    strHtml += '</table>';

    //insert the legend
    dojo.query('#layersTab').addContent(strHtml, 'first');

    //fix transparent pngs if necessary
    dtsUtility.FixPng(dojo.byId('layersTab'), gmePath);
},

_updateLegend: function(id, visible)
{
    ///<summary> Handler for VEShapeLayer::Show and VEShapeLayer::Hide.
    /// Updates the checked state of the appropriate input element in the legend </summary>
    /// <param name="id">the id of the checkbox element</param>
    /// <param name="visible">whether the corresponding layer is visible</param>

    var nodeList = dojo.query('#' + id, 'layersTab');
    if (nodeList.length > 0)
    {
        dojo.attr(nodeList[0], 'checked', visible);
    }
},

_toggleLayerVisibility: function(layerName, el)
{
    ///<summary> Toggles the visibility of the specified layer </summary>
    /// <param name="layerName">The point layer</param>
    /// <param name="el">The checkbox</param>

    var shapeLayer = this._featureLayers.hashtable[layerName];
    if (shapeLayer)
    {
        var action = (el.checked) ? 'Show' : 'Hide';
        shapeLayer[action]();
        shapeLayer.IsVisible = el.checked;
    }
},

_getDisplayedPtLyrs: function()
{
    ///<summary> Returns the currently visible point layers </summary>

    var pointLayer, pointLayers = [];
    dojo.forEach(this._featureLayers.keys(), function(item)
    {
        pointLayer = this._featureLayers.get(item);
        if (pointLayer.Visibility) { pointLayers.push(item); }
    }, this);
    return pointLayers;
},

_getDrawings: function()
{
    ///<summary> Returns the drawings currently in the map </summary>

    var drawingLayer = DrawingTools.DrawingLayer;
    var shape, shapeInfo, lineWidth;
    var drawings = [];
    for (var i = 0; i < drawingLayer.GetShapeCount(); i++)
    {
        shape = drawingLayer.GetShapeByIndex(i);
        if (shape)
        {
            shapeInfo = {};

            shapeInfo.IconClass = shape.GMEIconClass;
            shapeInfo.FontColor = shape.GMEFontColor;
            shapeInfo.FontSize = shape.GMEFontSize;
            shapeInfo.FontWeight = shape.GMEFontWeight;
            lineWidth = shape.GetLineWidth();
            shapeInfo.LineWidth = (lineWidth) ? lineWidth : 0;
            shapeInfo.LineColor = shape.GetLineColor();
            shapeInfo.FillColor = shape.GetFillColor();
            shapeInfo.Label = shape.GetTitle();
            shapeInfo.Points = shape.GetPoints();
            shapeInfo.ShapeType = shape.GetType();
            shapeInfo.CustomIcon = shape.GetCustomIcon();
            shapeInfo.Description = shape.GetDescription();
            shapeInfo.GMEDrawingType = shape.GMEDrawingType;

            drawings.push(shapeInfo);
        }
    }

    return drawings;
},

// =================================
// M A P    I M A G E    E X P O R T
// =================================

getMapImage: function(type)
{
    ///<summary> Downloads the current map view as an image </summary>

    //cancel any pending calls - best way I've found to insure this can be called multiple times
    if (this.getMapImageDeferred) { this.getMapImageDeferred.cancel(); }

    //get the map parameters
    var mapParams = this.GetMapParams();

    //Get only the atlasLayers that are displayed and coerce them into something I can deserialize on the server - we're not using msajax for this
    var displayedAtlasLayers = dojo.filter(this._atlasLayers, function(item) { return (item.IsLoaded && mapParams.zoom <= item.MaxVisibleLevel && mapParams.zoom >= item.MinVisibleLevel); });
    displayedAtlasLayers = dojo.map(displayedAtlasLayers, function(item) { delete item.__type; return item; });

    //Get the displayed dynamic wms layers
    var dynamicWMSLayer;
    var displayedDynamicWMSLayers = [];
    dojo.forEach(this._dynamicWMSLayers.keys(), function(item)
    {
        dynamicWMSLayer = this._dynamicWMSLayers.get(item);
        if (dynamicWMSLayer.IsLoaded)
        {
            displayedDynamicWMSLayers.push(dynamicWMSLayer);
        }
    }, this);

    //Get the displayed pointlayers
    var pointLayers = this._getDisplayedPtLyrs();

    //Get anything the user has drawn on the map using the drawing tools
    var drawings = this._getDrawings();

    /*  Because of the way dojo.io.iframe.send works, 
    /*  the only way I could find to get it to use POST
    /*  was to include a form with method=post
    /*  I was specifying method='post' in the args but it wasn't respecting it*/
    var form = document.createElement('form');
    dojo.attr(form, 'method', 'post');
    document.body.appendChild(form);

    //create our content object
    var content = {
        moduleid: this._moduleId,
        portalid: this._portalId,
        userid: this._userId,
        sessionkeysuffix: sessionKeySuffix,
        bbox: mapParams.bboxString,
        zoom: mapParams.zoom,
        atlaslayers: dojo.toJson(displayedAtlasLayers),
        dynamicwmslayers: dojo.toJson(displayedDynamicWMSLayers),
        pointlayers: dojo.toJson(pointLayers),
        drawings: dojo.toJson(drawings),
        mapstyle: this._map.GetMapStyle(),
        type: type
    };

    /*  Use dojo.io.iframe.send to post data to the handler and get back the image
    /*  This only works the first time! 
    /*  setting a timeout allows it to work again but I don't know how long it's gonna take
    /*  so we keep the deferred object and cancel it on the next call*/
    this.getMapImageDeferred = dojo.io.iframe.send({
        url: gmePath + 'map.gmemapimage.aspx',
        form: form,
        content: content,
        handleAs: 'json',
        handle: dojo.hitch(this, this._mapImageCallbackError)
    });

    //get rid of the form we created above
    document.body.removeChild(form);
},

// ===================================
// S E S S I O N   M A N A G E M E N T
// ===================================

_loadMapSessionCallBack: function(mapsettings)
{
    ///<summary> Re-set the client side based on the map settings </summary>
    try
    {
        if (!mapsettings)
        {
            dtsUtility.DisplayUserMessage('Message_Toaster_Topic', 'Saved session does not exist.', 'warning');
            return;
        }        

        //---------
        //Map style
        //---------
        //this.SetMapStyle(mapsettings.MapStyle);
        //put a timeout on this because it interferes with getting the points when we panzoom below - also interaction with panzoom causes ie6 crash
        var y = dojo.hitch(this, this.SetMapStyle, mapsettings.MapStyle);
        setTimeout(y, 350);

        //------------
        //Point layers
        //------------
        dojo.forEach(this._featureLayers.keys(), function(pointLyrName)
        {
            var shapeLayer = this._featureLayers.get(pointLyrName);
            if (shapeLayer)
            {
                //if it's in the mapsettings.LayerNames, turn it on, otherwise, turn it off
                var action = (dojo.indexOf(mapsettings.LayerNames, pointLyrName) > -1) ? 'Show' : 'Hide';
                shapeLayer[action]();
                shapeLayer.IsVisible = (action === 'Show') ? true : false;
            }
        }, this);

        //---------------------------
        //Center point and zoom level
        //---------------------------
        //put this at the bottom of the call stack to avoid an ie6 error that crashes the browser!
        this.PanZoomToPoint(mapsettings.CenterPoint.Lat, mapsettings.CenterPoint.Lon, mapsettings.ZoomLevel);

        //------------
        //Atlas layers
        //------------
        //Get the atlas layers collection from the map
        var atlasLayers = dojo.clone(this.Get_AtlasLayers());

        //Go through the map's atlas layers collection
        var zIndex, n = 0;
        dojo.forEach(atlasLayers, function(layer)
        {
            //if the layer is in the mapsettings...
            if (dojo.some(mapsettings.AtlasLayers, function(item) { return layer.LayerID === item.LayerID; }))
            {
                //it needs to be on if it is not
                n = dtsUtility.GetArrayItemIndex(mapsettings.AtlasLayers, layer, 'LayerID'); //the index of the item in the array
                zIndex = 30 - n;
                layer.zIndex = zIndex;
                //load layer into the map setting z-index appropriately if it is already in the map, update z-index and toggle visibility
                this.AddAtlasLayer(layer, zIndex);
                //set IsLoaded property to true
                layer.IsLoaded = true;
            }
            else
            {
                //it needs to be off if it is not
                if (layer.IsLoaded) this.DropAtlasLayer(layer)
                //set IsLoaded property to true
                layer.IsLoaded = false;
            }
        }, this);

        //Set the new atlasLayers array on the map object sorting it appropriately first   then build the legend      
        this.Set_AtlasLayers(atlasLayers);

        //--------
        //Drawings
        //--------
        //Get the drawings layer and clear it
        var drawingLayer = DrawingTools.DrawingLayer;
        drawingLayer.DeleteAllShapes();

        if (mapsettings.Markup && mapsettings.Markup.length > 1)
        {   //if there are drawings
            var drawings = dojo.fromJson(mapsettings.Markup);
            var shape;

            //draw each one on the map
            dojo.forEach(drawings, function(drawing)
            {
                var points = [];
                dojo.forEach(drawing.Points, function(point)
                {   //for some reason, we can't just pass item.Points to the VEShape constructor
                    points.push(new VELatLong(point.Latitude, point.Longitude));
                });

                shape = new VEShape(drawing.ShapeType, points);
                shape.SetTitle(drawing.Label);

                switch (drawing.GMEDrawingType)
                {
                    case 'Polyline':
                    case 'Polygon':
                    case 'Circle':
                        shape.SetLineWidth(drawing.LineWidth);
                        shape.SetLineColor(new VEColor(drawing.LineColor.R, drawing.LineColor.G, drawing.LineColor.B, drawing.LineColor.A));
                        shape.SetFillColor(new VEColor(drawing.FillColor.R, drawing.FillColor.G, drawing.FillColor.B, drawing.FillColor.A));
                        break;
                    case 'Label':
                        shape.SetCustomIcon(drawing.CustomIcon);
                        break;
                    case 'Point':
                        //get the custom icon from the drawing tools, adjusting for whether it was saved in/ we are in ie6 ...
                        shape.SetCustomIcon(DrawingTools.GetCustomIcon(drawing.IconClass));
                        break;
                    default:
                        break;
                }

                //need to set these properties in case the map image is exported
                shape.GMEIconClass = drawing.IconClass;
                shape.GMEFontColor = drawing.FontColor;
                shape.GMEFontSize = drawing.FontSize;
                shape.GMEFontWeight = drawing.FontWeight;
                shape.GMEDrawingType = drawing.GMEDrawingType;

                shape.HideIcon();

                drawingLayer.AddShape(shape);

                //Fix the delete link in the description
                var rx = new RegExp('DrawingTools\\.Delete\\(.*\\)', 'g');
                var shapeDesc = drawing.Description.replace(rx, 'DrawingTools.Delete(\'' + shape.GetID() + '\')');

                shape.SetDescription(shapeDesc);
            });
        }
    }
    catch (err)
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic', 'An error ocurred loading the stored session.', 'error');
    }
},

SaveMapSession: function(sessionName, userId, moduleId, callback)
{
    ///<summary> Store a map session in the database </summary>        

    //Get only the atlasLayers that are displayed - just the id's
    var displayedAtlasLayers = dojo.filter(map.Get_AtlasLayers(), function(item) { return (item.IsLoaded); });
    displayedAtlasLayers = dojo.map(displayedAtlasLayers, function(item) { return item.LayerID; });

    //Get the displayed pointlayers
    var pointLayerNames = this._getDisplayedPtLyrs();

    //Get anything the user has drawn on the map using the drawing tools
    var drawings = this._getDrawings();

    var center = this._map.GetCenter();
    this._mapSettings.CenterPoint.Lat = center.Latitude;
    this._mapSettings.CenterPoint.Lon = center.Longitude;
    this._mapSettings.ZoomLevel = this._map.GetZoomLevel();
    this._mapSettings.MapStyle = this._map.GetMapStyle();

    this._service.AddUserSession(this._mapSettings, displayedAtlasLayers, pointLayerNames, dojo.toJson(drawings), sessionName, userId, moduleId, callback, Utility.OnFailed);
},

// ==========================================
// M I S C   P U B L I C    F U N C T I O N S
// ==========================================    

Refresh: function()
{
    ///<summary> Refresh the map by re-getting the pin data </summary>

    this._GetPinData();
},

// ===========
// P O I N T S
// ===========
_GetPinData: function()
{
    /// <summary> Get the latest map data from the webservice. </summary>

    //get the map parameters
    var mapParams = this.GetMapParams();

    //call webservice   
    //Need to call this for each layer in this._featureLayers
    var layer;
    dojo.forEach(this._featureLayers.keys(), function(layerName)
    {
        //Get the layer
        layer = this._featureLayers.get(layerName);
        //always get points so we can interactively change the visibility of layers
        var def = this._service.GetPoints(mapParams.bboxString, mapParams.zoom, layerName, this._moduleId, this._portalId, this._userId, sessionKeySuffix, dojo.hitch(this, this._OnMapDataSucceeded), Utility.OnFailed);
    }, this);
    return false;
},

_OnMapDataSucceeded: function(layer)
{
    /// <summary> Receive data for map. </summary>
    /// <param name="layer">The webservice result object - array of GainsPoint objects</param>  

    if (layer != null && layer.Points != null)
    {
        //Create a new array to hold the points
        var newPoints = new Array();

        //find the layer
        var shapeLayer;
        if (this._featureLayers) shapeLayer = this._featureLayers.get(layer.LayerName);
        if (shapeLayer == null) return;

        //clear existing pins
        shapeLayer.DeleteAllShapes();

        //Loop over the points
        dojo.forEach(layer.Points, function(mapPoint)
        {
            var loc = new VELatLong(mapPoint.Location.Lat, mapPoint.Location.Lon);
            //Create the shape
            var newShape = new VEShape(VEShapeType.Pushpin, loc);
            newShape.GAINSType = "gainsPoint";
            newShape.Bounds = mapPoint.ClusterArea;
            newShape.PointLocationIds = mapPoint.ClusteredPointLocationIds;
            //Default Pin popup information  
            newShape.SetTitle("Point: " + mapPoint.PointLocationId);
            newShape.SetDescription("Loading...");

            //Classify the points
            var pinClass = mapPoint.MarkerClass;
            //can add a cl for clustered
            pinClass += (mapPoint.IsClustered == true) ? '-cl' : '';

            //IE6 requires a PNG fix - GME injects the css into the page all we need it to add the ie6 suffix
            pinClass += (dojo.isIE < 7 && dojo.isIE > 0) ? 'ie6' : '';

            newShape.SetCustomIcon('<div class="' + pinClass + '"></div>');

            //Add to array of points                    
            newPoints.push(newShape);
        });

        //Add the shape arrays to the layers
        shapeLayer.AddShape(newPoints);
        if (!shapeLayer.IsVisible) shapeLayer.Hide(); //when we add shapes the layer is made visible so we need to set its visibility according to our custom IsVisible property
    }
},

_PinActivate: function(e)
{
    /// <summary> Receives any mouse of event from VE </summary>
    /// <param name="e">The MapEvent object</param> 

    if (e.elementID)
    {
        var popupShape = this._map.GetShapeByID(e.elementID)

        if (popupShape && popupShape.GAINSType == 'gainsPoint')
        {
            //set current pin
            this._currentpin = popupShape;
            this._currentindex = 0;

            //get the content for the pin.
            this._getAJAXContent(false);
            //while that's happening, show a loading... message
            this._currentpin.SetDescription('<div id="' + this._PopupPrefix + this._currentpin.GetID() + '"><div id="infoboxLoading">Loading...</div></div>');
            this._currentpin.SetTitle("");
            this.reinstateDefaultHideInfoBox(); //reinstate the default hideinfobox function and disable the mousedown handler
        }
    }
},

_getAJAXContent: function(expandCommentingUi)
{
    /// <summary> Request content for popup. </summary>
    /// <param name="expandCommentingUi">Whether the commenting ui should be expanded when the popup is displayed</param>  

    //call the web service
    var callbackFunc = dojo.hitch(this, this._OnContentSucceeded, expandCommentingUi === true);
    this._service.GetPointPopup(this._currentpin.PointLocationIds[this._currentindex], this._currentpin.GetShapeLayer().Name, this._moduleId, this._portalId, this._userId, sessionKeySuffix, callbackFunc, Utility.OnFailed, this._currentpin.GetID());
},

_OnContentSucceeded: function(expandCommentingUi, result, ID)
{
    /// <summary> Receive content for popup. </summary>  
    /// <param name="expandCommentingUi">Whether the commenting ui should be expanded</param>  
    /// <param name="result">The webservice result object - JSON PinData</param>
    /// <param name="ID">The popup ID associated with this call</param>  

    //verify this is the data for the current popup.        
    if (ID == this._currentpin.GetID() && result && result.DescriptionHtml)
    {
        if (this._map.GetMapMode() == VEMapMode.Mode3D)
        {
            //3D mode fails to be able to retrieve the div we placed earlier so resort to setting the title and description only
            this._currentpin.SetTitle('');
            this._currentpin.SetDescription(result.DescriptionHtml);
            this._map.ShowInfoBox(this._currentpin);
        }
        else
        {
            ////////////////////
            //CREATE THE CONTENT
            ////////////////////
            //create the content element
            var el = document.createElement('div');
            el.id = this._PopupPrefix + this._currentpin.GetID();
            el.innerHTML = result.DescriptionHtml;

            //------------------------------------------------
            //Add a button to load this point's data into the identify panel...
            //------------------------------------------------
            if (result.ShowDetailsButton)
            {
                var viewDetailsButton = document.createElement("div");
                viewDetailsButton.id = 'viewDetailsButton';
                viewDetailsButton.innerHTML = 'View Details';
                el.appendChild(viewDetailsButton);
                dojo.addClass(viewDetailsButton, 'siteDetailsButton');
            }

            //------------------------------------------------
            //If this is a clustered point, show the number of records
            //------------------------------------------------
            if (this._currentpin.PointLocationIds.length > 1)
            {
                var siteRecords = document.createElement('div');
                siteRecords.innerHTML = (this._currentindex + 1) + ' of ' + this._currentpin.PointLocationIds.length + ' Points';
                dojo.addClass(siteRecords, 'siteRecords');
                el.appendChild(siteRecords);
            }

            //------------------------------------------------
            // Add the NEXT / PREV buttons if this pin
            // represents multiple data points
            //------------------------------------------------
            if (this._currentpin.PointLocationIds.length > 1)
            {
                var prevButton = document.createElement('div');
                prevButton.id = 'prevButton';
                prevButton.innerHTML = 'Previous';
                el.appendChild(prevButton);
                dojo.addClass(prevButton, 'ActionButton');
                if (this._currentindex < 1)
                {
                    dojo.addClass(prevButton, 'ButtonDisabled');
                }

                var nextButton = document.createElement('div');
                nextButton.id = 'nextButton';
                nextButton.innerHTML = 'Next';
                el.appendChild(nextButton);
                dojo.addClass(nextButton, 'ActionButton');
                if (this._currentindex >= (this._currentpin.PointLocationIds.length - 1))
                {
                    dojo.addClass(nextButton, 'ButtonDisabled');
                }
            }

            ////////////////////////////////
            //SET THE CONTENT ON THE INFOBOX
            ////////////////////////////////
            //using SetDescription properly positions and sizes the infobox because the content is set before it is shown.
            this._currentpin.SetDescription('<div id="' + el.id + '">' + el.innerHTML + '</div>');
            this._map.ShowInfoBox(this._currentpin);

            /////////////////////
            //ENABLE THE CONTROLS
            /////////////////////  
            //Need to set event listeners after calling setdescription
            //------------------------------------------------
            //If this point is editable, enable the edit location button
            //------------------------------------------------
            if (result.IsEditable)
            {
                dojo.query('#editLocBtn', el.id).connect('onclick', dojo.hitch(this, this._EditPointLocation));
            }

            //addatlaslayerbutton
            var nodeList = dojo.query('.addAtlasLayerButton', el.id);
            if (nodeList && nodeList.length > 0)
            {   //if the button is there
                var showAtlasLayerButton = nodeList[0];
                var layer, zIndex;
                //get the layerid from the button attribute
                var layerId = dojo.attr(showAtlasLayerButton, 'layerId');
                //get the layer from our atlaslayers collection based on the id
                dojo.forEach(this._atlasLayers, function(item) { if (item.LayerID == layerId) { layer = item; } }, this);
                //if we found the layer and it's not already loaded
                if (layer && !layer.IsLoaded)
                {   //attach the event handler
                    //use zindex 31 that will put it on top of all others
                    dojo.connect(showAtlasLayerButton, 'click', dojo.hitch(this, this.AddAtlasLayer, layer, 31));
                }
            }

            //------------------------------------------------
            //If this point is commentable, setup the commenting ui (added by mjuniper 02/06/2009 ... using dojo)
            //------------------------------------------------
            if (result.IsCommentable)
            {
                dojo.query('.showCommentUIDiv', el.id).connect('onclick', dojo.hitch(this, this.toggleCommentDiv, 'commentingUI'));
                dojo.query('.submitFeedBack', el.id).connect('onclick', dojo.hitch(this, this.submitFeedback, true));
                if (expandCommentingUi === true) this.toggleCommentDiv('commentingUI');
            }

            //View Details button
            dojo.query('#viewDetailsButton', el.id).connect('click', dojo.hitch(this, this._LoadDetails, false))

            //------------------------------------------------
            // Add the NEXT / PREV buttons if this pin
            // represents multiple data points
            //------------------------------------------------
            if (this._currentpin.PointLocationIds.length > 1)
            {
                prevButton = dojo.byId('prevButton');
                if (prevButton && this._currentindex > 0)
                {
                    dojo.connect(prevButton, 'click', dojo.hitch(this, this._PreviousRecord));
                }
                nextButton = dojo.byId('nextButton');
                if (nextButton && this._currentindex < (this._currentpin.PointLocationIds.length - 1))
                {
                    dojo.connect(nextButton, 'click', dojo.hitch(this, this._NextRecord));
                }
            }
        } //end else this._map.GetMapMode() == VEMapMode.Mode3D
    } //end if ID == this._currentpin.GetID() && result && result.DescriptionHtml
    else
    {
        this._currentpin.SetTitle('');
        this._currentpin.SetDescription('Info not available.');
        this._map.ShowInfoBox(this._currentpin);
    }
},

_showIdPanelLoader: function()
{
    /// <summary> Shows the loading message/ image in the popup </summary> 

    try
    {
        dijit.byId('resultsTab').attr('content', '<div id="infoboxLoading">Loading...</div>');
    }
    catch (err) { /*swallow it*/ }
},

_LoadDetails: function(isReloading)
{
    /// <summary> Request content for identify panel. </summary>
    dijit.byId('sidebarTabContainer').selectChild(dijit.byId('resultsTab'));

    var pid, layerName;

    if (isReloading) //indicates whether it is reloading after submitting feedback (true) or loading from the popup 'details' button
    {   //if reloading, need to get pid and layer from the details pane in case the user has moused over other points
        pid = dojo.byId('detailsPanePID').value;
        layerName = dojo.byId('detailsPaneLayerName').value;
    }
    else
    {
        pid = this._currentpin.PointLocationIds[this._currentindex];
        layerName = this._currentpin.GetShapeLayer().Name;
    }

    this._showIdPanelLoader();

    this._service.GetPointDetails(pid, layerName, this._moduleId, this._portalId, this._userId, sessionKeySuffix, dojo.hitch(this, this._loadDetailsCallback, pid, layerName), Utility.OnFailed);
},

_loadDetailsCallback: function(pid, layerName, response)
{
    /// <summary> Receive content for identify panel. </summary>
    /// <param name="response">The webservice response. </param>
    var resultsTabEl = dojo.byId('resultsTab');
    if (resultsTabEl && response && response.DescriptionHtml)
    {
        dijit.byNode(resultsTabEl).attr('content', response.DescriptionHtml);

        //addatlaslayerbutton
        var nodeList = dojo.query('.addAtlasLayerButton', resultsTabEl);
        if (nodeList && nodeList.length > 0)
        {   //if the button is there
            var showAtlasLayerButton = nodeList[0];
            var layer, zIndex;
            //get the layerid from the button attribute
            var layerId = dojo.attr(showAtlasLayerButton, 'layerId');
            //get the layer from our atlaslayers collection based on the id
            dojo.forEach(this._atlasLayers, function(item) { if (item.LayerID == layerId) { layer = item; } }, this);
            //if we found the layer and it's not already loaded
            if (layer)
            {   //attach the event handler
                //use zindex 31 that will put it on top of all others
                dojo.connect(showAtlasLayerButton, 'click', dojo.hitch(this, this.AddAtlasLayer, layer, 31));
            }
        }

        //If this point is commentable, setup the commenting ui
        if (response.IsCommentable)
        {
            dojo.query('.submitFeedBack', resultsTabEl).connect('onclick', dojo.hitch(this, this.submitFeedback, false));

            var pidEl = dojo.create('input');
            dojo.attr(pidEl, 'type', 'hidden');
            dojo.attr(pidEl, 'id', 'detailsPanePID');
            pidEl.value = pid;
            dojo.place(pidEl, resultsTabEl, 'last');
            var layerNameEl = dojo.create('input');
            dojo.attr(layerNameEl, 'type', 'hidden');
            dojo.attr(layerNameEl, 'id', 'detailsPaneLayerName');
            layerNameEl.value = layerName;
            dojo.place(layerNameEl, resultsTabEl, 'last');
        }
    }
    else
    {
        dijit.byId('resultsTab').attr('content', '');
    }
},

_PreviousRecord: function()
{
    /// <summary> Request the previous record. </summary>  

    this._currentindex--;
    this._showInfoboxLoader();
    this._getAJAXContent(false);
},

_NextRecord: function()
{
    /// <summary> Request the next record. </summary>  

    this._currentindex++;
    this._showInfoboxLoader();
    this._getAJAXContent(false);
},

//========================================
// C O M M E N T I N G   F U N C T I O N S
//========================================

toggleCommentDiv: function(elementId)
{
    ///<summary> Shows/ hides the specified element and focuses the inputElement </summary>

    var nodes = dojo.query('.' + elementId, dojo.byId(this._PopupPrefix + this._currentpin.GetID()));
    if (!nodes || nodes.length < 1) { return; }
    var element = nodes[0];

    if (element)
    {
        dojo.toggleClass(element, 'hiddenComment');
    }

    if (!dojo.hasClass(element, 'hiddenComment'))
    {
        //focus first input
        var firstInput = dojo.query('textarea, input', element)[0];
        if (firstInput && firstInput.focus) firstInput.focus();

        window.ero.hide = function(a) { return; }; //disable closing the infobox so it doesn't go away when the user mouses off it            
        this._map.AttachEvent('onmousedown', this.MouseDownDelegate); //listen for map click to reinstate default window.ero.hide
    }
    else
    {
        this.reinstateDefaultHideInfoBox();
    }
},

reinstateDefaultHideInfoBox: function(evt)
{
    ///<summary> Reinstates the default hideinfobox function and cancels the mousedown listener </summary>

    //When a user clicks on any of the comment div, we disable the default hideinfobox function so it doesn't go away when the user mouses off it
    //This function reinstates it and is called when another pushpin is activated, a comment is submitted, or the map is clicked on
    window.ero.hide = this._defaultEroHide;
    this._map.DetachEvent('onmousedown', this.MouseDownDelegate);
},

submitFeedback: function(popup)
{
    ///<summary> Submits the feedback to the web service </summary>        

    //get the pointlocationid and  the layername, and the containerin which to look for the commenting ui elements
    var pointLocId, layerName, parentElement;
    if (popup)
    {
        pointLocId = this._currentpin.PointLocationIds[this._currentindex];
        layerName = this._currentpin.GetShapeLayer().Name;
        parentElement = dojo.byId(this._PopupPrefix + this._currentpin.GetID());
    }
    else
    {
        pointLocId = dojo.byId('detailsPanePID').value;
        layerName = dojo.byId('detailsPaneLayerName').value;
        parentElement = dojo.byId('resultsTab');
    }

    //get the comment, rating, and tag values
    var comment = dojo.query('.txtComment', parentElement)[0];
    var commentValue = '';
    if (comment) { commentValue = comment.value; }

    var ratingValue = -1;
    dojo.query('input[type="radio"]', parentElement).forEach(function(item) { if (item.checked) ratingValue = item.value; });

    var tag = dojo.query('.txtTag', parentElement)[0];
    var tagValue = '';
    if (tag) { tagValue = tag.value; }

    //make sure at least one is specified - comment, rating, tag
    var valid = (commentValue.length > 0 || (ratingValue > 0 && ratingValue < 6) || tagValue.length > 0);
    if (!valid) { dtsUtility.DisplayUserMessage('Message_Toaster_Topic', 'You must specify a comment, rating, or tag!', 'warning'); return; }

    //call webservice
    this._service.SubmitFeedback(layerName, pointLocId, commentValue, ratingValue, tagValue, this._moduleId, this._portalId, this._userId, sessionKeySuffix, dojo.hitch(this, this.FeedbackCallback, popup), dojo.hitch(this, this.FeedbackCallbackError));

    this.reinstateDefaultHideInfoBox();
},

FeedbackCallback: function(popup, response)
{
    ///<summary> Callback function for submitFeedBack </summary>

    if (!response) { dtsUtility.DisplayUserMessage('Message_Toaster_Topic', 'An error ocurred submitting your feedback.', 'error'); return response; }

    if (popup)
    {
        //get the popup again
        this._showInfoboxLoader();
        this._getAJAXContent(true);
    }
    else
    {
        //get the details again
        this._LoadDetails(true);
    }

    dtsUtility.DisplayUserMessage('Message_Toaster_Topic', 'Your feedback was successfully submitted.', 'info'); return response;
},

FeedbackCallbackError: function(response)
{
    ///<summary> Errback function for submitFeedBack </summary>

    dtsUtility.DisplayUserMessage('Message_Toaster_Topic', 'An error ocurred submitting your feedback.', 'error'); return response;
},

ExportPointsShapeFile: function(layerName)
{
    ///<summary> Exports points for the specified layername as a shapefle </summary>

    //get the map parameters
    var mapParams = this.GetMapParams();
    this._service.ExportPointsShapefile(mapParams.bboxString, layerName, this._moduleId, this._portalId, this._userId, sessionKeySuffix, dojo.hitch(this, this.ExportPointsCallback), Utility.OnFailed);
},

ExportPointsCallback: function(url)
{
    ///<summary> Callback handler for Export points </summary>

    var winRef = window.open(gmePath + "download/" + url);
    if (!winRef) dtsUtility.DisplayUserMessage('Message_Toaster_Topic', 'A popup blocker may have prevented the points from being downloaded. Please add this site to your popup blocker\'s \'allowed\' list.', 'warning');
},

//============================================
// P O I N T   L O C A T I O N   E D I T I N G
//============================================    

_EditPointLocation: function()
{
    /// <summary> Begins editing a point location </summary>  

    //keep track of the point we're editing
    this._editPin = this._map.GetShapeByID(this._currentpin.GetID())
    this._editIndex = dojo.clone(this._currentindex);

    //enable map click handler
    this._map.AttachEvent("onclick", this.MapClickDelegate);
    //hide the popup
    this._map.HideInfoBox();
    //change the mouse cursor - we use the onmousemove handler because the default cursor seems to take over whenever the mouse is moved
    dojo.byId("veMap").style.cursor = 'crosshair';
    this.MouseMoveDelegate = dojo.hitch(this, this._MouseMove);
    this._map.AttachEvent("onmousemove", this.MouseMoveDelegate);
},

_MouseMove: function(e)
{
    /// <summary> Make sure the cursor stays a crosshair </summary> 

    dojo.byId("veMap").style.cursor = 'crosshair';
},

_MapClick: function(e)
{
    // <summary> Click handler for editing point locations </summary> 

    //disable map click and mouse move handlers
    this._map.DetachEvent("onclick", this.MapClickDelegate);
    this._map.DetachEvent("onmousemove", this.MouseMoveDelegate);

    //set the cursor back to normal
    dojo.byId("veMap").style.cursor = 'normal';

    //get the pointlocationid, the layername, and the xy
    var pointLocId = this._editPin.PointLocationIds[this._editIndex];
    var layerName = this._editPin.GetShapeLayer().Name;
    var LL = this._map.PixelToLatLong(new VEPixel(e.mapX, e.mapY));

    //call webservice (webservice saves new location to the database)
    this._service.UpdatePointLocation(layerName, pointLocId, LL.Longitude, LL.Latitude, this._moduleId, this._portalId, this._userId, sessionKeySuffix, dojo.hitch(this, this.UpdatePointLocationCallback), Utility.OnFailed);
},

UpdatePointLocationCallback: function(data)
{
    // <summary> Callback handler for editing point locations </summary>

    //Initially we were going to refetch the points and re-show the popup but that (showing the popup after re-fetching) was problematic due to clustering
    var shapeLayer = this._editPin.GetShapeLayer();

    var iconString = this._editPin.GetCustomIcon();

    //remove the locationid from the current pin/ delete the current pin if it is not clustered
    if (this._editPin.PointLocationIds.length > 1)
    {
        this._editPin.PointLocationIds.splice(this._editIndex, 1);
        //if the count is now 1, change the cssclass
        if (this._editPin.PointLocationIds.length === 1)
        {
            this._editPin.SetCustomIcon(iconString.replace('-cl', ''));
        }
    }
    else
    {
        //delete the shape
        this._map.DeleteShape(this._editPin);
    }

    //Draw the new point
    var loc = new VELatLong(data.Location.Lat, data.Location.Lon);
    //Create the shape
    var newShape = new VEShape(VEShapeType.Pushpin, loc);
    newShape.GAINSType = "gainsPoint";
    newShape.Bounds = data.ClusterArea;
    newShape.PointLocationIds = data.ClusteredPointLocationIds;

    //Classify the point
    if (iconString) newShape.SetCustomIcon(iconString.replace('-cl', ''));

    //Add the shape to the layer
    shapeLayer.AddShape(newShape);

    //Set it as the current pin
    this._currentpin = newShape;
    this._currentindex = 0;

    //Get the content for the pin.        
    this._getAJAXContent(false);

    //while that's happening, show a loading... message
    this._currentpin.SetDescription('<div id="' + this._PopupPrefix + this._currentpin.GetID() + '"><div id="infoboxLoading">Loading...</div></div>');
    this._currentpin.SetTitle("Point: " + data.PointLocationId);

    //Show the popup
    this._map.ShowInfoBox(this._currentpin);
},

//================================================================
// A T L A S   L A Y E R S   A N D   U S E R   A D D E D   D A T A
//================================================================

AddKMLLayer: function(layer, zIndex)
{
    ///<summary> Adds a kml atlas layer to the map </summary>

    if (layer.IsLoaded) return;

    var shapeLayer = new VEShapeLayer();
    shapeLayer.GMETitle = layer.TOCName; //can't use SetTitle() here because VE sets the layer title based on the kml file
    shapeLayer.AtlasLayerZIndex = zIndex;
    var myShapeSourceSpec = new VEShapeSourceSpecification(VEDataType.ImportXML, layer.TileUrl, shapeLayer);

    this._map.ImportShapeLayerData(myShapeSourceSpec, this._addKMLCallback, false);
},

_addKMLCallback: function(layer)
{
    //This only works for the pushpins...
    //        var zIndex = layer.AtlasLayerZIndex;
    //        var shapeCount = layer.GetShapeCount();
    //        var shape;
    //        for (var i = 0; i < shapeCount; i++) {
    //            shape = layer.GetShapeByIndex(i);
    //            shape.SetZIndex(zIndex, zIndex);
    //        }
},

DropKMLLayer: function(layerID)
{
    ///<summary> Removes a kml atlas layer from the map </summary>

    var shapeLayer;
    var shapeLayerCount = this._map.GetShapeLayerCount();
    for (var s = shapeLayerCount - 1; s > -1; s--)
    {
        shapeLayer = this._map.GetShapeLayerByIndex(s);
        if (shapeLayer.GMETitle == layerID)
        {
            this._map.DeleteShapeLayer(shapeLayer);
        }
    }
},

AddGeoRssLayer: function(layer, zIndex)
{
    ///<summary> Adds a kml atlas layer to the map </summary>

    if (layer.IsLoaded) return;

    var shapeLayer = new VEShapeLayer();
    shapeLayer.GMETitle = layer.TOCName; //can't use SetTitle() here because VE sets the layer title based on the kml file
    shapeLayer.AtlasLayerZIndex = zIndex;
    var layerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS, layer.TileUrl, shapeLayer);

    //insert a css rule to hide the ve messagepanel
    dojox.html.insertCssRule('#veMap_vemessagepanel', 'visibility: hidden');
    //set an interval timer to check for the vemessagpanel...
    this.checkMessagePanelTimer = setInterval(dojo.hitch(this, this._checkForMessagePanel), 500);

    this._map.ImportShapeLayerData(layerSpec, dojo.hitch(this, this._addGeoRssCallback), false);
},

_addGeoRssCallback: function(layer)
{
    if (this.checkMessagePanelTimer)
    {
        //clear our interval
        clearInterval(this.checkMessagePanelTimer);
        // remove our css rule
        dojox.html.removeCssRule('#veMap_vemessagepanel', 'visibility: hidden');
    }

    //Check for an error - handler returns one point with error info in notes if any error ocurred
    if (layer.GetShapeCount() === 1)
    {
        var shape = layer.GetShapeByIndex(0);
        if (shape.Title === 'Error')
        {
            dtsUtility.DisplayUserMessage('Message_Toaster_Topic', shape.Notes, 'error');
            this._map.DeleteShapeLayer(layer);
        }
    }
},

ClearUploadedShapeLayers: function()
{
    ///<summary> Clears all shapelayers except flyways and gains points </summary>

    //probably should keep track of these and explicitly delete only the ones we want but for now...
    var shapeLayer;
    var shapeLayerCount = this._map.GetShapeLayerCount();
    for (var s = shapeLayerCount - 1; s > -1; s--)
    {
        shapeLayer = this._map.GetShapeLayerByIndex(s);
        var shapeLayerName = shapeLayer.GetTitle();
        if (shapeLayerName != 'Drawing' && !this._featureLayers.containsKey(shapeLayerName) && !shapeLayer.GMETitle)
        {
            this._map.DeleteShapeLayer(shapeLayer);
        }
    }
},

// ===============================
// Z O O M   T O   L O C A T I O N
// ===============================

PanZoomToPoint: function(lat, lon, zoomLevel)
{
    ///<summary> Pans/ zooms to the specified lat/ lon, and zoom level. </summary>

    if (lat === '' || lon === '')
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic', "Can't zoom to Lat: " + lat + ",  Long: " + lon, 'warning');
    }

    else
        if (isNaN(lat) || isNaN(lon))
    {
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic', "Can't zoom to Lat: " + lat + ",  Long: " + lon, 'warning');
    }
    else
    {
        //For some reason VE can't Zoom to 0,0
        if (lat == 0) { lat = lat + 0.0001; }
        if (lon == 0) { lon = lon + 0.0001; }
        if (lat > 85) { lat = 85; } //VE's projection has the poles at ~85
        if (lat < -85) { lat = -85; }
        this._map.SetCenterAndZoom(new VELatLong(lat, lon), zoomLevel);
    }
},

PanZoomToPlaceName: function(placename)
{
    ///<summary> Pans/ zooms to the specified placename </summary>

    //first, call the webservice and see if we get anything
    this._service.ZoomToLocation(this._moduleId, this._portalId, this._userId, placename, dojo.hitch(this, this._zoomLocationCallback, placename), Utility.OnFailed);
},

_zoomLocationCallback: function(placename, result)
{
    ///<summary> Callback handler for ZoomToLocation </summary>

    //Check if we got a result
    if (result && result.length > 0)
    {
        if (result.length === 1)
        {   //only 1 result
            //pan/ zoom to it
            this.PanZoomToPoint(result[0].Latitude, result[0].Longitude, result[0].ZoomLevel);
        }
        else
        {   //multiple results
            //show the disambiguation dialog
            var sel = dojo.byId('zoomLocDisambigSel');
            sel.options.length = 0;
            var opt;
            dojo.forEach(result, function(item)
            {
                opt = dojo.doc.createElement('option');
                opt.innerHTML = 'Lat: ' + item.Latitude + ', Lon: ' + item.Longitude + ', Zoom: ' + item.ZoomLevel;
                opt.value = dojo.toJson(item);
                sel.appendChild(opt);
            });

            dijit.byId('zoomLocDisambigDlg').show();
        }
    }
    else if (placename)
    {
        //no results, just use ve    
        this._map.Find(null, placename);
    }
    else
    {
        //display message for user
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic', 'An error ocurred zooming to the specified location.', 'error')
    }
},

_zoomLocDisambigDlgCallback: function()
{
    var sel = dojo.byId('zoomLocDisambigSel');
    if (!sel.value)
    {
        //display message for user
        dtsUtility.DisplayUserMessage('Message_Toaster_Topic', 'You must select a location from the list.', 'warning')
        return;
    }
    map._zoomLocationCallback(null, [dojo.fromJson(sel.value)]);
    dijit.byId('zoomLocDisambigDlg').hide();
},

//=====================================================
// G M E   F U  N C T I O N S   /   P R O P E R T I E S
//=====================================================    

Get_FeatureLayers: function()
{
    ///<summary> Gets the point layers in the map </summary>

    return this._featureLayers;
}

});
});