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 if (typeof(Dmp.Env) == 'undefined') Dmp.Env = new Object(); if (typeof(Dmp.Env.Connections) == 'undefined') Dmp.Env.Connections = new Object(); Dmp.Env.Connections["SS"] = new Dmp.Conn.Connection("http://parcelstream.com/InitSession.aspx", ["t0", "t1", "t2", "t3"]);