if (typeof (Dmp) == 'undefined') Dmp = new Object(); var _TOOLKIT_LOCATION='http://parcelstream.com/api/lib\\3.0\\Legacy/';Dmp.HostName='http://parcelstream.com/'; // Create namespace if (typeof (Dmp) == 'undefined') Dmp = new Object(); if (typeof (Dmp.Core) == 'undefined') Dmp.Core = new Object(); if (typeof (Dmp.Core.QueryModel) == 'undefined') Dmp.Core.QueryModel = new Object(); if (typeof (Dmp.Core.WktTools) == 'undefined') Dmp.Core.WktTools = new Object(); if (typeof (Dmp.Core.Collections) == "undefined") Dmp.Core.Collections = new Object(); if (typeof (Dmp.Core.Layers) == 'undefined') Dmp.Core.Layers = new Object(); if (typeof (Dmp.Core.Layers.MapLayers) == 'undefined') Dmp.Core.Layers.MapLayers = new Object(); if (typeof (Dmp.Layers) == 'undefined') Dmp.Layers = new Object(); if (typeof (Dmp.Layer) == 'undefined') Dmp.Layer = new Object(); if (typeof (Dmp.Drawing) == 'undefined') Dmp.Drawing = new Object(); if (typeof (Dmp.Env) == 'undefined') Dmp.Env = new Object(); if (typeof (Dmp.Conn) == "undefined") Dmp.Conn = new Object(); if (typeof (Dmp.Util) == 'undefined') Dmp.Util = new Object(); if (typeof (Dmp.Abstraction) == 'undefined') Dmp.Abstraction = new Object(); if (typeof (Dmp.Legacy) == 'undefined') Dmp.Legacy = new Object(); if (typeof (Dmp.Identify) == 'undefined') Dmp.Identify = new Object(); if (typeof (Dmp.Map) == 'undefined') Dmp.Map = new Object(); if (typeof (Dmp.Cookbook) == 'undefined') Dmp.Cookbook = new Object(); /** * Generates a unique string that are generally used for creating IDs for temporary objects. * @returns the unique string * @syntax: public static String Dmp.Util.getGuid() * @returns a unique string * @type {String} */ Dmp.Util.getGuid = function() { if (!Dmp.Util._guidCount) Dmp.Util._guidCount = 1; var tday = new Date(); var rand = Math.floor(Math.random() * 2000000000) return tday.getTime() + "" + rand + "" + Dmp.Util._guidCount++; }; //getGuid /** * Takes a key-value pair Json object and uses the key to set the respective property on the targetObject. * functions and properties starting with "_" cannot be overwritten in this way. * @params {Object} targetObject. Object to get its properties populated. Required. * @params {Object} json. Used to populate the targetObject. The key must match the desired property to set. Required. * @private */ Dmp.Util._populateFromJson = function(targetObject, json) { for(var n in json) { if(n && n.length > 0 && n.charAt(0) == "_") continue; if(typeof(targetObject[n]) == "function") continue; targetObject[n] = json[n]; } } /** * @params {GMap3 object} map. Required. * @returns the current zoom level of the given GMap3. * @type {Number} */ Dmp.Util.getZoomLevel = function(map) { if(!map || !map.getZoom) return 1; return map.getZoom(); } var __projectionHelper = null; /** * Method to return a MapCanvasProjection object * Implements a dummy OverlayView() class and binds it to the map * @params {Object} _map. Google map object. * @returns MapCanvasProjection for usage of 'fromContainerPixelToLatLng' method line * @type {MapCanvasProjection} */ Dmp.Util.getMapCanvasProjection = function(_map) { if(!__projectionHelper) { function canvasProjection(_map) { this.setMap(_map); } canvasProjection.prototype = new google.maps.OverlayView(); canvasProjection.prototype.onAdd = function() { } canvasProjection.prototype.onRemove = function() { } canvasProjection.prototype.draw = function() { } __projectionHelper = new canvasProjection(map); } return __projectionHelper.getProjection(); } /** * @author Jon Davis * @version 1.3.1 */ var using = window.using = function( scriptName, callback, context ) { function durl(sc) { var su = sc; if (sc && sc.substring(0, 4) == "url(") { su = sc.substring(4, sc.length - 1); } var r = using.registered[su]; return (!r && (!using.__durls || !using.__durls[su]) && sc && sc.length > 4 && sc.substring(0, 4) == "url("); } var a=-1; var scriptNames = new Array(); if (typeof(scriptName) != "string" && scriptName.length) { var _scriptNames = scriptName; for (var s=0;s<_scriptNames.length; s++) { if (using.registered[_scriptNames[s]] || durl(_scriptNames[s])) { scriptNames.push(_scriptNames[s]); } } scriptName = scriptNames[0]; a=1; } else { while (typeof(arguments[++a]) == "string") { if (using.registered[scriptName] || durl(scriptName)) { scriptNames.push(arguments[a]); } } } callback = arguments[a]; context = arguments[++a]; if (scriptNames.length > 1) { var cb = callback; callback = function() { using(scriptNames, cb, context); } } var reg = using.registered[scriptName]; if (!using.__durls) using.__durls = {}; if (durl(scriptName) && scriptName.substring(0, 4) == "url(") { scriptName = scriptName.substring(4, scriptName.length - 1); if (!using.__durls[scriptName]) { scriptNames[0] = scriptName; using.register(scriptName, true, scriptName); reg = using.registered[scriptName]; var callbackQueue = using.prototype.getCallbackQueue(scriptName); var cbitem = new using.prototype.CallbackItem(function() { using.__durls[scriptName] = true; }); callbackQueue.push(cbitem); callbackQueue.push(new using.prototype.CallbackItem(callback, context)); callback = undefined; context = undefined; } } if (reg) { // load dependencies first for (var r=reg.requirements.length-1; r>=0; r--) { if (using.registered[reg.requirements[r].name]) { using(reg.requirements[r].name, function() { using(scriptName, callback, context); }, context); return; } } // load each script URL for (var u=0; u 2) return; } if (remote) { using.srcScript(scriptUrl, asyncWait, callbackQueue); } else { var xhr; if (window.XMLHttpRequest) xhr = new XMLHttpRequest(); else if (window.ActiveXObject) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } xhr.onreadystatechange = function(){ if (xhr.readyState == 4 && xhr.status == 200) { using.injectScript(xhr.responseText, scriptName); if (callbackQueue) { for (var q=0; q 0 || callbackQueue.length > 1) { xhr.open("GET", scriptUrl, true); } else { xhr.open("GET", scriptUrl, false); } xhr.send(null); } }, genScriptNode : function() { var scriptNode = document.createElement("script"); scriptNode.setAttribute("type", "text/javascript"); scriptNode.setAttribute("language", "JavaScript"); return scriptNode; }, srcScript : function(scriptUrl, asyncWait, callbackQueue) { var scriptNode = using.prototype.genScriptNode(); scriptNode.setAttribute("src", scriptUrl); if (callbackQueue) { var execQueue = function() { using.__callbackQueue[scriptUrl] = undefined; for (var q=0; q 0) { setTimeout(execQueue, asyncWait); } else { execQueue(); } } }; } var headNode = document.getElementsByTagName("head")[0]; headNode.appendChild(scriptNode); }, injectScript : function(scriptText, scriptName) { var scriptNode = using.prototype.genScriptNode(); try { scriptNode.setAttribute("name", scriptName); } catch (err) { } scriptNode.text = scriptText; var headNode = document.getElementsByTagName("head")[0]; headNode.appendChild(scriptNode); } }; using.register = using.prototype.register; using.load = using.prototype.load; using.wait = using.prototype.wait; using.defaultAsyncWait = using.prototype.defaultAsyncWait; using.srcScript = using.prototype.srcScript; using.injectScript = using.prototype.injectScript; //Make sure registered always exists. -MW 5/1/08 using.registered = { }; /** * CONFIDENTIAL AND PROPRIETARY * This document is confidential and contains proprietary information. * Neither this document nor any of the information contained herein * may be reproduced or disclosed to any person under any circumstances * without the express written consent of Digital Map Products. * * Copyright: Copyright (c) 2010 * Company: Digital Map Products * @author Gregory * @version 1.0 * */ /** * @class * Links an IMapLayer and a Resource. * Contains descriptive, bounding, preferences, and other information. * resourceName, connectionId, connectionUrl, and ID should not change after construction. * @param {Object} nameOrXml. Could be XML dom or a resourceName (string). If it is an Xml Dom, the Xml must have a resourceName defined. Required. * @param {String} connectionId. ID of the Connection object that this ResourceReference belongs. Required if no Xml Dom is provided. * @param {Object} params. Json style object to parameterize this ResourceReference. Optional */ Dmp.Layer.ResourceReference = function(nameOrXml, connectionId, params) { if(!nameOrXml) { return; } if(typeof(nameOrXml) == "string" && !connectionId) { return; } var _self = this; var _sourceUrl = null; if(typeof(nameOrXml) == "string") { this.resourceName = nameOrXml;}; this.connectionId = connectionId; this.dataResourceName = null; this.title = null; this.abstract = null; this.attribution = null; this.visibilityPreference = true; this.visibilityTrueCondition = null; this.visibilityFalseCondition = null; this.zoomRange = {min:1, max:21}; this.zoomScaleRange = new Object(); this.bounds = null; this.identifiablePreference = true; this.style = null; this.conditionStyles = new Array(); this.time = null; this.filter = null; this.attributeLinks = null; this.keyFields = null; this.hotspotId = null; this.hotspotPreference = false; this._observers = new Object(); this._ldr = null; if(params) { this.connectionUrl = params.connectionUrl; } /** * Determines if this ResourceReference is visible based on its 'visibilityPreference' property, the zoomRange, and bounds. * @param {Object} map. Handle to the map control object. Used to get bounds/scale information. Required. * @returns True if the MapView is in the layer's zoom range, bounds, and visibilityPreference == true * @type {Boolean} */ this.isVisible = function(map) { if(_self.visibilityPreference == false) { return false; } var zoomLevel = Dmp.Util.getZoomLevel(map); if( _self.zoomRange.max < zoomLevel || _self.zoomRange.min > zoomLevel ) { return false; } return true; } //isVisible /** * Accessor/Mutator method for all properties on this object. * Sets 'property' to 'val' if both are provided, returns 'property' otherwise * @param {String} property. A string matching the name of a property on this object. Required. * @param {Object} val. An object matching the type of this[property]. Optional. * @returns The value of the given property if 'val' is not provided. Returns null otherwise. * @type {Object} */ this.attr = function(property, val){ if(typeof(val) != "undefined") { _self[property] = val; if(property == "hotspotId" && _self.displayCache) _self.displayCache.hotspotId = val; for (var n in _self._observers['onPropertyChange']) { _self._observers['onPropertyChange'][n]({property:property, val:val}); } } else { return _self[property]; } } /** * Attach a listener to 'event' and invoke 'funct' upon trigger. * The callback function will be parameterized with ([EVENT], {[VALUES (if applicable)]}). * Current supported events: "onPropertyChange". * @param {String} event. The event to observe. Required. * @param {Function} funct. The function to be invoke when the given event is triggered. Required. */ this.addCallback = function(event, funct) { if(!event || typeof(event) != "string") { return; } else if (!funct || typeof(funct) != "function") { return; } if(typeof(_self._observers[event]) == "undefined") { _self._observers[event] = new Array(); } _self._observers[event].push(funct); } if(typeof(_self._load) == "function") { _self._load(nameOrXml, connectionId, _self.connectionUrl); } if(params) { Dmp.Util._populateFromJson(_self, params); } this.connectionObj = Dmp.Env.Connections.getConnectionObject(_self.connectionId, _self.connectionUrl); } //Dmp.Layer.ResourceReference /** * CONFIDENTIAL AND PROPRIETARY * This document is confidential and contains proprietary information. * Neither this document nor any of the information contained herein * may be reproduced or disclosed to any person under any circumstances * without the express written consent of Digital Map Products. * * Copyright: Copyright (c) 2010 * Company: Digital Map Products * @author Gregory * @version 1.0 * */ if( typeof(google) != "undefined" && typeof(google.maps) != "undefined" && typeof(google.maps.Map) != "undefined") { /** * Container of Dmp IMapLayer objects that is stored as a property on the Google map object. * Currently, only Wms Layers will be stored in this container. * @see Dmp.Layer.IMapLayer * @addon */ google.maps.Map.prototype.dmpLayers = new Array(); google.maps.Map.prototype.DMPLayers = google.maps.Map.prototype.dmpLayers /** * Returns the handle to the IMapLayer with the matching inputted ID. Applicable only to Wms Layers. * @addon * @param {String} id. The string that uniquely identifies this MapLayer. Required. * @returns MapLayer object that has the matching ID. Returns null otherwise. * @type {Object} MapLayer */ google.maps.Map.prototype.getDmpLayerById = function (id) { var arr = this.dmpLayers; var len = arr.length; for(var i = 0; i < len; i++) { if( arr[i].id == id ) { return arr[i]; } } return null; } google.maps.Map.prototype.getDMPLayerById = google.maps.Map.prototype.getDmpLayerById /** * Refresh will force a layer to re-draw itself. Applicable only to Wms Layers. * Calls refresh on all layers associated with this map. Refresh can be called on individual layers as well. * @addon */ google.maps.Map.prototype.refresh = function() { var layerList = this.dmpLayers; for(var n in layerList) { layerList[n].refresh(); } } } /** * @class * Base class for Map Layers. Map Layers' responsibility is displaying itself on the map. * Current supported types: WMS * IMapLayers must be added to the map control via "IMapLayer.setMap(MAP)" to property function. */ Dmp.Layer.IMapLayer = function() { this._resourceReferences = new Array(); this._map = null; this.visibility = true; var _self = this; /** * @returns the layer resources associated with this layer * @type {Array} */ this.getResourceReferences = function() { return _self._resourceReferences; } } /** * Takes a json object as input and determines which properties are valid GetMap parameters * @params params. Associative array of properties. Extra/mispelled properties will be ignored. Required. * @returns Associative array of valid GetMap properties and their values * @type {Object} * @private */ Dmp.Layer._checkRenderOptions = function(params){ var validParameters = ["Color", "ViewInTime", "ActiveVersionId", "ShowField", "ShowValues", "HideField", "HideValues", "Output", "Transformer", "AntiAlias", "IgnoreHoles"]; //NOT: query, hotspotfield, sld/body, attributelink var validOptions = new Object(); for(var n in params) { for(var i =0; i < validParameters.length; i++) { if(n.toLowerCase() == validParameters[i].toLowerCase()) { validOptions[n] = params[n]; //break; } } } return validOptions; } //_checkRenderOptions /** * CONFIDENTIAL AND PROPRIETARY * This document is confidential and contains proprietary information. * Neither this document nor any of the information contained herein * may be reproduced or disclosed to any person under any circumstances * without the express written consent of Digital Map Products. * * Copyright: Copyright (c) 2010 * Company: Digital Map Products * @author Gregory * @version 1.0 * */ /** * @class * Used to display Wms resources on the map and each WmsLayer can contain multiple Wms Resources. * Resources are added via Dmp.Layer.ResourceReference which are added using the '.addChild' method * Added to the map via "LAYER.setMap(MAP)", which is an asynchronous method. Listen for "onAddComplete" via LAYER.addCallback("onAddComplete", FUNCTION). * @see this.addChild * @extends {Dmp.Layer.IMapLayer} * @param {String} tagOrXml. A string to uniquely identify this MapLayer or an Xml string definition of this layer. Recommended. * @param {String} connectionId. ID of the Connection object that this MapLayer belongs. Required if a tag is provided. * @param {Object} params. An associative array of layer properties and render options. Optional. * To add render options, simply add the options to the json object as a normal parameter. * The render options will be appended to the GetMap requests (only valid options will be appended). * The render options that have values dependent on the number of ResourceReferences in the layer are NOT supported. To use these, add them at the ResourceReference level. */ Dmp.Layer.WmsLayer = function (tagOrXml, connectionId, params){ if(!tagOrXml) { tagOrXml = "WmsLayer" + Dmp.Util.getGuid(); } else if( typeof(tagOrXml) != "object" && (!connectionId || (typeof(connectionId) != "string" && typeof(connectionId) != "number")) ) { //throw new Error("connectionId must be a non-empty string if no xmlDom is provided"); return; } this.base = Dmp.Layer.IMapLayer; this.base(); var _self = this; this._zoomFlag = false; //used to improve zoom display this.connectionId = "" + connectionId; this.visibility = true; this.zIndex = 2; this.getClassName = function() { return "WmsLayer"; } this._listeners = new Array(); this._observers = new Object(); /** * Accessor/Mutator method for all properties on this object. * Sets 'property' if 'val' is provided, returns 'property' otherwise. * Calls all observers listening to [onPropertyChange] (if any) * callback is parameterized with {property, value} * If a display property is changed, [LAYER].refresh should be invoked. * @param {String} property. A string matching the name of a property on this object. Required. * @param {Object} val. An object matching the type of this[property]. Optional. * @returns The value of the given property if 'val' is not provided. Returns null otherwise. * @type {Object} */ this.attr = function(property, val) { if(typeof(val) != "undefined") { _self[property] = val; for (var n in _self._observers["onPropertyChange"]) { _self._observers["onPropertyChange"][n]({property:property, val:val}); } } else { return _self[key]; } } /** * API to attach a listener to 'eventParam'. * When the specified 'event' occurs, the given callback will be invoked * The callback function will be parameterized with an Associative Array of values (if any) * Current supported events: "onPropertyChange", "onAddComplete" * @param {String} eventParam. The event to observe. Required. * @param {Function} funct. Function to be invoke upon 'eventParam' triggering. Required. */ this.addCallback = function(eventParam, funct) { if(!eventParam || typeof(eventParam) != "string") { //throw new Error("property parameter must be a non-empty string"); return; } else if (!funct || typeof(funct) != "function") { //throw new Error("function parameter must be a function"); return; } if(typeof(_self._observers[eventParam]) == "undefined") { _self._observers[eventParam] = new Array(); } return (_self._observers[eventParam].push(funct) - 1); } /** * Removes callback(s) from this Wms Layer object. * If only an eventType is provided, all observers of 'eventType' will be removed. * If an 'id' is provided, only that observer of 'eventType' will be removed. * The 'id' is just the index of the callback function (returned by .addCallback * @params {String} eventType. The name of the event. Required. * @params {Int} id. The id (index) of the callback to remove. Optional. */ this.removeCallback = function(eventType, id) { if(!_self._observers[eventType]) return; if(!id) { for(var i = 0; i < _self._observers[eventType].length; i++) { delete _self._observers[eventType][i]; } } else { if( id < 0 || id >= _self._observers[eventType].length) return; delete _self._observers[eventType][id]; } } /** * Creates a [Dmp][Layer][ResourceReference] based on the parameters and adds it to this WmsLayer's ResourceReference list. * Links this layer to a resource * @see Dmp.Layer.ResourceReference * @param {String} tagOrResourceReference. A string to uniquely identify this ResourceReference or a Dmp.Layer.ResourceReference object. Recommended. * @param {String} resourceName. Name of a Resource to bind to this WmsLayer. First parameter will be used in place of resourceName is not provided. Optional. * @param {String} style. A string/IStyle object of an SldPath/SldBody. Will be overridden if 'style' is provided in the extra parameter. Recommended. * @param {Object} params. Associative Array or xml dom of extra parameters to instantiate this ResourceReference. Optional. */ this.addChild = function(tagOrResourceReference, resourceName, style, params) { var res = null; //first parameter is a resourceReference object if(tagOrResourceReference && typeof(tagOrResourceReference) == "object" && typeof(tagOrResourceReference.isVisible) == "function") { res = tagOrResourceReference; } else if (tagOrResourceReference && typeof(tagOrResourceReference) == "object" && typeof(tagOrResourceReference.getAttribute) != "undefined") { res = new Dmp.Layer.ResourceReference(tagOrResourceReference, _self.connectionId, {connectionUrl:_self.connectionUrl}); } else { //first parameter is an ID or an xmlDom is provided for a map composition load tagOrResourceReference = "" + tagOrResourceReference; if (!resourceName) { resourceName = tagOrResourceReference; } if(tagOrResourceReference == "") tagOrResourceReference = "ResourceReference_" + Dmp.Util.getGuid(); res = new Dmp.Layer.ResourceReference(resourceName, _self.connectionId, {connectionUrl:_self.connectionUrl}); Dmp.Util._populateFromJson(res, params); res.resourceName = resourceName; if(style) res.style = style; if(!res.id) res.id = tagOrResourceReference; } _self._resourceReferences.push(res); //add 'res' to Collection } //addChild /** * Returns a ResourceReference object associated with this WmsLayer. * @see Dmp.Layer.ResourceReference * @params {String} id. The string that uniquely identifies the ResourceReference. Required. * @returns ResourceReference with a matching ID * @type {Dmp.Layer.ResourceReference} */ this.getChildById = function(id) { //TODO: case of multiple nodes of the same ID? for(var i = 0; i < _self._resourceReferences.length; i++) { if (_self._resourceReferences[i].id == id) { return _self._resourceReferences[i]; } } } /** * Forces this WmsLayer to re-draw. * Internally invoked if MAP.refresh() is called. * Should be invoked by the application. */ this.refresh = function() { _self.draw(); } //load by Xml dom, if provided if(tagOrXml && typeof(tagOrXml) == "object" && typeof(tagOrXml.getAttribute) != "undefined" && typeof(_self._load) == "function") { _self._load(tagOrXml); } else { this.id = "" + tagOrXml; } if(params) { this._params = params; this._renderOptions = Dmp.Layer._checkRenderOptions(params); Dmp.Util._populateFromJson(_self, params); this.connectionUrl = params.connectionUrl; } this.connectionObj = Dmp.Env.Connections.getConnectionObject(this.connectionId, this.connectionUrl); } // WmsLayer if( typeof(google) != "undefined" && typeof(google.maps) != "undefined" && typeof(google.maps.Map) != "undefined") { Dmp.Layer.WmsLayer.prototype = new google.maps.OverlayView(); } /** * Contains logic to add a Dmp Layer object to the Google map object. Invoked by LAYER.setMap(GMap3) * Should not manually be invoked. * Current supported types: Wms * @addon * @see Dmp.Layer.IMapLayer * @private */ Dmp.Layer.WmsLayer.prototype.onAdd = function() { var _self = this; var div = document.createElement("div"); this._map = this.map; div.style.position = "absolute"; div.style.height = this._map.getDiv().offsetHeight; div.style.width = this._map.getDiv().offsetWidth; this._map.dmpLayers.push(_self); //pan listener var listenerHandle = google.maps.event.addListener(_self._map, 'dragend', function() { _self.draw(); }); _self._listeners.push(listenerHandle); //zoom listener listenerHandle = google.maps.event.addListener(_self._map, 'zoom_changed', function() { _self.layerDiv.style.visibility = "hidden"; _self._zoomFlag = true }); _self._listeners.push(listenerHandle); /** * Uses context from the GetMap URL request to determine which request to display * @private */ this._imageLoaded = function() { var source = this.src; var contextUrl = this.name; var mapView = _self._map.getBounds(); var bbox = contextUrl.substring(contextUrl.indexOf("bbox=") + 5); if(!source || typeof(source) != "string" || !contextUrl || typeof(contextUrl) != "string") return; bbox = bbox.split("&")[0]; if(bbox) bbox = bbox.split(","); if(!bbox || !bbox.length || bbox.length != 4) return; if(mapView.getSouthWest().lat() == bbox[1] && mapView.getSouthWest().lng() == bbox[0] && mapView.getNorthEast().lat() == bbox[3] && mapView.getNorthEast().lng() == bbox[2] ) { var proj = _self.getProjection(); var center = _self._map.getCenter(); _self.layerDiv.style.left = proj.fromLatLngToDivPixel(center).x - _self._map.getDiv().offsetWidth/2 + 'px'; _self.layerDiv.style.top = proj.fromLatLngToDivPixel(center).y - _self._map.getDiv().offsetHeight/2 + 'px'; if(_self.layerDiv.lastChild) _self.layerDiv.replaceChild(this, _self.layerDiv.lastChild); else _self.layerDiv.appendChild(this); if(_self._zoomFlag ) { _self.layerDiv.style.visibility = "visible"; _self._zoomFlag = false; } //end if zoomFlag } //end BBox check } //_imageLoaded this.getPanes().overlayLayer.appendChild(div); this.layerDiv = div; for (var n in _self._observers["onAddComplete"]) { _self._observers["onAddComplete"][n]({layer:_self}); } } //onAdd /** * Remove this layer from the Google map. Invoked by LAYER.setMap(null). * This method uses splice (array length will change after each remove) * @addon * @private */ Dmp.Layer.WmsLayer.prototype.onRemove = function() { var _self = this; this._zoomFlag = false; var index = 0; for (index; index < _self._map.dmpLayers.length; index++) { if(_self._map.dmpLayers[index].id == _self.id) { break; } } if(index >= _self._map.dmpLayers.length) { //throw new Error("Cannot remove a layer that isn't on the map"); return; } _self._map.dmpLayers.splice(index, 1); for(var i = 0; i < _self._listeners.length; i++) { google.maps.event.removeListener(_self._listeners[i]); } this.layerDiv.parentNode.removeChild(this.layerDiv); } //onRemove /** * Hides the Wms Layer, but the layer will still make requests. * @addon */ Dmp.Layer.WmsLayer.prototype.hide = function() { this.layerDiv.style.visibility = "hidden"; this.visibility = false; this.refresh(); } //hide /** * Show the Wms Layer, and will not issue a new GetMap request. * @addon */ Dmp.Layer.WmsLayer.prototype.show = function() { if(!this._zoomFlag) { this.layerDiv.style.visibility = "visible"; } this.visibility = true; this.refresh(); } //show Dmp.Layer.WmsLayer.prototype.copy = function() { //not implemented } //copy /** * Re-draws all visible resourceReferences bound to this layer. Invoked by 'dragent' and 'zoom_changed' events. * Should not manually be called, if application needs to re-draw the map use LAYER.refresh() or MAP.refresh(). * @addon * @private */ Dmp.Layer.WmsLayer.prototype.draw = function() { var _self = this; if(typeof(_self._drawAddon) == "function") { //check for advanced drawing method (if included) _self._drawAddon(); return; } if(!_self.visibility) { this.layerDiv.style.visibility = "hidden"; _self.zoomFlag = false; return; } var layers = ""; //must var sld = ""; //must var sldEmpty = true; var sldBody = null; var attributeLinks = ""; //optional var linksEmpty = true; var query = ""; //optional var queryEmpty = true; var visibleRes = new Array(); for(var i in _self._resourceReferences) { if( _self._resourceReferences[i].isVisible(_self.map) ) { layers += "," + _self._resourceReferences[i].resourceName; //'style' check var style = _self._resourceReferences[i].style; if( style ) { if(style.indexOf("<") == 0) { sldBody = style; } sld += "," + style; sldEmpty = false; } else { sld += ", "; } //'attributeLink' check if(_self._resourceReferences[i].attributeLinks) { attributeLinks += "," + _self._resourceReferences[i].attributeLinks; linksEmpty = false; } else { attributeLinks += ", "; } //'query' check if(_self._resourceReferences[i].filter) { query += "," + _self._resourceReferences[i].filter; query = false; } else { query += ", "; } //store visible resourceReferences visibleRes.push(_self._resourceReferences[i]); } //end if isVisible } //end for resourceReferences //turn off layer if no children are visible if(layers == "") { _self._zoomFlag = false; this.layerDiv.style.visibility = "hidden"; return; } else if (!_self._zoomFlag && _self.visibility ) { this.layerDiv.style.visibility = "visible"; } //end if/else var view = _self.map.getBounds(); var params = { xMin: view.getSouthWest().lng(), yMin: view.getSouthWest().lat(), xMax: view.getNorthEast().lng(), yMax: view.getNorthEast().lat() }; var callbackWaiting = function() { var url = _self.connectionObj.getBaseUrl(visibleRes[0].resourceName) + "GetMap.aspx?"; url += "bbox=" + params.xMin + "," + params.yMin + "," + params.xMax + "," + params.yMax; url += "&width=" + _self.map.getDiv().offsetWidth; url += "&height=" + _self.map.getDiv().offsetHeight; url += "&layers=" + layers.substring(1); //remove extra first comma if(!sldEmpty) { if(sldBody) { url += "&sld_body=" + sldBody; } else { url += "&sld=" + sld.substring(1); } } if(!linksEmpty) url += "&attributeLinks=" + attributeLinks.substring(1); if(!queryEmpty) url += "&query=" + query.substring(1); if(visibleRes[0].viewInTime) url += "&viewInTime=" + visibleRes[0].viewInTime; for(var n in _self._renderOptions) { url += "&"+n+"=" + _self._renderOptions[n]; } var imgTag = document.createElement('img'); imgTag.onload = _self._imageLoaded; //function to handle display logic upon image load completion if (_self.opacity <= 1) { _self.layerDiv.style.filter = "alpha(opacity=" + (_self.opacity * 100) + ")"; } if (_self.zIndex) _self.layerDiv.style.zIndex = _self.zIndex; else _self.layerDiv.style.zIndex = 2; url = _self.connectionObj.finalizeUrl(url); imgTag.name = url; imgTag.setAttribute("src", url); } if(_self.connectionObj.isReady()) { callbackWaiting(); } else { _self.connectionObj._loadArray.push(callbackWaiting); } } //draw Dmp.Core.Layers.MapLayers.WmsLayer = Dmp.Layer.WmsLayer; Dmp.Layer.WMSLayer = Dmp.Layer.WmsLayer; /** * CONFIDENTIAL AND PROPRIETARY * This document is confidential and contains proprietary information. * Neither this document nor any of the information contained herein * may be reproduced or disclosed to any person under any circumstances * without the express written consent of Digital Map Products. * * Copyright: Copyright (c) 2010 * Company: Digital Map Products * @author Gregory * @version 1.0 * */ /** * @class * Creates a TileLayer that's added to the Google map via 'MAP.overlayMapTypes.push(new google.maps.ImageMapType(LAYER))'. * To maintain correct initial behavior, authentication must be completed before adding a Tile Layer to the map. * @param {String} connectionIdOrXml. ID of the Connection object that this Tile Layer belongs or XML for map composition loading. Required. * @param {String} resourceName. Name of the resource for this Tile Layer. Required if no XML definition is provided. * @param {Object} params. An associative array of layer properties. Optional. */ Dmp.Layer.TileLayer = function(connectionIdOrXml, resourceName, params ) { var _self = this; this.alt = ""; this.isPng = true; this.maxZoom = 21; this.minZoom = 1; this.name = ""; //this.opacity = 1; //opacity currently bugged: 9/24/2010 this.tileSize = new google.maps.Size(256, 256); this.resourceName = resourceName; this.connectionId = connectionIdOrXml; this.visibility = true; //load by Xml dom, if provided if(connectionIdOrXml && typeof(connectionIdOrXml) == "object" && typeof(connectionIdOrXml.getAttribute) != "undefined" && typeof(_self._load) == "function") { _self._load(connectionIdOrXml); } else { //this.id = "" + tagOrXml; /* //automatically create a child (can only have 1 active per tile) if 'resourceName' is provided if(resourceName && typeof(resourceName) == "string") { _self.addChild(tagOrXml, resourceName, "", params); } */ } if(params) { this._renderOptions = Dmp.Layer._checkRenderOptions(params); Dmp.Util._populateFromJson(_self, params); } this.opacity = null; //currently bugged: 9/24/2010 this.connectionObj = Dmp.Env.Connections.getConnectionObject(this.connectionId, this.connectionUrl); /** * Converts XYZ to a quadKey that's used as the 'tileId' in the request * @param {Number} tileX * @param {Number} tileY * @param {Number} levelOfDetail * @returns quadkey * @type {Number} * @private */ function TileXYToQuadKey(tileX, tileY, levelOfDetail) { var quadKey = ''; for (var i = levelOfDetail; i > 0; i--) { var digit = '0'; var mask = 1 << (i - 1); if ((tileX & mask) != 0) { digit++; } if ((tileY & mask) != 0) { digit++; digit++; } quadKey += digit; }//for i return quadKey; }//TileXYToQuadKey /** * Abstract method of Google ImageMapTypes and should be invoked by google maps control * @param {Object} tileXY. Object containing an 'x' and 'y' property with respective coordinates. Required. * @param {Object} zoom. Level of detail (1-21). Required. * @returns url for the currently display tiles * @type {String} * @private */ this.getTileUrl = function(tileXY, zoom) { if(!(_self.minZoom <= zoom && _self.maxZoom >= zoom && _self.visibility) ) return ""; var url = _self.connectionObj.getBaseUrl(_self.resourceName) + "GetMap.aspx?layers=" + _self.resourceName; for(var n in _self._renderOptions) { url += "&"+n+"=" + _self._renderOptions[n]; } if(_self.sld) url += "&sld=" + _self.sld; else if(_self.sldBody) url += "&sld_Body=" + _self.sldBody; url += "&tileid=" + TileXYToQuadKey(tileXY.x, tileXY.y, zoom); url = _self.connectionObj.finalizeUrl(url); return url; } } // TileLayer if(typeof(Dmp.Env.Connections) == "undefined") { /** * Collection of Connection objects * Associative Array * @see Dmp.Conn.Connection */ Dmp.Env.Connections = new Object(); } //end if /** * Method for obtaining connection objects in modified forms. * Standard form: Only 'source' is provided and is an ID to the connection object. The connection object is returned with no modifications. * New Domain form: Only 'source' is provided and is a domain URL. The connection object returned only has static properties and the domain used will be 'source'. * Override Domain form: Both 'source' and 'connectionUrl' are provided. 'source' is a valid ID and 'connectionUrl' is a domain URL. The connection object returned has properties of the connectionObject[ID] but uses 'connectionUrl' as its domain URL when making requests. * You must include the "Utility" package when using the "source" parameter for a URL override. * URLs must be of the form "http://..../" or "https://..../" * @params {String} source. ID for the connection object or a domain URL. Required. * @params {String} connectionUrl. A URL override for the connection object. Optional. * @returns a connection object (may be modified depending on parameters) * @type {Dmp.Conn.Connection} */ Dmp.Env.Connections.getConnectionObject = function(source, connectionUrl){ var _self = this; var returnUrl = ""; /** * Method that provides an overridden base url method for this connection object wrapper. * @param {String} newBaseUrl. The new Url to be used in place of the original base. Required. * @param {String} res. The name of the resource that will be used in the following request. Allows proper server request when dealing with temporary layers. Optional. * @private */ function overrideBaseUrl(newBaseUrl, res) { if(!newBaseUrl || typeof(newBaseUrl) != "string" || newBaseUrl.length <= 0) return ""; if(typeof(res) != "undefined" && res) { var tempPath = res.split("/")[0]; if(tempPath && tempPath.match(/_T\d{1,3}/gi)){ return "" + newBaseUrl + "/" + tempPath + "/"; } } if(newBaseUrl.charAt(newBaseUrl.length-1) != "/") newBaseUrl += "/"; return newBaseUrl; } //source is a valid connection ID if( source.indexOf("http://") == -1 && source.indexOf("https://") == -1 ) { if(!connectionUrl) { return Dmp.Env.Connections[source]; } else if (connectionUrl && typeof(connectionUrl) == "string") { if(connectionUrl.indexOf("http://") >= 0 || connectionUrl.indexOf("https://") >= 0) { var obj = new function() { var id = source; for(var n in Dmp.Env.Connections[source]) { this[n] = Dmp.Env.Connections[source][n]; } this.getBaseUrl = function(res) { return overrideBaseUrl(connectionUrl, res); } this.getJson = function(url, succ, err, output) { var domainedUrl = ""; if( url.indexOf("http://") == -1 && url.indexOf("https://") == -1 ) { domainedUrl += this.getBaseUrl(); } domainedUrl += url; Dmp.Env.Connections[id].getJson(domainedUrl, succ, err, output); } } return obj; } } } else {//if(source.indexOf("http://") != -1 || source.indexOf("https://") != -1){ //source is a url var obj = new function() { var closureSource = source; this.getBaseUrl = function(res) { return overrideBaseUrl(closureSource, res); } this.getJson = function(url, succ, err, output){ var domainedUrl = ""; if(url.indexOf("http://") == -1 && url.indexOf("https://") == -1) { domainedUrl += this.getBaseUrl(); } domainedUrl += url; Dmp.Util.getJson(domainedUrl, succ, err, output); } this.isReady = function() { return true; } this.finalizeUrl = function(url) { return url; } } return obj; } //end if/else } //end Dmp.Env.Conn /** * Collection of Resource objects that are internally created when a ResourceReference is constructed. * @see Dmp.Layer.Resource * @see Dmp.Layer.ResourceReference */ Dmp.Env.Resources = new Object(); /** * @class * Connection object that handles the proper workflow for sending authenticated web requests. * @param {String} initUrl. Initialization URL to start this session. Typically is "initSession.aspx". Recommended. */ Dmp.Conn.Connection = function(initUrl) { if(typeof(initUrl) == "undefined" || !initUrl) { //throw new Error("Session URL must be present"); } var _self = this; var _initComplete = false; //extract the base url (http://parcelstream.com/InitSession.aspx -> http://parcelstream.com) //_baseUrl will be reset after .init(sik) is called var _baseUrl = ""; var _initService = ""; var parseHelper = initUrl.split("://"); if(parseHelper.length >= 2) { _baseUrl += parseHelper[0] + "://" parseHelper = parseHelper[1].split("/"); } else { _baseUrl += "http://" parseHelper = parseHelper.split("/"); } _baseUrl += parseHelper[0]; // http://parcelstream.com _initService += parseHelper[1]; // InitSession.aspx this.userId = null; this.useCandy = false; this._loadArray = new Array(); // used for methods needing 'onload' callbacks var _domainList = new Array(); /** * Handles web requests asynchronously. * Supports full url (http://spatialstream.com/getQuery.aspx?...) or service only (getQuery.aspx?...) * @param {String} jsonUrl * @param {Function} succCall * @param {Function} errCall * @param {String} outputType */ this.getJson = function(jsonUrl, succCall, errCall, outputType) { return getJsonInternal(jsonUrl, succCall, errCall, outputType); } //getJson function getJsonInternal(jsonUrl, succCall, errCall, outputType, init) { var MAX_WAIT_TIME = 2 * 1000; var timeoutThread = null; var callbackFunc = Dmp.Util.getGuid(); var sucCallback = "S" + callbackFunc; var errCallback = "E" + callbackFunc; //Listener for script loader function _loadedURL() { if (timeoutThread == "done") return; //in case we got called multiple times, cancel the previous threads. if (timeoutThread) window.clearTimeout(timeoutThread); //start the timer. timeoutThread = window.setTimeout(function() { //Timeout error if (errCall) { var resp = { Response: { Error: { message: "Timeout"}} }; errCall(resp); } }, MAX_WAIT_TIME); } //_loadedURL function _clean() { if (timeoutThread) window.clearTimeout(timeoutThread); else timeoutThread = "done"; window[sucCallback] = null; window[errCallback] = null; }; //_clean //On Success window[sucCallback] = function(p1, p2, p3, p4) { _clean(); if (succCall) succCall(p1, p2, p3, p4); }; //succ //On Error window[errCallback] = function(p1, p2, p3, p4) { _clean(); if (errCall) errCall(p1, p2, p3, p4); }; //err var callbackWaiting = function() { var urlWithOid = ""; if( jsonUrl.indexOf("http://") == -1 && jsonUrl.indexOf("https://") == -1 ) { urlWithOid += _self.getBaseUrl(); } urlWithOid += jsonUrl; if (jsonUrl.indexOf("?") > 0) urlWithOid += "&"; else urlWithOid += "?"; urlWithOid += "obsId=window"; urlWithOid += "&obsSuccessMethod=" + sucCallback; urlWithOid += "&obsErrorMethod=" + errCallback; if (urlWithOid.indexOf("output=") < 0) { if (!outputType) outputType = "json"; urlWithOid += "&output=" + outputType; } if( init != "init" ) { urlWithOid = _self.finalizeUrl(urlWithOid); } //'using' Call using("url(" + urlWithOid + ")", _loadedURL); } //secret parameter to stop all web requests until connection establishes (except the connection initializer) if(_self.isReady() || init == "init") { callbackWaiting(); } else { _self._loadArray.push(callbackWaiting); } } /** * Returns the baseUrl of this connection object. Optional 'res' parameter that accepts a temporary * resource and appends the folder to the base url. * @param {String} res. Resource that will be used in the URL. If it's temporary, the proper temporary information * will be included in the baseUrl. Optional. * @returns base url of this connection * @type {String} */ this.getBaseUrl = function(res) { if(res && typeof(res) == "string") { var tempPath = res.split("/")[0]; if(tempPath && tempPath.match(/_T\d{1,3}/gi)){ return "" + _baseUrl + "/" + tempPath + "/"; } } return _baseUrl + "/"; } //getBaseUrl /** * @param {String} url. * @return * @type {String} */ this.finalizeUrl = function( url ) { var newUrl = "" + url; if( _self.useCandy ) { newUrl += "&SS_CANDY=" + _self._candy; } if( _self.userId ) { newUrl += "&uid=" + _self.userId; } return newUrl; } /** * @returns the service used for initSession * @type {String} * @private */ this._getInitService = function() { return _initService; } /** * Determins if the InitSession aspx call for this connection object has been completed. * @returns true if the initialization call is complete * @type {Boolean} */ this.isReady = function() { return _initComplete; } /** * Begins initialization of this connection object, which in mose cases is calling InitSession aspx. * The alternative case is authenticating a page using the same cookie. * optionalCallback should be used if any authenticating-required web requests are made by the application on startup * The asynchronous workflow is handled for internal web requests * @param {String} sik. Of the form "KEY" or "/sub-domain/folder/KEY". Recommended. * @param {Function} optionalCallback. Function to be invoked upon authentication completion. Optional. */ this.init = function(sik, optionalCallback){ if(typeof(sik) == "undefined" || !sik) { //throw new Error("a SIK must be provided"); } /* function siSuccess(r){ var row = r.Response.Results.Data.Row; _self.userId = row.UserId; _self._candy = row.Candy; _baseUrl = row.Domains.split(",")[0]; _domainList = row.Domains.split(","); if(_baseUrl.charAt(_baseUrl.length-1) == "/") _baseUrl = _baseUrl.substring(0, _baseUrl.length-1); //invoked after UserProperties.aspx logic is completed function afterUserPropertyComplete() { // callback queue for methods awaiting InitSession.aspx response _initComplete = true; while (_self._loadArray.length > 0) { _self._loadArray[0](); _self._loadArray.splice(0, 1); } if(optionalCallback != null && typeof(optionalCallback) == "function") { optionalCallback(); } } //'init' is a special key to allow web requests without completing the authentication process var testAuthenticationUrl = _self.getBaseUrl() + "UserProperties.aspx?"; _self.getJson(testAuthenticationUrl, function(json) { if ( json.User.authenticationMethod.indexOf("SS_CANDY") < 0 ) { _self.useCandy = true; } afterUserPropertyComplete(); }, function(err) { //error if(err && err.Response && err.Response.Error && err.Response.Error.message && err.Response.Error.message.indexOf("You are not logged in") >= 0) { _self.useCandy = true; } afterUserPropertyComplete(); }, null, "init"); } function siFailure(err) { //exception } */ var key = sik; var _url = ""; var urlParser = _self.getBaseUrl().split("://"); if(urlParser.length >= 2) { _url += urlParser[0] + "://"; } urlParser = urlParser[1].split("/"); if(key.charAt(0) == "/") { //parse var keyParser = key.split("/"); //append sub-domain if(keyParser[1] != "") { _url += keyParser[1] + "."; } //append domain _url += urlParser[0]; //append post-domain _url += "/" + keyParser[2]; //set key (sik) key = keyParser[2] + "/" + keyParser[3]; } else { _url = _self.getBaseUrl(); } if(_url.charAt(_url.length-1) == "/") _url = _url.substring(0, _url.length-1); _url += "/" + _self._getInitService() + "?sik=" + key; //'init' is a special key to allow web requests without completing the authentication process //callback also invokes UserProperties.aspx to handle browser cookies getJsonInternal(_url, function (response) { var row = response.Response.Results.Data.Row; _self.userId = row.UserId; _self._candy = row.Candy; _baseUrl = row.Domains.split(",")[0]; _domainList = row.Domains.split(","); if(_baseUrl.charAt(_baseUrl.length-1) == "/") _baseUrl = _baseUrl.substring(0, _baseUrl.length-1); //invoked after UserProperties.aspx logic is completed function afterUserPropertyComplete() { // callback queue for methods awaiting InitSession.aspx response _initComplete = true; while (_self._loadArray.length > 0) { _self._loadArray[0](); _self._loadArray.splice(0, 1); } if(optionalCallback != null && typeof(optionalCallback) == "function") { optionalCallback(); } } //'init' is a special key to allow web requests without completing the authentication process var testAuthenticationUrl = _self.getBaseUrl() + "UserProperties.aspx?"; getJsonInternal(testAuthenticationUrl, function(json) { if ( json.User.authenticationMethod.toLowerCase() == "trustedreferrer" ) { _self.useCandy = true; } afterUserPropertyComplete(); }, function(err) { //error if(err && err.Response && err.Response.Error && err.Response.Error.message && err.Response.Error.message.indexOf("You are not logged in") >= 0) { _self.useCandy = true; } afterUserPropertyComplete(); }, null, "init"); }, function (err) { //exception }, null, "init"); } //init } //Dmp.Conn.Connection /** * Transforms an XML string by applying the given XSL string * @params {String} xml. The XML string to be transformed. * @params {String} xsl. The stylesheet that should be applied. * @returns the transformed xml * @type {String} */ Dmp.Util.transformXml = function(xml, xsl) { if (window.ActiveXObject && window.GetObject) { var xmlDom = new ActiveXObject('Microsoft.XMLDOM'); xmlDom.loadXML(xml); var xslDom = new ActiveXObject('Microsoft.XMLDOM'); xslDom.loadXML(xsl); return (xmlDom.transformNode(xslDom)); } else if (window.DOMParser) { var xmlDom = new DOMParser().parseFromString(xml, 'text/xml'); var xslDom = new DOMParser().parseFromString(xsl, 'text/xml'); var xsltProcessor = new XSLTProcessor(); xsltProcessor.importStylesheet(xslDom); var dom = xsltProcessor.transformToDocument(xmlDom); var str = (new XMLSerializer()).serializeToString(dom); return (str); } throw { description: 'No XML parser available' }; }; /** * Helper to parse xml nodes. * @param {Object} node. a jqDom node. Required. * @param {Object} name. Name of the node to find. Required. * @returns text contained in the node * @type {String} * @private */ Dmp.Util.nodeVal = function(node, name) { node = node.find(name); return node ? node.text() : null; }; //nodeVal /** * Converts an XML string into the available brower's xml dom * @params {String} xml. The XML text as a string. * @returns * @type {xml dom} * @throws xml parser not available */ Dmp.Util.getXmlDom = function(xml) { if (window.ActiveXObject && window.GetObject) { var dom = new ActiveXObject('Microsoft.XMLDOM'); dom.loadXML(xml); return (dom); } else if (window.DOMParser) { var dom = new DOMParser().parseFromString(xml, 'text/xml'); return (dom); } throw { description: 'No XML parser available' }; }; /** * Uses the browser's XML parser to create an XML Dom element. The XML Dom is returned as a jQuery object. * @syntax: public static JQueryDom Dmp.Util.parseXml(String xmlString) * @param {String} xml. XML string to be converted. * @returns jQuery XML Dom of the given XML string. * @type {jQuery Dom} * @throws browser XML parser not detected. * @deprecated */ Dmp.Util.parseXml = function(xml) { if (window.ActiveXObject && window.GetObject) { var dom = new ActiveXObject('Microsoft.XMLDOM'); dom.async="false"; dom.loadXML(xml); return $(dom); } else if (window.DOMParser) { var dom = new DOMParser().parseFromString(xml, 'text/xml'); return $(dom); } throw { description: 'No XML parser available' }; }; /** * @syntax: public static int Dmp.Util.getHashCode (String val ) * @param {String} val * @returns Hash code for the input string * @deprecated */ Dmp.Util.getHashCode = function(val) { val += ""; var hash = 0; var len = val.length; for (var i = 0; i < len; i++) { // rotate left and xor hash <<= 1; if (hash < 0) hash |= 1; hash ^= val.charCodeAt(i); } return hash; }; //getHashCode /** * Converts the array to a comma delimited string * @param {Array} arr * @private */ Dmp.Util._joinArr = function(arr) { var str = ""; for (var idx in arr) { var element = arr[idx]; //is it 2D array? if (Dmp.Util._getType(element) == 'Array') { if (str != "") str += "\n"; str += Dmp.Util._joinArr(element); } else { if (str != "") str += ","; str += element; } } //for idx return str; }; //_joinArr /** * @param {String} serviceUrl * @param {Object} paramHashtable * @returns full URL with the serviceUrl and paramHashTable properly joined * @type {String} * @private */ Dmp.Util._constructUrlFromHashtable = function(serviceUrl, paramHashtable) { if (paramHashtable == null) return serviceUrl; var paramsString = ""; for (var key in paramHashtable) { var val = paramHashtable[key]; if (val == null) val = ''; else if (Dmp.Util._getType(val) == 'Array') { val = Dmp.Util._joinArr(val); } if (paramsString != '') paramsString += '&'; paramsString += key + '=' + escape(val); } //for key var completeUrl = serviceUrl; if (paramsString && paramsString.length > 0) { if (completeUrl.indexOf('?') < 0) { completeUrl += '?' + paramsString; } else { completeUrl += '&' + paramsString; } } return completeUrl; }; //_constructUrlFromHashtable /** * * @param {Object} v * @returns the type of the input object * @private */ Dmp.Util._getType = function(v) { if (v == null || typeof (v) != 'object') return typeof (v); else if (v.length!=null) return 'Array'; }; /** * * @param {Object} modelObj * @param {Array} paramArr * @returns name-value paired array * @type {Array} * @private */ Dmp.Util._constructParamsDict = function(modelObj, paramArr) { var dict = []; for (var i = 0; i < paramArr.length; i++) { var k = paramArr[i]; var v = modelObj[k]; if (v == null || (v == "" && v!= 0)) continue; dict[k] = v; } //for i return dict; }; //_constructParamsDict /** * Uses the input url and outputType(if provided) and makes a server request * successCallBack is instantiated with the response of the server request * @syntax: public static void Dmp.Util.getJson (String url, Callback successCall, Callback errorCall ) * @param {String} url * @param {function} succCall * @param {function} errCall * @param {String} outputType * @deprecated */ Dmp.Util.getJson = function(url, succCall, errCall, outputType) { //Timeout. This time is counted after using.js gave us a callback. var MAX_WAIT_TIME = 2 * 1000; var timeoutThread = null; var callbackFunc = Dmp.Util.getGuid(); var sucCallback = "S" + callbackFunc; var errCallback = "E" + callbackFunc; //Listener for script loader function _loadedURL() { if (timeoutThread == "done") return; //in case we got called multiple times, cancel the previous threads. if (timeoutThread) window.clearTimeout(timeoutThread); //start the timer. timeoutThread = window.setTimeout(function() { //Timeout error if (errCall) { var resp = { Response: { Error: { message: "Timeout"}} }; errCall(resp); } }, MAX_WAIT_TIME); } //_loadedURL function _clean() { if (timeoutThread) window.clearTimeout(timeoutThread); else timeoutThread = "done"; window[sucCallback] = null; window[errCallback] = null; }; //_clean //On Success window[sucCallback] = function(p1, p2, p3, p4) { _clean(); if (succCall) succCall(p1, p2, p3, p4); }; //succ //On Error window[errCallback] = function(p1, p2, p3, p4) { _clean(); if (errCall) errCall(p1, p2, p3, p4); }; //err var urlWithOid = url; if (url.indexOf("?") > 0) urlWithOid += "&"; else urlWithOid += "?"; urlWithOid += "obsId=window"; urlWithOid += "&obsSuccessMethod=" + sucCallback; urlWithOid += "&obsErrorMethod=" + errCallback; if (urlWithOid.indexOf("output=") < 0) { if (!outputType) outputType = "json"; urlWithOid += "&output=" + outputType; } //'using' Call using("url(" + urlWithOid + ")", _loadedURL); }; //Dmp.Util.getJson /** * Exception class * @param {Object} ex */ Dmp.Exception = function(ex) { this.message = ex; this.description = ex; }; //Dmp.Exception /** * * @param {String} name * @returns cookie * @type {String} * @deprecated */ Dmp.Util.getCookie = function(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); } return null; };//getCookie //Utility functions to get the recordset (added Feb 24, 2010) Dmp.Util.getRecordSet = function(index, json){ if (!json) return null; json = json.Response.Results; if (!json.RecordSet && index==0) return json; else if (!json.RecordSet) return null; if (index < json.RecordSet.length) return json.RecordSet[index]; else return null; };//getRecordSet Dmp.Util.getFirstRow = function(recordSet){ if (!recordSet) return null; return recordSet.Data.Row.length?recordSet.Data.Row[0]:recordSet.Data.Row; };//getFirstRow Dmp.Util.getRowAt = function(recordSet, i){ if (!recordSet) return null; else if (!recordSet.Data.Row.length && i==0) return recordSet.Data.Row; else if (!recordSet.Data.Row.length) return null; return recordSet.Data.Row[i]; };//getFirstRow //end addition //DMCFactory - 3/29/2010 //loads file and calls back with className handle if successful Dmp.Util.Factory = new function() { this.load = function(pathName, className, _callback) { var url = pathName;//Dmp.HostName + "GetFile.aspx?file=" + pathName; //use getScript to load JS, then callback with the className (null for failure) function _success(jsCode){ function _load() { var loadClassFunction = new Function("return new " + className + "();"); var loadedClassName = loadClassFunction(); _callback(loadedClassName); } $.getScript(url, _load); } function _failure() { _callback(null); //file not found } Dmp.Util.getJson(url, _success, _failure); }; }; //factory //Transform a record object into an XML string - 3/31/2010 Dmp.Util.transformToXML = function(record) { var xml = ""; for (var field in record) { xml += "<" + field + " " + record[field] + " />"; } xml += ""; }; //transformToXML /** * CONFIDENTIAL AND PROPRIETARY * This document is confidential and contains proprietary information. * Neither this document nor any of the information contained herein * may be reproduced or disclosed to any person under any circumstances * without the express written consent of Digital Map Products. * * Copyright: Copyright (c) 2010 * Company: Digital Map Products * @author Gregory * @version 1.0 * */ Dmp.Layer.ResourceReference.prototype.checkBounds = function() { //check bounds. Code from Legacy //based on http://www.faqs.org/faqs/graphics/algorithms-faq/ Section 2.03. //Odd number of crosses -> inside. Even number of crosses -> outside. //need algorithms for bbox vs bounds check /* if (this.bounds != null) { var p = map.GetCenter(); var y = p.Latitude; var x = p.Longitude; var cn=0; var i=0; var pol = this.bounds.GetPoints(); var npol= pol.length; var j=npol-1; for(i,j;i" node in this ResourceReference * @params {String} trueConditionsString. Array with the true conditions based on the current state. Required. * @returns The first style that meets its condition. Otherwise returns the default style. * @type {Object} SldStyle or SldBody class */ Dmp.Layer.ResourceReference.prototype.getCurrentStyle = function(trueConditions) { var _self = this; if(!trueConditions || trueConditions.length <= 0) { return _self.style; } //Loops through each IStyle object for(var n in _self.conditionStyles) { if(!_self.conditionStyles || !_self.conditionStyles[n] || !_self.conditionStyles[n].condition) { continue; } var conditions = _self.conditionStyles[n].condition.split(" "); var stack = new Array(); //contains {TRUE, FALSE, AND, OR} (Strings) only var evaluate = false; //determines when to pop from the stack //Loops through each condition of this style (A AND B -> ['A','AND','B']) for(var m in conditions) { var condition = conditions[m]; if(evaluate) { if(_self._arrayContains(trueConditions, condition)) { stack.push("TRUE"); } else { stack.push("FALSE"); } var rhs = stack.pop(); var op = stack.pop(); var lhs = stack.pop(); if (op.toUpperCase() == "AND" ) { if (rhs.toUpperCase() == "TRUE" && lhs.toUpperCase() == "TRUE") { stack.push("TRUE"); } else { stack.push("FALSE"); } } else if (op.toUpperCase() == "OR") { if (rhs.toUpperCase() == "TRUE" || lhs.toUpperCase() == "TRUE") { stack.push("TRUE"); } else { stack.push("FALSE"); } } else { stack.push("FALSE"); } evaluate = false; } else if(condition.toUpperCase() == "AND" || condition.toUpperCase() == "OR") { stack.push(condition.toUpperCase()); evaluate = true; } else { if(_self._arrayContains(trueConditions, condition)) { stack.push("TRUE"); } else { stack.push("FALSE"); } } } //end conditions //returns the first matched conditional style if (stack.pop().toUpperCase() == "TRUE") { return _self.conditionStyles[n].style; } } //end style list return _self.style; } //getCurrentStyle /** * GetLdr returns an object that contains an 'allocateSymbolizer' method, which takes in a record and returns an object with an image Url. * @returns Ldr object. * @type {Object} */ Dmp.Layer.ResourceReference.prototype.getLdr = function() { return this._ldr; } /** * Parses an xmlDom and populates relevant properties of the ResourceReference. * @param {Object} xmlDom. An XML Dom describing a ResourceReference. Required. * @private */ Dmp.Layer.ResourceReference.prototype._load = function(paramObj, connectionId, connectionUrl) { if(!paramObj) return; var _self = this; //call GetLdr.aspx whenever the style property is updated function _getLdr() { var url = "GetLdr.aspx?&format=json"; var sld = _self.style; var isBody = false; if (typeof(sld) == "object") { //TODO: set isBody if(sld.getType() == "body") isBody = true; sld = sld.styleValue(); } if(!sld || typeof(sld) != "string") return; sld = encodeURIComponent(sld); if(isBody) { url += "&sld_body=" + sld; } else { url += "&sld=" + sld; } Dmp.Env.Connections["SS"].getJson(url, function(json) { _self._ldr = json; }, function(err) { //couldn't fetch LDR }); } //invoke the _getLdr method whenever the style property is updated this.addCallback("onPropertyChange", function(e) { if(e.property == "style") { _self._ldr = null; _getLdr(); } }); if(this.style) _getLdr(); if(paramObj && typeof(paramObj) == "string" && connectionId) { if(_self.getResource(paramObj, connectionId) == null) { _self._setResource(paramObj, connectionId, connectionUrl) } } else if(typeof(paramObj) == "object") { //temp variables to assist in parsing var xmlDom = paramObj; var tempDom = null; var parsedText = null; parsedText = xmlDom.getAttribute("Name"); if(parsedText) { _self.resourceName = parsedText; } else { //warning: no resourceName was found } var value = "text"; //cross-browser compatibility if(xmlDom.textContent) value = "textContent"; parsedText = xmlDom.getAttribute("DataResourceName"); if(parsedText && typeof(parsedText) == "string") { _self.dataResourceName = parsedText; } parsedText = xmlDom.getElementsByTagName("Title")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { _self.title = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("Abstract")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { _self.abstract = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("Attribution")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { _self.attribution = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("VisibilityPreference")[0]; if(parsedText && parsedText[value]) { if( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "true") { _self.visibilityPreference = true; } else if ( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "false") { _self.visibilityPreference = false; } else if (typeof(parsedText[value]) == "boolean") { _self.visibilityPreference = parsedText[value]; } } var tempDom = xmlDom.getElementsByTagName("VisibilityPreference")[0]; if(tempDom && typeof(tempDom.getAttribute) != "undefined") { parsedText = tempDom.getAttribute("TrueCondition"); if(parsedText && typeof(parsedText) == "string") { _self.visibilityTrueCondition = parsedText; } parsedText = tempDom.getAttribute("FalseCondition"); if(parsedText && typeof(parsedText) == "string") { _self.visibilityFalseCondition = parsedText; } } parsedText = xmlDom.getElementsByTagName("ZoomInLimit")[0]; if(parsedText && parsedText[value] && !isNaN(parsedText[value])) { parsedText = parseInt(parsedText[value], 10); //force to base 10 _self.zoomRange.max = Dmp.Util.scaleToZoomLevel(parsedText); } parsedText = xmlDom.getElementsByTagName("ZoomOutLimit")[0]; if(parsedText && parsedText[value] && !isNaN(parsedText[value])) { parsedText = parseInt(parsedText[value], 10); //force to base 10 _self.zoomRange.min = Dmp.Util.scaleToZoomLevel(parsedText); } parsedText = xmlDom.getElementsByTagName("Bounds")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { _self.bounds = Dmp.Core.WktTools.toShape(parsedText[value]); } parsedText = xmlDom.getElementsByTagName("IdentifiablePreference")[0]; if(parsedText && parsedText[value]) { if( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "true") { _self.identifiablePreference = true; } else if ( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "false") { _self.identifiablePreference = false; } else if (typeof(parsedText[value]) == "boolean") { _self.identifiablePreference = parsedText[value]; } } parsedText = xmlDom.getElementsByTagName("Time")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { _self.time = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("Filter")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { _self.filter = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("Tag")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { _self.id = parsedText[value]; } if(!_self.id) { _self.id = "ResourceReference_" + Dmp.Util.getGuid(); } parsedText = xmlDom.getElementsByTagName("HotspotPreference")[0]; if(parsedText && parsedText[value]) { if( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "true") { _self.hotspotPreference = true; } else if ( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "false") { _self.hotspotPreference = false; } else if (typeof(parsedText[value]) == "boolean") { _self.hotspotPreference = parsedText[value]; } } parsedText = xmlDom.getElementsByTagName("AttributeLinks")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { _self.attribution = parsedText[value]; } tempDom = xmlDom.getElementsByTagName("Style"); if(tempDom && tempDom.length) { for(var i = 0; i < tempDom.length; i++) { var condition = tempDom[i].getAttribute("Condition"); var styleClass = tempDom[i].getAttribute("Class"); styleClass = styleClass.split("."); var styleObj = null; for(var n in styleClass) { styleObj = new window["Dmp"]["Drawing"][styleClass[styleClass.length-1]](tempDom[i][value]); //create path/body SLD } if(condition) { //if it has a 'Condition' attribute, add it to the conditional styles list var conditionalStyle = new Object(); conditionalStyle.condition = condition; conditionalStyle.style = styleObj; _self.conditionStyles.push(conditionalStyle); } else { //if no 'Condition' attribute is present, it is the default SLD _self.style = styleObj; } } } //create appropriate Resource objects if(_self.dataResourceName && _self.getResource(_self.dataResourceName, connectionId) == null) { _self._setResource(_self.dataResourceName, connectionId, connectionUrl); } if(_self.resourceName && _self.getResource(_self.resourceName, connectionId) == null) { _self._setResource(_self.resourceName, connectionId, connectionUrl); } } //end if } //_load /** * Determines if this ResourceReference is identifiable based on identifiablePreference, scale, and the related resource's metadata. * @returns True if this resource is capable of identify. * @type {Boolean} */ Dmp.Layer.ResourceReference.prototype.isIdentifiable = function() { var _self = this; var res = null; if(!_self.identifiablePreference) { return false; } if(_self.dataResourceName) { res = _self.getResource(_self.dataResourceName, _self.connectionId); if(res == null || !res.isIdentifiable()) { return false; } } else { res = _self.getResource(_self.resourceName, _self.connectionId); if(res == null || !res.isIdentifiable()) { return false; } } return true; } /** * Creates/updates (if it already exists) a [Dmp][Identify][HotspotDisplayCache] if parameter is 'true'. * HotspotDisplayCache is added as a property to this ResourceReference and overrides the logic for Hotspot identifies. * @see Dmp.Identify.HotspotDisplayCache * @param {Boolean} */ Dmp.Layer.ResourceReference.prototype.setHotspot = function(val) { var _self = this; if(val == true && _self.hotspotPreference) { //create/update displayCache if(!_self.displayCache) { _self.displayCache = new Dmp.Identify.HotspotDisplayCache(_self.hotspotId, _self.resourceName, _self.connectionId); } else { _self.displayCache.hotspotId = _self.hotspotId; } } else { //clear displayCache if(_self.displayCache) _self.displayCache.hotspotId = null; } } /** * Calls 'Locate' on its DisplayCache or Resource object, whichever one exists (priority to DisplayCache). * DisplayCaches and Resource objects implement 'Locate' * @see Dmp.Identify.HotspotDisplayCache * @see Dmp.Layer.Resource * @param {Object} posObj. Object containing coordinates (lat/lon and pixX/Y). Required. * @param {Object} map. Handle to the map control object. Used to obtain bounds/scale information. Required. * @param {String} fields. A string array of fields to be returned from the Identify.aspx call. These fields will be added on top of the KeyField and DescriptorFields. Optional. * @param {Function} locateCallback. A function to be invoked upon Identify completion. Optional. * @param {Object} params. An associative array of parameters for locate. Supported parameters: time, filter, zoomRange, isDisplayRequired. Optional. */ Dmp.Layer.ResourceReference.prototype.locate = function ( posObj, map, fields, locateCallback, params) { //TODO: determine whether the Resource 'isIdentifiable' or not var _self = this; if(_self.isVisible(map) || (params && !params.isDisplayRequired) ) { if(_self.displayCache && _self.hotspotId && (!params || params.isDisplayRequired) ) { _self.displayCache.hotspotId = _self.hotspotId; _self.displayCache.locate( posObj, map, fields, locateCallback, params); } else { var res = _self.getResource(); if(!res) { //throw new Error("Resource is null"); return; } res.locate( posObj, map, fields, locateCallback, params); } } } /** * Getting Legend Image: To display on the legend UI or on the printed map */ Dmp.Layer.ResourceReference.prototype.getLegendModel = function() { var legend = new Dmp.Layers.Legend(); legend.layer = this.resourceName; legend.sld = this.style; if(typeof(legend.sld) == "object") legend.sld = legend.sld.styleValue(); legend.sld_body = this.sld_body; return legend; }; //getLegendModel Dmp.Layers.Legend = function() { var _self = this; this.getUrl = function() { var paramArr = ["layer", "sld", "sld_body", "width", "height", "showSize", "bbox", "orientation", "labels", "headers", "swatchWidth", "swatchHeight", "swatchSpacing", "maxSwatches", "maxLabels", "rampWidth", "rampHeight", "full_path", "contextPoint", "xPath", "backgroundStyle", "query", "labelStyle", "headerStyle"]; //var paramDict = Dmp.Util._constructParamsDict(this, paramArr); var paramDict = ""; for(var i = 0; i < paramArr.length; i++) { if( typeof(_self[paramArr[i]]) != "undefined") { paramDict += "&"+paramArr[i]+"=" + _self[paramArr[i]]; } } if(paramDict && paramDict.length > 0) paramDict = paramDict.substring(1); //GL: 3-25-2010 //Legend.aspx currently doesn't support $(FOLDER)/folder/file, only FOLDER/folder/file /* if(paramDict && paramDict.sld) { paramDict.sld = paramDict.sld.replace("$(", ""); paramDict.sld = paramDict.sld.replace(")/", "/"); } */ return "Legend.aspx?" + paramDict; }; //getUrl }; //Legend /** * Converts an XML Dom to a Dictionary of Wms Layer properties/values. * Used during 'map[load]' when an XML Dom is passed to a MapLayer object. * Invoked internally. * @param {XML Dom} jqDom. XML Dom describing the MapLayer to be added. Required. * @returns key-value pair dictionary * @type {Associative Array} * @private */ Dmp.Layer.WmsLayer._domToDict = function(xmlDom){ if(!xmlDom || typeof(xmlDom.getAttribute) == "undefined") { //create via xml return; } var params = new Object(); var parsedText = ""; var value = "text"; //cross-browser compatibility if(xmlDom.textContent) value = "textContent"; parsedText = xmlDom.getAttribute("Source"); if(parsedText) { params["connectionId"] = parsedText; } parsedText = xmlDom.getAttribute("ConnectionUrl"); if(parsedText) { params["ConnectionUrl"] = parsedText; } parsedText = xmlDom.getElementsByTagName("Opacity")[0]; if(parsedText && parsedText[value] && !isNaN(parsedText[value]) ) { params["opacity"] = parseFloat(parsedText[value]); } parsedText = xmlDom.getElementsByTagName("Visibility")[0]; if(parsedText && parsedText[value]) { if(typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "true") params["visibility"] = true; else if(typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "false") params["visibility"] = false; else if (typeof(parsedText[value]) == "boolean") params["visibility"] = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("GroupName")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value] == "string") ) { params["groupName"] = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("GroupType")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value] == "string") ) { params["groupType"] = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("Source")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value] == "string") ) { params["sourceUrl"] = parsedText[value]; } return params; } //domToDict /** * Loads the properties and ResourceReferences of this layer based on an xmlDom. * Invoked internally by map.load(XML). * @see google.maps.Map.prototype.load * @params {Xml Dom} xmlDom. xmlDom object from the Map Compostion Xml ( ... ) * @private */ Dmp.Layer.WmsLayer.prototype._load = function(xmlDom) { var _self = this; var params = Dmp.Layer.WmsLayer._domToDict(xmlDom); Dmp.Util._populateFromJson(_self, params); var resourceReferences = xmlDom.getElementsByTagName("LayerResources")[0]; if(!resourceReferences) return; resourceReferences = resourceReferences.getElementsByTagName("Resource"); if(!resourceReferences || !resourceReferences.length) return; for(var i = 0; i < resourceReferences.length; i++) { var name = resourceReferences[i].getAttribute('Name'); if(name && typeof(name) == "string") { //_self.addChild(tempId, null, null, resourceReferences[i]); _self.addChild(resourceReferences[i]); } } } /** * Iterates through all StyleConditions of each ResourceReference associated with this WmsLayer. * Populates an array with variables based on each StyleCondition and the current state * @returns an array of variables (true/false conditions) * @type {Array} * @private */ Dmp.Layer.WmsLayer.prototype._getStyleConditions = function() { var conditions = new Array(); var layerList = this._map.dmpLayers; for(var n in layerList) { var resRef = layerList[n]._resourceReferences; for(var m in resRef) { if (resRef[m].visibilityTrueCondition && resRef[m].visibilityFalseCondition) { if(resRef[m].isVisible(this._map)) { conditions.push(resRef[m].visibilityTrueCondition); } else { conditions.push(resRef[m].visibilityFalseCondition); } } } } return conditions; } //getStyleConditions /** * Draws this layer on the map when needed * This function is similar to the base .draw method but handles more advanced cases * @addon * @private */ Dmp.Layer.WmsLayer.prototype._drawAddon = function() { var _self = this; if(!_self.visibility) { this.layerDiv.style.visibility = "hidden"; _self.zoomFlag = false; return; } var layers = ""; //must var sld = ""; //optional var sldEmpty = true; var sldBody = null; var attributeLinks = ""; //optional var linksEmpty = true; var query = ""; //optional var queryEmpty = true; var useHotspot = false; var hotspotField = ""; var temporaryResource = ""; var visibleRes = new Array(); var currentConditions = _self._getStyleConditions(); for(var i in _self._resourceReferences) { _self._resourceReferences[i].hotspotId = null; if( _self._resourceReferences[i].isVisible(_self._map) ) { var resourceName = (_self._resourceReferences[i].dataResourceName ||_self._resourceReferences[i].resourceName); layers += "," + resourceName; var style = _self._resourceReferences[i].getCurrentStyle(currentConditions); if( style ) { if( typeof(style) == "object" && typeof(style.getType) == "function") { if(style.getType() == "body") { sldBody = style.styleValue(); } else { sld += "," + style.styleValue(); } } else { sld += "," + style; if(style.indexOf("<") == 0) { sldBody = style; } } sldEmpty = false; } else { sld += ","; } //'attributeLink' check if(_self._resourceReferences[i].attributeLinks) { attributeLinks += "," + _self._resourceReferences[i].attributeLinks; linksEmpty = false; } else { attributeLinks += ","; } //'query' check if(_self._resourceReferences[i].filter) { query += "," + _self._resourceReferences[i].filter; queryEmpty = false; } else { query += ","; } if(_self._resourceReferences[i].hotspotPreference && _self._resourceReferences[i].isIdentifiable() && _self._resourceReferences[i].keyField) { useHotspot = true; hotspotField = _self._resourceReferences[i].keyField; } if(resourceName && resourceName.match(/_T\d{1,3}/gi)){ temporaryResource = resourceName; } //store visible resourceReferences visibleRes.push(_self._resourceReferences[i]); } } //end for _resourceReferences //turn off layer if no children are visible if(layers == "") { _self._zoomFlag = false; this.layerDiv.style.visibility = "hidden"; return; } else if (!_self._zoomFlag && _self.visibility ) { this.layerDiv.style.visibility = "visible"; } //end if/else var view = _self._map.getBounds(); var params = { xMin: view.getSouthWest().lng(), yMin: view.getSouthWest().lat(), xMax: view.getNorthEast().lng(), yMax: view.getNorthEast().lat() }; var callbackWaiting = function() { var url = _self.connectionObj.getBaseUrl(temporaryResource) + "GetMap.aspx?"; url += "bbox=" + params.xMin + "," + params.yMin + "," + params.xMax + "," + params.yMax; url += "&width=" + _self._map.getDiv().offsetWidth; url += "&height=" + _self._map.getDiv().offsetHeight; url += "&layers=" + layers.substring(1); //remove extra first comma if(!sldEmpty) { if(sldBody) { url += "&sld_body=" + sldBody; } else { url += "&sld=" + sld.substring(1); } } if(!linksEmpty) url += "&attributeLinks=" + attributeLinks.substring(1); if(!queryEmpty) url += "&query=" + query.substring(1); if(visibleRes[0].viewInTime) url += "&viewInTime=" + visibleRes[0].viewInTime; for(var n in _self._renderOptions) { url += "&"+n+"=" + _self._renderOptions[n]; } var imgTag = document.createElement('img'); imgTag.onload = _self._imageLoaded; _self.layerDiv.style.position = "absolute"; if (_self.opacity && parseFloat(_self.opacity) <= 1) { _self.layerDiv.style.filter = "alpha(opacity=" + (parseFloat(_self.opacity) * 100) + ")"; } if (_self.zIndex) _self.layerDiv.style.zIndex = _self.zIndex; else _self.layerDiv.style.zIndex = 2; imgTag.name = url; //check for hotspot, issue request if(useHotspot) { url += "&hotspot=true" + "&tempCache=true"; url += "&hotspotField=" + hotspotField; _self.connectionObj.getJson(url, function(json) { _self.hotspotId = json.Cache.TempId; var hotspotUrl = _self.connectionObj.getBaseUrl(_self.hotspotId); for(var i = 0; i < visibleRes.length; i++) { if(visibleRes[i].getResource().getMetadata().GeometryType.toUpperCase() != "POLYGON") { visibleRes[i].attr("hotspotId", _self.hotspotId); visibleRes[i].setHotspot(true); } } hotspotUrl += "GetFile.aspx?File=" + _self.hotspotId + "." + json.Cache.ImageType; hotspotUrl = _self.connectionObj.finalizeUrl(hotspotUrl); imgTag.setAttribute("src", hotspotUrl); }, function(err) { //error }); } else { url = _self.connectionObj.finalizeUrl(url); imgTag.setAttribute("src", url); } } //callbackWaiting if(_self.connectionObj.isReady()) { callbackWaiting(); } else { _self.connectionObj._loadArray.push(callbackWaiting); } } //drawAddon /** * @ignore * Warning: this file is not yet supported! */ /** * Converts an XML Dom to a Dictionary of Tile Layer properties/values. * Used during 'map[load]' when an XML Dom is passed to a MapLayer object. * Invoked internally. * @param {XML Dom} jqDom. XML Dom describing the MapLayer to be added. Required. * @returns key-value pair dictionary * @type {Associative Array} * @private */ Dmp.Layer.TileLayer._domToDict = function(xmlDom) { if(!xmlDom || typeof(xmlDom.getAttribute) == "undefined") { //create via xml return; } var params = new Object(); var parsedText = ""; var value = "text"; //cross-browser compatibility if(xmlDom.textContent) value = "textContent"; parsedText = xmlDom.getAttribute("Source"); if(parsedText) { params["connectionId"] = parsedText; } parsedText = xmlDom.getAttribute("ConnectionUrl"); if(parsedText) { params["connectionUrl"] = parsedText; } parsedText = xmlDom.getElementsByTagName("Opacity")[0]; if(parsedText && parsedText[value] && !isNaN(parsedText[value]) ) { params["opacity"] = parseFloat(parsedText[value]); } parsedText = xmlDom.getElementsByTagName("Visibility")[0]; if(parsedText && parsedText[value]) { if(typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "true") params["visibility"] = true; else if(typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "false") params["visibility"] = false; else if (typeof(parsedText[value]) == "boolean") params["visibility"] = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("GroupName")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value] == "string") ) { params["groupName"] = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("GroupType")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value] == "string") ) { params["groupType"] = parsedText[value]; } return params; } //_domToDict /** * Loads the properties and ResourceReference of this layer based on an xmlDom. * Invoked internally by map.load(XML). * @params {Xml Dom} xmlDom. xmlDom object from the Map Compostion Xml ( ... ) * @private */ Dmp.Layer.TileLayer.prototype._load = function(xmlDom) { var _self = this; var params = Dmp.Layer.TileLayer._domToDict(xmlDom); Dmp.Util._populateFromJson(_self, params); var resourceReferences = xmlDom.getElementsByTagName("LayerResources")[0]; if(!resourceReferences) return; resourceReferences = resourceReferences.getElementsByTagName("Resource"); if(!resourceReferences || !resourceReferences.length) return; for(var i = 0; i < resourceReferences.length; i++) { var name = resourceReferences[i].getAttribute('Name'); if(name && typeof(name) == "string") { //var tempId = (resourceReferences[i].getAttribute("Tag") || ("" + name + "_" + Dmp.Util.getGuid()) ); //_self.addChild(tempId, null, null, resourceReferences[i]); debugger; var resParams = Dmp.Layer.TileLayer.prototype._domToDict2(resourceReferences[i]); Dmp.Util._populateFromJson(_self, resParams); } } } //_load Dmp.Layer.TileLayer.prototype._domToDict2 = function(xmlDom) { //CHANGE to parameter{} return //temp variables to assist in parsing //var xmlDom = paramObj; var _self = this; var tempDom = null; var parsedText = null; var params = new Object(); parsedText = xmlDom.getAttribute("Name"); if(parsedText) { params.resourceName = parsedText; } else { //warning: no resourceName was found } var value = "text"; //cross-browser compatibility if(xmlDom.textContent) value = "textContent"; parsedText = xmlDom.getAttribute("DataResourceName"); if(parsedText && typeof(parsedText) == "string") { params.dataResourceName = parsedText; } parsedText = xmlDom.getElementsByTagName("Title")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { params.title = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("Abstract")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { params.abstract = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("Attribution")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { params.attribution = parsedText[value]; } parsedText = xmlDom.getElementsByTagName("VisibilityPreference")[0]; if(parsedText && parsedText[value]) { if( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "true") { params.visibilityPreference = true; } else if ( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "false") { params.visibilityPreference = false; } else if (typeof(parsedText[value]) == "boolean") { params.visibilityPreference = parsedText[value]; } } var tempDom = xmlDom.getElementsByTagName("VisibilityPreference")[0]; if(tempDom && typeof(tempDom.getAttribute) != "undefined") { parsedText = tempDom.getAttribute("TrueCondition"); if(parsedText && typeof(parsedText) == "string") { params.visibilityTrueCondition = parsedText; } parsedText = tempDom.getAttribute("FalseCondition"); if(parsedText && typeof(parsedText) == "string") { params.visibilityFalseCondition = parsedText; } } parsedText = xmlDom.getElementsByTagName("ZoomInLimit")[0]; if(parsedText && parsedText[value] && !isNaN(parsedText[value])) { parsedText = parseInt(parsedText[value], 10); //force to base 10 params.maxZoom = Dmp.Util.scaleToZoomLevel(parsedText); } parsedText = xmlDom.getElementsByTagName("ZoomOutLimit")[0]; if(parsedText && parsedText[value] && !isNaN(parsedText[value])) { parsedText = parseInt(parsedText[value], 10); //force to base 10 params.minZoom = Dmp.Util.scaleToZoomLevel(parsedText); } parsedText = xmlDom.getElementsByTagName("Bounds")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { params.bounds = Dmp.Core.WktTools.toShape(parsedText[value]); } parsedText = xmlDom.getElementsByTagName("IdentifiablePreference")[0]; if(parsedText && parsedText[value]) { if( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "true") { params.identifiablePreference = true; } else if ( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "false") { params.identifiablePreference = false; } else if (typeof(parsedText[value]) == "boolean") { params.identifiablePreference = parsedText[value]; } } parsedText = xmlDom.getElementsByTagName("HotspotPreference")[0]; if(parsedText && parsedText[value]) { if( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "true") { params.hotspotPreference = true; } else if ( typeof(parsedText[value]) == "string" && parsedText[value].toLowerCase() == "false") { params.hotspotPreference = false; } else if (typeof(parsedText[value]) == "boolean") { params.hotspotPreference = parsedText[value]; } } parsedText = xmlDom.getElementsByTagName("AttributeLinks")[0]; if(parsedText && parsedText[value] && typeof(parsedText[value]) == "string") { params.attribution = parsedText[value]; } tempDom = xmlDom.getElementsByTagName("Style"); if(tempDom && tempDom.length) { for(var i = 0; i < tempDom.length; i++) { var condition = tempDom[i].getAttribute("Condition"); var styleClass = tempDom[i].getAttribute("Class"); styleClass = styleClass.split("."); var styleObj = null; for(var n in styleClass) { styleObj = new window["Dmp"]["Drawing"][styleClass[styleClass.length-1]](tempDom[i][value]); //create path/body SLD } if(condition) { //if it has a 'Condition' attribute, add it to the conditional styles list var conditionalStyle = new Object(); conditionalStyle.condition = condition; conditionalStyle.style = styleObj; params.conditionStyles.push(conditionalStyle); } else { //if no 'Condition' attribute is present, it is the default SLD params.style = styleObj; } } } /* //create appropriate Resource objects if(_self.dataResourceName && _self.getResource(_self.dataResourceName, _self.connectionId) == null) { _self._setResource(_self.dataResourceName, _self.connectionId, _self.connectionUrl); } if(_self.resourceName && _self.getResource(_self.resourceName, _self.connectionId) == null) { _self._setResource(_self.resourceName, _self.connectionId, _self.connectionUrl); } */ return params; } //_load /** * @class * A wrapper that allows read access to Resource's metadata. * Contains the metadata of the Resource and helper functions/variables for Identify capability. * Unique to each Resource and Connection ID. * @param {String} resourceName. Name of the Resource for this object to wrap. Required. * @param {String} connectionId. ID of the Connection object that this Resource belongs. Required. * @param {String} connectionUrl. Source url override to be used for sent web requests. Optional. */ Dmp.Layer.Resource = function(resourceName, connectionId, connectionUrl) { if(!resourceName || !connectionId) { return; } var _metadata = null; var _metadataFetched = false; var _self = this; this._observers = new Object(); this.keyFields = ""; this.descriptorFields = ""; this.LOCATE_TOLERANCE = 10; this.resourceName = resourceName; var key = resourceName.toUpperCase() + "_" + connectionId.toUpperCase(); Dmp.Env.Resources[key] = _self; this.connectionObj = Dmp.Env.Connections.getConnectionObject(connectionId, connectionUrl); var callbackWaiting = function() { //var url = Dmp.Env.Connections[connectionId].getBaseUrl(resourceName) + "BrowseLayers.aspx?"; var url = _self.connectionObj.getBaseUrl(resourceName) + "BrowseLayers.aspx?"; url += "layers=" + resourceName; //Dmp.Env.Connections[connectionId].getJson(url, function(json) { _self.connectionObj.getJson(url, function(json) { _metadataFetched = true; if( json && json.Layers && json.Layers.Layer) { _metadata = json.Layers.Layer; if( typeof(_metadata[0]) != "undefined" ) { _metadata = _metadata[0]; } _self.keyFields = (_metadata.KeyFields || "_DMP_ID"); } for(var n in _self._observers["metadataLoaded"]) { _self._observers["metadataLoaded"][n](_metadata); } }, function(err) { //throw new Error("error retrieving metadata: " + err.Response.Error.message); _metadataFetched = true; }); } //if(Dmp.Env.Connections[connectionId].isReady()) { callbackWaiting(); } //else { Dmp.Env.Connections[connectionId]._loadArray.push(callbackWaiting); } if(_self.connectionObj.isReady()) { callbackWaiting(); } else { _self.connectionObj._loadArray.push(callbackWaiting); } /** * @returns true if this reference is capable of identify * @type {Boolean} */ this.isIdentifiable = function() { if ( _metadata && typeof(_metadata.Schema) != "undefined" ) { return true; } return false; } /** * @returns the metaData for this reference * @type {Object} */ this.getMetadata = function() { return _metadata; } this.isReady = function() { if(_metadataFetched) return true; return false; } /** * Attach a listener to 'event' and invoke 'funct' upon trigger. * The callback function will be parameterized with ([EVENT], {[VALUES (if applicable)]}). * Current supported events: "metadataLoaded". * @param {String} event. The event to observe. Required. * @param {Function} funct. The function to be invoke when the given event is triggered. Required. */ this.addCallback = function(event, funct) { if(!event || typeof(event) != "string") { return; } else if (!funct || typeof(funct) != "function") { return; } if(typeof(_self._observers[event]) == "undefined") { _self._observers[event] = new Array(); } _self._observers[event].push(funct); } /** * Constructs an 'Identify aspx' request based on this resource's data and the parameterized variables. * @param {Object} posObj. Object containing coordinates (lat/lon and pixX/Y). Required. * @param {Object} map. Handle to the map control object. Used to obtain bounds/scale information. Required. * @param {String} fields. A string array of fields to be returned from the Identify.aspx call. These fields will be added on top of the KeyField and DescriptorFields. Optional. * @param {Function} locateCallback. A function to be invoked upon Identify completion. Optional. * @param {Object} params. An associative array of parameters for locate. Supported parameters: time, filter, zoomRange. Optional. */ this.locate = function ( posObj, map, fields, locateCallback, params ) { var url = _self.connectionObj.getBaseUrl(resourceName) + "Identify.aspx?"; url += "&dataSource=" + resourceName; url += "&pixX=" + Math.round(posObj.pixX); //hotspot specific url += "&pixY=" + Math.round(posObj.pixY); url += "&lat=" + posObj.lat; url += "&long=" + posObj.lon; var callbackWaiting = function() { //what do keyFields look like? url += "&keyField=" + _self.keyFields; //if(_metadata && _metadata.KeyFields) { url += "&keyField=" + _metadata.KeyFields; } //else { url += "&keyField=" + "_DMP_ID"; } //FIELDS var queryFields = ""; if(fields) { //string or array or strings? for(var n in fields) { queryFields += "," + fields[n]; } if(queryFields.length > 0) { queryFields = queryFields.substr(1); } } //else { /* if(typeof(_self.keyFields) == "string") { for(var n in _self.keyFields) { queryFields += "," + _self.keyFields[n]; break; } } */ if(queryFields.indexOf(_self.keyFields) < 0) queryFields += "," + _self.keyFields; if(_self.descriptorFields) { for(var n in descFields) { queryFields += "," + descFields[n]; } } //} if(queryFields != "") { url += "&fields=" + queryFields; } //TIME if(params && params.time) { url += "&viewInTime=" + time; } //FILTER if(params && params.filter) { url += "&query=" + filter; } //POINT / LINESTRING identify without hotspot if(_metadata && (_metadata.GeometryType == "POINT" || _metadata.GeometryType == "LINESTRING") ){ if(typeof(Dmp.Util.distanceBetweenPoints) == "undefined") { //throw new Error("Include the 'Identify' package to Identify"); return; } //(map, xMin, yMin, xMax, yMax) var distInMeters = Dmp.Util.distanceBetweenPoints(map, 0, 0, _self.LOCATE_TOLERANCE, _self.LOCATE_TOLERANCE); if (distInMeters){ distInMeters = Math.round(distInMeters); url += "&bufferDist=" + distInMeters; url += "&bufferUnit=3"; //meters } } _self.connectionObj.getJson(url, function(json) { if( typeof(locateCallback) != "undefined" && locateCallback) { locateCallback(json); } }, function(err) { //error }); } if(_self.isReady()) { callbackWaiting(); } else { _self.addCallback("metadataLoaded", callbackWaiting); } } //locate } /** * parses the wkt and returns the geometry type and an array of points * @param {String} wktString * @returns geoType or array of points * @type {geoType, Array} */ Dmp.Core.WktTools.getGeoStructFromWkt = function(wktString) { // parses out points var regex = new RegExp(/(?:\()([^)(]*)(?:\))/g); var matches = regex.exec(wktString); var wktPoints = null; if (matches != null && matches.length > 0) { wktPoints = matches[0].substring(1, matches[0].length - 1); } // parses out type; regex = new RegExp(/[^(]*/g); var m1 = regex.exec(wktString); var geoType = null; if (m1 != null && m1.length > 0) { geoType = m1[0].replace(/ /, ''); } if (wktPoints == null || wktPoints == '' || geoType == null || geoType == '') return null; var pointTokens = wktPoints.split(","); var retArray = []; for (var i = 0; i < pointTokens.length; i++) { var twoValues = pointTokens[i].split(" "); twoValues = Dmp.Core.WktTools._deleteBlankStringFromArray(twoValues); if (twoValues.length != 2) throw "unsupported/malformatted wkt format:" + wktPoints; retArray.push({ x: parseFloat(twoValues[0]), y: parseFloat(twoValues[1]) }); } //for i return { Type: geoType, Points: retArray }; }; //getGeoStructFromWkt /** * given an array of strings, delete the ones with "", " ", or multiple blanks. Preserve the original order * @param {Array} stringArray * @private * @returns array of strings * @type {Array} */ Dmp.Core.WktTools._deleteBlankStringFromArray = function(stringArray) { var retArray = []; for (var j = 0; j < stringArray.length; j++) { var isBlank = true; var arr = stringArray[j].split(" "); for (var k = 0; k < arr.length; k++) if (arr[k].length != 0) { isBlank = false; break; } if (!isBlank) { var v = stringArray[j]; //trim value v = v.replace(/\s*$/, ""); v = v.replace(/^\s*/, ""); retArray.push(v); } } return retArray; }; //_deleteBlankStringFromArray /** * CONFIDENTIAL AND PROPRIETARY * This document is confidential and contains proprietary information. * Neither this document nor any of the information contained herein * may be reproduced or disclosed to any person under any circumstances * without the express written consent of Digital Map Products. * * Copyright: Copyright (c) 2006 * Company: Digital Map Products * @author Samir * @version 1.0 * */ Dmp.Util.EventPriority = function() { this.LOWEST = 1 this.LOW = 2; this.MEDIUM = 3; this.HIGH = 9000; this.HIGHEST = 99999; }; //Dmp.Util.EventPriority /** * Center for adding observers, callbacks, and sending notifcations of event occurrances * @constructor */ Dmp.Util.EventManager = function(){ //assuming that an event will be notified more frequently than adding observers this._event2PriorityArray = new Array(); //some events are already executed and observers which are added later should be dispatched immediately. this._eventPassed = new Array(); //contains priority rankings var eventPriority = new Dmp.Util.EventPriority(); //flags to detect invalid priorities var flag_highestPriority = false; var flag_lowestPriority = false; /** * Notifies all listeners of the specified event. * Order of notification respects each listener's priority * @param {Object} evtObj. 'eventType' must be a property of the evtObj */ this.notify = function (evtObj){ if (evtObj==null) throw new Dmp.Exception("Event object is NULL"); if (evtObj.eventType == null) throw new Dmp.Exception("evtObj.eventType is NULL"); if (evtObj.deadEvent){ this.setDispatchedEvent(evtObj.eventType, evtObj); } //Get an array sorted by priority var priorityArray = this._event2PriorityArray[evtObj.eventType]; //nobody listening if (priorityArray==null) return null; //the observers can choose to call removeObserver and tamper with a priority array. //I will need to create a clone of an array before calling execute. var priorityArrClone = []; //clone for ( var i=0; ib * @type {int} * @private */ function sortByPriorityMethod(a, b) { //returning negative for ab if (a.priority==null) a.priority = 2; if (b.priority==null) b.priority = 2; if (a.priority>b.priority){ return -1; }else if (a.priority= 4) break; htm += key+": " + record[key]+ "
"; count ++; };//for key surfaceObj.html(htm); surfaceObj.htmlText = htm; surfaceObj.record = record; if (succCallback) succCallback(htm); };//transform };//Dmp.Util.DefaultTransformer //For Google Map Dmp.Core.WktTools.toShape = function(wktString, color, weight, opacity, fillColor, fillOpacity) { var geoStruct = Dmp.Core.WktTools.getGeoStructFromWkt(wktString); var gPoints = []; for (var i = 0; i < geoStruct.Points.length; i++) { gPoints.push(new google.maps.LatLng(geoStruct.Points[i].y, geoStruct.Points[i].x)); } if (geoStruct.Type == "POINT") { if (gPoints.length != 1) throw null; var gMark = new google.maps.Marker({position : gPoints[0]}); gMark.Type = "Point"; //google map's marker does not have a .Type attribute. Added for shape identification return gMark; //return a GMarker instead of points, contains essential "setImage" function } else if (geoStruct.Type == "LINESTRING") { if (gPoints.length < 2) throw null; return new google.maps.Polyline({ path: gPoints, strokeColor: color, strokeWeight: weight, strokeOpacity: opacity }); } else if (geoStruct.Type == "POLYGON" || geoStruct.Type == "MULTIPOLYGON") { if (gPoints.length < 3) throw null; return new google.maps.Polygon({ paths: gPoints, strokeColor: color, strokeOpacity: opacity, strokeWeight: weight, fillColor: fillColor, fillOpacity: fillOpacity }); } else { return null; } } //toShape /** * Takes a Google map zoom level as input * @param {Number} zoomLevel * @returns a unitless scale representative of the zoom level * @type {Number} */ Dmp.Util.zoomLevelToScale = function( zoomLevel ) { if(isNaN(zoomLevel)) { zoomLevel = map.getZoom(); //Google } var screenResolution = 96; //pixels per inch var lat = 38; //latitude var scale = screenResolution * 39.37 * 156543.04 * Math.cos(lat*Math.PI/180)/(Math.pow(2,zoomLevel)); return scale; } /** * Takes a unitless zoom scale as input * @param {Number} scale * @returns zoom level representative of the a unitless scale * @type {Number} */ Dmp.Util.scaleToZoomLevel = function(scale) { if(!scale || isNaN(scale)) { zoomLevel = map.getZoom(); //Google } var screenResolution = 96; //pixels per inch var lat = 38; //latitude return Math.round(Math.log(screenResolution * 39.37 * 156543.04 * Math.cos(lat*Math.PI/180)/scale)/Math.LN2); } ////////////////////////////////////////////////////////////// //old Event Manager //only Pause ("onmousepause") and Click ("click") events are supported ////////////////////////////////////////////////////////////// //Dmp.Map.EventManager = function(gMap) { // var mGDivOffset = $("#" + gMap.getContainer().id).offset(); // this.addCallback = function(event, callback) { // if (event == "onmousepause") { // var po = new _PauseHandler(callback); // // /*this.addCallback("mousemove", po.moved); // this.addCallback("mouseout", po.clear); // this.addCallback("mouseleave", po.clear); // this.addCallback("mousedown", po.clear);*/ // // GEvent.addListener(gMap, "mousemove", po.moved); //try removing on // GEvent.addListener(gMap, "mouseout", po.clear); // GEvent.addListener(gMap, "mouseleave", po.clear); // GEvent.addListener(gMap, "mousedown", po.clear); // GEvent.addListener(gMap, "click", po.clear); // // // } else { // //dud parameter contains gMap's overlay. In this case it's null (and thus called dud) // //e contains x & y event properties (unless an object is clicked, 'a' will contain properties) // GEvent.addListener(gMap, "click", function(dud, e, a) { // // if(!e){ //if an object is clicked (as opposed to the map), the event property changes argument ordering // e = a; // } // callback(getEventObj(e)); // }); // } // }; //addCallback // function _PauseHandler(callback) { // var t; // var lastX, lastY; // // this.moved = function(e) { // //debugger; // if (lastX && lastY && e.x == lastX && e.y == lastY) return; // lastX = e.x; // lastY = e.y; // var clonedEvt = cloneVeEvent(e); // if (t) window.clearTimeout(t); // t = window.setTimeout(function() { // //debugger; // callback(getEventObj(clonedEvt)); // }, 800); // }; //moved // this.clear = function(e) { // if (t) window.clearTimeout(t); // } // }; //_PauseHandler // function cloneVeEvent(e) { // var newE = new Object(); // newE.x = e.x; // newE.y = e.y; // return newE; // }; //cloneVeEvent // function getEventObj(e) { // //if (e.pageX == null && e.clientX) e.pageX = e.clientX; // //if (e.pageY == null && e.clientY) e.pageY = e.clientY; // if (!e.x || !e.y) return; //e not instantiated // // var gLL = new GLatLng(e.y, e.x); // //debugger; // var pixOnMap = gMap.fromLatLngToContainerPixel(gLL); // //var pixOnMap = { x: (e.pageX - mVEDivOffset.left), y: (e.pageY - mVEDivOffset.top) }; // //var absXY = { x: e.pageX, y: e.pageY }; // // //e's x & y are relative (as opposed to Bing, Bing is absolute) // var absXY = { x: pixOnMap.x + mGDivOffset.left, y: pixOnMap.y + mGDivOffset.top}; // // //returns GLatLng of the google map // var latlon = gMap.getBounds().getCenter(); // // var evtObj = { // pixX: pixOnMap.x, // pixY: pixOnMap.y, // absX: absXY.x, // absY: absXY.y, // lon: e.x, //latlon.lng(), // lat: e.y, //latlon.lat(), // extents: {} // }; // // var view = gMap.getBounds(); // evtObj.extents.xMin = view.getSouthWest().lng(); // evtObj.extents.yMin = view.getSouthWest().lat(); // evtObj.extents.xMax = view.getNorthEast().lng(); // evtObj.extents.yMax = view.getNorthEast().lat(); // evtObj.date = new Date(); // return evtObj; // }; //getEventObj //}; //Dmp.Map.EventManager ////Dmp.Map.EventManager.prototype = new Dmp.Util.EventManager(); //For Google Map var flag_setup = false; //used to initialize EM /** * @class * Event Manager that overrides the map's events, allowing for priorities and additional events. * @param {Dom Element} veMap. The dom element where the VEMap will be contained. Required. */ Dmp.Map.EventManager = function(veMap) { this.base = Dmp.Util.EventManager; this.base(); var _self = this; var evtMapping = []; //Key is HTML event //Value is DMP event evtMapping["onmousedown"] = "onmousedown"; evtMapping["onmouseup"] = "onmouseup"; evtMapping["onmousemove"] = "onmousemove"; evtMapping["onmouseclick"] = "onmouseclick"; //mousedown+mouseup within pixels-moved threshold evtMapping["ondblclick"] = "onmousedoubleclick"; //2 consecutive onMouseClicks. Duration between clicks and movement threshold determined on DOM level evtMapping["onmouseout"] = "onmouseout"; //not used //add-ons evtMapping["onrightclick"] = "onrightclick"; //mousedown+mouseup within threshold and rightMouseButton is used evtMapping["onmousepause"] = "onmousepause"; //mousemove without another mousemove for X seconds evtMapping["onmousewheel"] = "onmousewheel"; //mouseWheel scrolls up or down (same event) var attachEventMethodName; var useCapture; var isMouseDown = false; var lastMouseDown = null; var _mousePausethread = null; var MOUSE_PAUSE_TIME = 800; var MOUSE_CLICK_THRESHOLD = 4; //max # of pixel difference between mouseDown and mouseUp to register MouseClick //multiple browser support if (veMap.attachEvent){ //IE attachEventMethodName = "attachEvent"; useCapture = null; } else if (veMap.addEventListener){ attachEventMethodName = "addEventListener"; useCapture = false; } else if (veMap.AttachEvent){ attachEventMethodName = "AttachEvent"; useCapture = false; } else { alert("Warning: Unsupported Browser."); } //assignHtmlEvent function assignHtmlEvent(htmlType, eventType){ if (htmlType=="onmouseclick") htmlType = "onclick"; else if (htmlType=="onmousedoubleclick") htmlType = "ondblclick"; //set page event handlers for onload and unload veMap[attachEventMethodName](htmlType, function(e){ forwardMouseEvent(eventType, e); }, useCapture); }//end assignHtmlEvent //setup this.setup = function(){ for (var htmlType in evtMapping){ assignHtmlEvent(htmlType, evtMapping[htmlType]); //pre-assign events from the array } //On mouse out, clear the mouse pause thread veMap[attachEventMethodName]("onmouseout", function(e){ if( _mousePausethread) window.clearTimeout(_mousePausethread); }, useCapture); veMap[attachEventMethodName]("onmouseleave", function(e){ if( _mousePausethread) window.clearTimeout(_mousePausethread); }, useCapture); //Hijack HTML event veMap.originalAttachEvent = veMap[attachEventMethodName]; //catch others' events (after pre-assigning the array veMap[attachEventMethodName] = attachEventHijackMethod; //add observers for the caught events } //end SETUP //attachEventHijackMethod function attachEventHijackMethod ( eventType, func ) { eventType = (""+eventType).toLowerCase(); if (evtMapping[eventType]==null){ veMap.originalAttachEvent(eventType, func); return; } var observer = new eventOverrideObserver(func); _self.addObserver( observer, "handleEvent", evtMapping[eventType], 3 ); }//end attachEventHijackMethod //eventOverrideObserver function eventOverrideObserver(func ) { this.callbackFunc = func; this.handleEvent = function(dmpEvt) { func(dmpEvt.p1, dmpEvt.p2, dmpEvt.p3); } }//eventOverrideObserver //isMouseButtonDown //currently only running in I.E. this.isMouseButtonDown = function(event){ if (event==null || event.button==null) return false; var buttonCode = event.button; if (false) {//(this.isFireFox && false){ //For FF: //0 for standard 'click', usually left button //1 for middle button, usually wheel-click //2 for right button, usually right-click return (buttonCode>0); }else if (true){//(this.isIE){ //For IE: //0 Default. No button is pressed. //1 Left button is pressed. //2 Right button is pressed. //3 Left and right buttons are both pressed. //4 Middle button is pressed. //5 Left and middle buttons both are pressed. //6 Right and middle buttons are both pressed. //7 All three buttons are pressed. return (buttonCode>0); } };//end isMouseButtonDown //callDirectEvents function callDirectEvents(eventType){ //directly call VE event handler. Go through all the observers //debugger; var obsArr = _self.getObservers(eventType); for (var o=0; obsArr!=null && o[SLDPATH] * @type {String} */ this.toXml = function() { var xml = " * @type {String} */ this.toXml = function() { var xml = "