option is\n+ * provided or if you intend to call the
method later.\n+ * options - {Object} Optional object with properties to tag onto the map.\n *\n- * Valid options:\n- * rules - {Array()} List of rules to be added to the\n- * style.\n+ * Valid options (in addition to the listed API properties):\n+ * center - {|Array} The default initial center of the map.\n+ * If provided as array, the first value is the x coordinate,\n+ * and the 2nd value is the y coordinate.\n+ * Only specify if is provided.\n+ * Note that if an ArgParser/Permalink control is present,\n+ * and the querystring contains coordinates, center will be set\n+ * by that, and this option will be ignored.\n+ * zoom - {Number} The initial zoom level for the map. Only specify if\n+ * is provided.\n+ * Note that if an ArgParser/Permalink control is present,\n+ * and the querystring contains a zoom level, zoom will be set\n+ * by that, and this option will be ignored.\n+ * extent - {|Array} The initial extent of the map.\n+ * If provided as an array, the array should consist of\n+ * four values (left, bottom, right, top).\n+ * Only specify if and are not provided.\n * \n- * Returns:\n- * {}\n+ * Examples:\n+ * (code)\n+ * // create a map with default options in an element with the id \"map1\"\n+ * var map = new OpenLayers.Map(\"map1\");\n+ *\n+ * // create a map with non-default options in an element with id \"map2\"\n+ * var options = {\n+ * projection: \"EPSG:3857\",\n+ * maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000),\n+ * center: new OpenLayers.LonLat(-12356463.476333, 5621521.4854095)\n+ * };\n+ * var map = new OpenLayers.Map(\"map2\", options);\n+ *\n+ * // map with non-default options - same as above but with a single argument,\n+ * // a restricted extent, and using arrays for bounds and center\n+ * var map = new OpenLayers.Map({\n+ * div: \"map_id\",\n+ * projection: \"EPSG:3857\",\n+ * maxExtent: [-18924313.432222, -15538711.094146, 18924313.432222, 15538711.094146],\n+ * restrictedExtent: [-13358338.893333, -9608371.5085962, 13358338.893333, 9608371.5085962],\n+ * center: [-12356463.476333, 5621521.4854095]\n+ * });\n+ *\n+ * // create a map without a reference to a container - call render later\n+ * var map = new OpenLayers.Map({\n+ * projection: \"EPSG:3857\",\n+ * maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000)\n+ * });\n+ * (end)\n */\n- initialize: function(style, options) {\n+ initialize: function(div, options) {\n+\n+ // If only one argument is provided, check if it is an object.\n+ if (arguments.length === 1 && typeof div === \"object\") {\n+ options = div;\n+ div = options && options.div;\n+ }\n+\n+ // Simple-type defaults are set in class definition. \n+ // Now set complex-type defaults \n+ this.tileSize = new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH,\n+ OpenLayers.Map.TILE_HEIGHT);\n+\n+ this.paddingForPopups = new OpenLayers.Bounds(15, 15, 15, 15);\n+\n+ this.theme = OpenLayers._getScriptLocation() +\n+ 'theme/default/style.css';\n \n+ // backup original options\n+ this.options = OpenLayers.Util.extend({}, options);\n+\n+ // now override default options \n OpenLayers.Util.extend(this, options);\n- this.rules = [];\n- if (options && options.rules) {\n- this.addRules(options.rules);\n+\n+ var projCode = this.projection instanceof OpenLayers.Projection ?\n+ this.projection.projCode : this.projection;\n+ OpenLayers.Util.applyDefaults(this, OpenLayers.Projection.defaults[projCode]);\n+\n+ // allow extents and center to be arrays\n+ if (this.maxExtent && !(this.maxExtent instanceof OpenLayers.Bounds)) {\n+ this.maxExtent = new OpenLayers.Bounds(this.maxExtent);\n+ }\n+ if (this.minExtent && !(this.minExtent instanceof OpenLayers.Bounds)) {\n+ this.minExtent = new OpenLayers.Bounds(this.minExtent);\n+ }\n+ if (this.restrictedExtent && !(this.restrictedExtent instanceof OpenLayers.Bounds)) {\n+ this.restrictedExtent = new OpenLayers.Bounds(this.restrictedExtent);\n+ }\n+ if (this.center && !(this.center instanceof OpenLayers.LonLat)) {\n+ this.center = new OpenLayers.LonLat(this.center);\n }\n \n- // use the default style from OpenLayers.Feature.Vector if no style\n- // was given in the constructor\n- this.setDefaultStyle(style ||\n- OpenLayers.Feature.Vector.style[\"default\"]);\n+ // initialize layers array\n+ this.layers = [];\n \n- this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + \"_\");\n- },\n+ this.id = OpenLayers.Util.createUniqueID(\"OpenLayers.Map_\");\n \n- /** \n- * APIMethod: destroy\n- * nullify references to prevent circular references and memory leaks\n- */\n- destroy: function() {\n- for (var i = 0, len = this.rules.length; i < len; i++) {\n- this.rules[i].destroy();\n- this.rules[i] = null;\n+ this.div = OpenLayers.Util.getElement(div);\n+ if (!this.div) {\n+ this.div = document.createElement(\"div\");\n+ this.div.style.height = \"1px\";\n+ this.div.style.width = \"1px\";\n }\n- this.rules = null;\n- this.defaultStyle = null;\n- },\n \n- /**\n- * Method: createSymbolizer\n- * creates a style by applying all feature-dependent rules to the base\n- * style.\n- * \n- * Parameters:\n- * feature - {} feature to evaluate rules for\n- * \n- * Returns:\n- * {Object} symbolizer hash\n- */\n- createSymbolizer: function(feature) {\n- var style = this.defaultsPerSymbolizer ? {} : this.createLiterals(\n- OpenLayers.Util.extend({}, this.defaultStyle), feature);\n+ OpenLayers.Element.addClass(this.div, 'olMap');\n \n- var rules = this.rules;\n+ // the viewPortDiv is the outermost div we modify\n+ var id = this.id + \"_OpenLayers_ViewPort\";\n+ this.viewPortDiv = OpenLayers.Util.createDiv(id, null, null, null,\n+ \"relative\", null,\n+ \"hidden\");\n+ this.viewPortDiv.style.width = \"100%\";\n+ this.viewPortDiv.style.height = \"100%\";\n+ this.viewPortDiv.className = \"olMapViewport\";\n+ this.div.appendChild(this.viewPortDiv);\n \n- var rule, context;\n- var elseRules = [];\n- var appliedRules = false;\n- for (var i = 0, len = rules.length; i < len; i++) {\n- rule = rules[i];\n- // does the rule apply?\n- var applies = rule.evaluate(feature);\n+ this.events = new OpenLayers.Events(\n+ this, this.viewPortDiv, null, this.fallThrough, {\n+ includeXY: true\n+ }\n+ );\n \n- if (applies) {\n- if (rule instanceof OpenLayers.Rule && rule.elseFilter) {\n- elseRules.push(rule);\n- } else {\n- appliedRules = true;\n- this.applySymbolizer(rule, style, feature);\n+ if (OpenLayers.TileManager && this.tileManager !== null) {\n+ if (!(this.tileManager instanceof OpenLayers.TileManager)) {\n+ this.tileManager = new OpenLayers.TileManager(this.tileManager);\n+ }\n+ this.tileManager.addMap(this);\n+ }\n+\n+ // the layerContainerDiv is the one that holds all the layers\n+ id = this.id + \"_OpenLayers_Container\";\n+ this.layerContainerDiv = OpenLayers.Util.createDiv(id);\n+ this.layerContainerDiv.style.zIndex = this.Z_INDEX_BASE['Popup'] - 1;\n+ this.layerContainerOriginPx = {\n+ x: 0,\n+ y: 0\n+ };\n+ this.applyTransform();\n+\n+ this.viewPortDiv.appendChild(this.layerContainerDiv);\n+\n+ this.updateSize();\n+ if (this.eventListeners instanceof Object) {\n+ this.events.on(this.eventListeners);\n+ }\n+\n+ if (this.autoUpdateSize === true) {\n+ // updateSize on catching the window's resize\n+ // Note that this is ok, as updateSize() does nothing if the \n+ // map's size has not actually changed.\n+ this.updateSizeDestroy = OpenLayers.Function.bind(this.updateSize,\n+ this);\n+ OpenLayers.Event.observe(window, 'resize',\n+ this.updateSizeDestroy);\n+ }\n+\n+ // only append link stylesheet if the theme property is set\n+ if (this.theme) {\n+ // check existing links for equivalent url\n+ var addNode = true;\n+ var nodes = document.getElementsByTagName('link');\n+ for (var i = 0, len = nodes.length; i < len; ++i) {\n+ if (OpenLayers.Util.isEquivalentUrl(nodes.item(i).href,\n+ this.theme)) {\n+ addNode = false;\n+ break;\n }\n }\n+ // only add a new node if one with an equivalent url hasn't already\n+ // been added\n+ if (addNode) {\n+ var cssNode = document.createElement('link');\n+ cssNode.setAttribute('rel', 'stylesheet');\n+ cssNode.setAttribute('type', 'text/css');\n+ cssNode.setAttribute('href', this.theme);\n+ document.getElementsByTagName('head')[0].appendChild(cssNode);\n+ }\n }\n \n- // if no other rules apply, apply the rules with else filters\n- if (appliedRules == false && elseRules.length > 0) {\n- appliedRules = true;\n- for (var i = 0, len = elseRules.length; i < len; i++) {\n- this.applySymbolizer(elseRules[i], style, feature);\n+ if (this.controls == null) { // default controls\n+ this.controls = [];\n+ if (OpenLayers.Control != null) { // running full or lite?\n+ // Navigation or TouchNavigation depending on what is in build\n+ if (OpenLayers.Control.Navigation) {\n+ this.controls.push(new OpenLayers.Control.Navigation());\n+ } else if (OpenLayers.Control.TouchNavigation) {\n+ this.controls.push(new OpenLayers.Control.TouchNavigation());\n+ }\n+ if (OpenLayers.Control.Zoom) {\n+ this.controls.push(new OpenLayers.Control.Zoom());\n+ } else if (OpenLayers.Control.PanZoom) {\n+ this.controls.push(new OpenLayers.Control.PanZoom());\n+ }\n+\n+ if (OpenLayers.Control.ArgParser) {\n+ this.controls.push(new OpenLayers.Control.ArgParser());\n+ }\n+ if (OpenLayers.Control.Attribution) {\n+ this.controls.push(new OpenLayers.Control.Attribution());\n+ }\n }\n }\n \n- // don't display if there were rules but none applied\n- if (rules.length > 0 && appliedRules == false) {\n- style.display = \"none\";\n+ for (var i = 0, len = this.controls.length; i < len; i++) {\n+ this.addControlToMap(this.controls[i]);\n }\n \n- if (style.label != null && typeof style.label !== \"string\") {\n- style.label = String(style.label);\n+ this.popups = [];\n+\n+ this.unloadDestroy = OpenLayers.Function.bind(this.destroy, this);\n+\n+\n+ // always call map.destroy()\n+ OpenLayers.Event.observe(window, 'unload', this.unloadDestroy);\n+\n+ // add any initial layers\n+ if (options && options.layers) {\n+ /** \n+ * If you have set options.center, the map center property will be\n+ * set at this point. However, since setCenter has not been called,\n+ * addLayers gets confused. So we delete the map center in this \n+ * case. Because the check below uses options.center, it will\n+ * be properly set below.\n+ */\n+ delete this.center;\n+ delete this.zoom;\n+ this.addLayers(options.layers);\n+ // set center (and optionally zoom)\n+ if (options.center && !this.getCenter()) {\n+ // zoom can be undefined here\n+ this.setCenter(options.center, options.zoom);\n+ }\n }\n \n- return style;\n+ if (this.panMethod) {\n+ this.panTween = new OpenLayers.Tween(this.panMethod);\n+ }\n+ if (this.zoomMethod && this.applyTransform.transform) {\n+ this.zoomTween = new OpenLayers.Tween(this.zoomMethod);\n+ }\n },\n \n- /**\n- * Method: applySymbolizer\n- *\n- * Parameters:\n- * rule - {}\n- * style - {Object}\n- * feature - {}\n+ /** \n+ * APIMethod: getViewport\n+ * Get the DOMElement representing the view port.\n *\n * Returns:\n- * {Object} A style with new symbolizer applied.\n+ * {DOMElement}\n */\n- applySymbolizer: function(rule, style, feature) {\n- var symbolizerPrefix = feature.geometry ?\n- this.getSymbolizerPrefix(feature.geometry) :\n- OpenLayers.Style.SYMBOLIZER_PREFIXES[0];\n+ getViewport: function() {\n+ return this.viewPortDiv;\n+ },\n \n- var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer;\n+ /**\n+ * APIMethod: render\n+ * Render the map to a specified container.\n+ * \n+ * Parameters:\n+ * div - {String|DOMElement} The container that the map should be rendered\n+ * to. If different than the current container, the map viewport\n+ * will be moved from the current to the new container.\n+ */\n+ render: function(div) {\n+ this.div = OpenLayers.Util.getElement(div);\n+ OpenLayers.Element.addClass(this.div, 'olMap');\n+ this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);\n+ this.div.appendChild(this.viewPortDiv);\n+ this.updateSize();\n+ },\n \n- if (this.defaultsPerSymbolizer === true) {\n- var defaults = this.defaultStyle;\n- OpenLayers.Util.applyDefaults(symbolizer, {\n- pointRadius: defaults.pointRadius\n- });\n- if (symbolizer.stroke === true || symbolizer.graphic === true) {\n- OpenLayers.Util.applyDefaults(symbolizer, {\n- strokeWidth: defaults.strokeWidth,\n- strokeColor: defaults.strokeColor,\n- strokeOpacity: defaults.strokeOpacity,\n- strokeDashstyle: defaults.strokeDashstyle,\n- strokeLinecap: defaults.strokeLinecap\n- });\n- }\n- if (symbolizer.fill === true || symbolizer.graphic === true) {\n- OpenLayers.Util.applyDefaults(symbolizer, {\n- fillColor: defaults.fillColor,\n- fillOpacity: defaults.fillOpacity\n- });\n+ /**\n+ * Method: unloadDestroy\n+ * Function that is called to destroy the map on page unload. stored here\n+ * so that if map is manually destroyed, we can unregister this.\n+ */\n+ unloadDestroy: null,\n+\n+ /**\n+ * Method: updateSizeDestroy\n+ * When the map is destroyed, we need to stop listening to updateSize\n+ * events: this method stores the function we need to unregister in \n+ * non-IE browsers.\n+ */\n+ updateSizeDestroy: null,\n+\n+ /**\n+ * APIMethod: destroy\n+ * Destroy this map.\n+ * Note that if you are using an application which removes a container\n+ * of the map from the DOM, you need to ensure that you destroy the\n+ * map *before* this happens; otherwise, the page unload handler\n+ * will fail because the DOM elements that map.destroy() wants\n+ * to clean up will be gone. (See \n+ * http://trac.osgeo.org/openlayers/ticket/2277 for more information).\n+ * This will apply to GeoExt and also to other applications which\n+ * modify the DOM of the container of the OpenLayers Map.\n+ */\n+ destroy: function() {\n+ // if unloadDestroy is null, we've already been destroyed\n+ if (!this.unloadDestroy) {\n+ return false;\n+ }\n+\n+ // make sure panning doesn't continue after destruction\n+ if (this.panTween) {\n+ this.panTween.stop();\n+ this.panTween = null;\n+ }\n+ // make sure zooming doesn't continue after destruction\n+ if (this.zoomTween) {\n+ this.zoomTween.stop();\n+ this.zoomTween = null;\n+ }\n+\n+ // map has been destroyed. dont do it again!\n+ OpenLayers.Event.stopObserving(window, 'unload', this.unloadDestroy);\n+ this.unloadDestroy = null;\n+\n+ if (this.updateSizeDestroy) {\n+ OpenLayers.Event.stopObserving(window, 'resize',\n+ this.updateSizeDestroy);\n+ }\n+\n+ this.paddingForPopups = null;\n+\n+ if (this.controls != null) {\n+ for (var i = this.controls.length - 1; i >= 0; --i) {\n+ this.controls[i].destroy();\n }\n- if (symbolizer.graphic === true) {\n- OpenLayers.Util.applyDefaults(symbolizer, {\n- pointRadius: this.defaultStyle.pointRadius,\n- externalGraphic: this.defaultStyle.externalGraphic,\n- graphicName: this.defaultStyle.graphicName,\n- graphicOpacity: this.defaultStyle.graphicOpacity,\n- graphicWidth: this.defaultStyle.graphicWidth,\n- graphicHeight: this.defaultStyle.graphicHeight,\n- graphicXOffset: this.defaultStyle.graphicXOffset,\n- graphicYOffset: this.defaultStyle.graphicYOffset\n- });\n+ this.controls = null;\n+ }\n+ if (this.layers != null) {\n+ for (var i = this.layers.length - 1; i >= 0; --i) {\n+ //pass 'false' to destroy so that map wont try to set a new \n+ // baselayer after each baselayer is removed\n+ this.layers[i].destroy(false);\n }\n+ this.layers = null;\n+ }\n+ if (this.viewPortDiv && this.viewPortDiv.parentNode) {\n+ this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);\n }\n+ this.viewPortDiv = null;\n \n- // merge the style with the current style\n- return this.createLiterals(\n- OpenLayers.Util.extend(style, symbolizer), feature);\n+ if (this.tileManager) {\n+ this.tileManager.removeMap(this);\n+ this.tileManager = null;\n+ }\n+\n+ if (this.eventListeners) {\n+ this.events.un(this.eventListeners);\n+ this.eventListeners = null;\n+ }\n+ this.events.destroy();\n+ this.events = null;\n+\n+ this.options = null;\n },\n \n /**\n- * Method: createLiterals\n- * creates literals for all style properties that have an entry in\n- * .\n- * \n+ * APIMethod: setOptions\n+ * Change the map options\n+ *\n * Parameters:\n- * style - {Object} style to create literals for. Will be modified\n- * inline.\n- * feature - {Object}\n- * \n- * Returns:\n- * {Object} the modified style\n+ * options - {Object} Hashtable of options to tag to the map\n */\n- createLiterals: function(style, feature) {\n- var context = OpenLayers.Util.extend({}, feature.attributes || feature.data);\n- OpenLayers.Util.extend(context, this.context);\n-\n- for (var i in this.propertyStyles) {\n- style[i] = OpenLayers.Style.createLiteral(style[i], context, feature, i);\n- }\n- return style;\n+ setOptions: function(options) {\n+ var updatePxExtent = this.minPx &&\n+ options.restrictedExtent != this.restrictedExtent;\n+ OpenLayers.Util.extend(this, options);\n+ // force recalculation of minPx and maxPx\n+ updatePxExtent && this.moveTo(this.getCachedCenter(), this.zoom, {\n+ forceZoomChange: true\n+ });\n },\n \n /**\n- * Method: findPropertyStyles\n- * Looks into all rules for this style and the defaultStyle to collect\n- * all the style hash property names containing ${...} strings that have\n- * to be replaced using the createLiteral method before returning them.\n- * \n+ * APIMethod: getTileSize\n+ * Get the tile size for the map\n+ *\n * Returns:\n- * {Object} hash of property names that need createLiteral parsing. The\n- * name of the property is the key, and the value is true;\n+ * {}\n */\n- findPropertyStyles: function() {\n- var propertyStyles = {};\n-\n- // check the default style\n- var style = this.defaultStyle;\n- this.addPropertyStyles(propertyStyles, style);\n-\n- // walk through all rules to check for properties in their symbolizer\n- var rules = this.rules;\n- var symbolizer, value;\n- for (var i = 0, len = rules.length; i < len; i++) {\n- symbolizer = rules[i].symbolizer;\n- for (var key in symbolizer) {\n- value = symbolizer[key];\n- if (typeof value == \"object\") {\n- // symbolizer key is \"Point\", \"Line\" or \"Polygon\"\n- this.addPropertyStyles(propertyStyles, value);\n- } else {\n- // symbolizer is a hash of style properties\n- this.addPropertyStyles(propertyStyles, symbolizer);\n- break;\n- }\n- }\n- }\n- return propertyStyles;\n+ getTileSize: function() {\n+ return this.tileSize;\n },\n \n+\n /**\n- * Method: addPropertyStyles\n- * \n+ * APIMethod: getBy\n+ * Get a list of objects given a property and a match item.\n+ *\n * Parameters:\n- * propertyStyles - {Object} hash to add new property styles to. Will be\n- * modified inline\n- * symbolizer - {Object} search this symbolizer for property styles\n- * \n+ * array - {String} A property on the map whose value is an array.\n+ * property - {String} A property on each item of the given array.\n+ * match - {String | Object} A string to match. Can also be a regular\n+ * expression literal or object. In addition, it can be any object\n+ * with a method named test. For reqular expressions or other, if\n+ * match.test(map[array][i][property]) evaluates to true, the item will\n+ * be included in the array returned. If no items are found, an empty\n+ * array is returned.\n+ *\n * Returns:\n- * {Object} propertyStyles hash\n+ * {Array} An array of items where the given property matches the given\n+ * criteria.\n */\n- addPropertyStyles: function(propertyStyles, symbolizer) {\n- var property;\n- for (var key in symbolizer) {\n- property = symbolizer[key];\n- if (typeof property == \"string\" &&\n- property.match(/\\$\\{\\w+\\}/)) {\n- propertyStyles[key] = true;\n- }\n- }\n- return propertyStyles;\n+ getBy: function(array, property, match) {\n+ var test = (typeof match.test == \"function\");\n+ var found = OpenLayers.Array.filter(this[array], function(item) {\n+ return item[property] == match || (test && match.test(item[property]));\n+ });\n+ return found;\n },\n \n /**\n- * APIMethod: addRules\n- * Adds rules to this style.\n- * \n+ * APIMethod: getLayersBy\n+ * Get a list of layers with properties matching the given criteria.\n+ *\n * Parameters:\n- * rules - {Array()}\n+ * property - {String} A layer property to be matched.\n+ * match - {String | Object} A string to match. Can also be a regular\n+ * expression literal or object. In addition, it can be any object\n+ * with a method named test. For reqular expressions or other, if\n+ * match.test(layer[property]) evaluates to true, the layer will be\n+ * included in the array returned. If no layers are found, an empty\n+ * array is returned.\n+ *\n+ * Returns:\n+ * {Array()} A list of layers matching the given criteria.\n+ * An empty array is returned if no matches are found.\n */\n- addRules: function(rules) {\n- Array.prototype.push.apply(this.rules, rules);\n- this.propertyStyles = this.findPropertyStyles();\n+ getLayersBy: function(property, match) {\n+ return this.getBy(\"layers\", property, match);\n },\n \n /**\n- * APIMethod: setDefaultStyle\n- * Sets the default style for this style object.\n- * \n+ * APIMethod: getLayersByName\n+ * Get a list of layers with names matching the given name.\n+ *\n * Parameters:\n- * style - {Object} Hash of style properties\n+ * match - {String | Object} A layer name. The name can also be a regular\n+ * expression literal or object. In addition, it can be any object\n+ * with a method named test. For reqular expressions or other, if\n+ * name.test(layer.name) evaluates to true, the layer will be included\n+ * in the list of layers returned. If no layers are found, an empty\n+ * array is returned.\n+ *\n+ * Returns:\n+ * {Array()} A list of layers matching the given name.\n+ * An empty array is returned if no matches are found.\n */\n- setDefaultStyle: function(style) {\n- this.defaultStyle = style;\n- this.propertyStyles = this.findPropertyStyles();\n+ getLayersByName: function(match) {\n+ return this.getLayersBy(\"name\", match);\n },\n \n /**\n- * Method: getSymbolizerPrefix\n- * Returns the correct symbolizer prefix according to the\n- * geometry type of the passed geometry\n- * \n+ * APIMethod: getLayersByClass\n+ * Get a list of layers of a given class (CLASS_NAME).\n+ *\n * Parameters:\n- * geometry - {}\n- * \n+ * match - {String | Object} A layer class name. The match can also be a\n+ * regular expression literal or object. In addition, it can be any\n+ * object with a method named test. For reqular expressions or other,\n+ * if type.test(layer.CLASS_NAME) evaluates to true, the layer will\n+ * be included in the list of layers returned. If no layers are\n+ * found, an empty array is returned.\n+ *\n * Returns:\n- * {String} key of the according symbolizer\n+ * {Array()} A list of layers matching the given class.\n+ * An empty array is returned if no matches are found.\n */\n- getSymbolizerPrefix: function(geometry) {\n- var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES;\n- for (var i = 0, len = prefixes.length; i < len; i++) {\n- if (geometry.CLASS_NAME.indexOf(prefixes[i]) != -1) {\n- return prefixes[i];\n- }\n- }\n+ getLayersByClass: function(match) {\n+ return this.getLayersBy(\"CLASS_NAME\", match);\n },\n \n /**\n- * APIMethod: clone\n- * Clones this style.\n- * \n+ * APIMethod: getControlsBy\n+ * Get a list of controls with properties matching the given criteria.\n+ *\n+ * Parameters:\n+ * property - {String} A control property to be matched.\n+ * match - {String | Object} A string to match. Can also be a regular\n+ * expression literal or object. In addition, it can be any object\n+ * with a method named test. For reqular expressions or other, if\n+ * match.test(layer[property]) evaluates to true, the layer will be\n+ * included in the array returned. If no layers are found, an empty\n+ * array is returned.\n+ *\n * Returns:\n- * {} Clone of this style.\n+ * {Array()} A list of controls matching the given\n+ * criteria. An empty array is returned if no matches are found.\n */\n- clone: function() {\n- var options = OpenLayers.Util.extend({}, this);\n- // clone rules\n- if (this.rules) {\n- options.rules = [];\n- for (var i = 0, len = this.rules.length; i < len; ++i) {\n- options.rules.push(this.rules[i].clone());\n- }\n- }\n- // clone context\n- options.context = this.context && OpenLayers.Util.extend({}, this.context);\n- //clone default style\n- var defaultStyle = OpenLayers.Util.extend({}, this.defaultStyle);\n- return new OpenLayers.Style(defaultStyle, options);\n+ getControlsBy: function(property, match) {\n+ return this.getBy(\"controls\", property, match);\n },\n \n- CLASS_NAME: \"OpenLayers.Style\"\n-});\n-\n-\n-/**\n- * Function: createLiteral\n- * converts a style value holding a combination of PropertyName and Literal\n- * into a Literal, taking the property values from the passed features.\n- * \n- * Parameters:\n- * value - {String} value to parse. If this string contains a construct like\n- * \"foo ${bar}\", then \"foo \" will be taken as literal, and \"${bar}\"\n- * will be replaced by the value of the \"bar\" attribute of the passed\n- * feature.\n- * context - {Object} context to take attribute values from\n- * feature - {} optional feature to pass to\n- * for evaluating functions in the\n- * context.\n- * property - {String} optional, name of the property for which the literal is\n- * being created for evaluating functions in the context.\n- * \n- * Returns:\n- * {String} the parsed value. In the example of the value parameter above, the\n- * result would be \"foo valueOfBar\", assuming that the passed feature has an\n- * attribute named \"bar\" with the value \"valueOfBar\".\n- */\n-OpenLayers.Style.createLiteral = function(value, context, feature, property) {\n- if (typeof value == \"string\" && value.indexOf(\"${\") != -1) {\n- value = OpenLayers.String.format(value, context, [feature, property]);\n- value = (isNaN(value) || !value) ? value : parseFloat(value);\n- }\n- return value;\n-};\n-\n-/**\n- * Constant: OpenLayers.Style.SYMBOLIZER_PREFIXES\n- * {Array} prefixes of the sld symbolizers. These are the\n- * same as the main geometry types\n- */\n-OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text',\n- 'Raster'\n-];\n-/* ======================================================================\n- OpenLayers/StyleMap.js\n- ====================================================================== */\n-\n-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for\n- * full list of contributors). Published under the 2-clause BSD license.\n- * See license.txt in the OpenLayers distribution or repository for the\n- * full text of the license. */\n-\n-/**\n- * @requires OpenLayers/BaseTypes/Class.js\n- * @requires OpenLayers/Style.js\n- * @requires OpenLayers/Feature/Vector.js\n- */\n-\n-/**\n- * Class: OpenLayers.StyleMap\n- */\n-OpenLayers.StyleMap = OpenLayers.Class({\n-\n /**\n- * Property: styles\n- * {Object} Hash of {}, keyed by names of well known\n- * rendering intents (e.g. \"default\", \"temporary\", \"select\", \"delete\").\n+ * APIMethod: getControlsByClass\n+ * Get a list of controls of a given class (CLASS_NAME).\n+ *\n+ * Parameters:\n+ * match - {String | Object} A control class name. The match can also be a\n+ * regular expression literal or object. In addition, it can be any\n+ * object with a method named test. For reqular expressions or other,\n+ * if type.test(control.CLASS_NAME) evaluates to true, the control will\n+ * be included in the list of controls returned. If no controls are\n+ * found, an empty array is returned.\n+ *\n+ * Returns:\n+ * {Array()} A list of controls matching the given class.\n+ * An empty array is returned if no matches are found.\n */\n- styles: null,\n+ getControlsByClass: function(match) {\n+ return this.getControlsBy(\"CLASS_NAME\", match);\n+ },\n+\n+ /********************************************************/\n+ /* */\n+ /* Layer Functions */\n+ /* */\n+ /* The following functions deal with adding and */\n+ /* removing Layers to and from the Map */\n+ /* */\n+ /********************************************************/\n \n /**\n- * Property: extendDefault\n- * {Boolean} if true, every render intent will extend the symbolizers\n- * specified for the \"default\" intent at rendering time. Otherwise, every\n- * rendering intent will be treated as a completely independent style.\n+ * APIMethod: getLayer\n+ * Get a layer based on its id\n+ *\n+ * Parameters:\n+ * id - {String} A layer id\n+ *\n+ * Returns:\n+ * {} The Layer with the corresponding id from the map's \n+ * layer collection, or null if not found.\n */\n- extendDefault: true,\n+ getLayer: function(id) {\n+ var foundLayer = null;\n+ for (var i = 0, len = this.layers.length; i < len; i++) {\n+ var layer = this.layers[i];\n+ if (layer.id == id) {\n+ foundLayer = layer;\n+ break;\n+ }\n+ }\n+ return foundLayer;\n+ },\n \n /**\n- * Constructor: OpenLayers.StyleMap\n+ * Method: setLayerZIndex\n * \n * Parameters:\n- * style - {Object} Optional. Either a style hash, or a style object, or\n- * a hash of style objects (style hashes) keyed by rendering\n- * intent. If just one style hash or style object is passed,\n- * this will be used for all known render intents (default,\n- * select, temporary)\n- * options - {Object} optional hash of additional options for this\n- * instance\n+ * layer - {} \n+ * zIdx - {int} \n */\n- initialize: function(style, options) {\n- this.styles = {\n- \"default\": new OpenLayers.Style(\n- OpenLayers.Feature.Vector.style[\"default\"]),\n- \"select\": new OpenLayers.Style(\n- OpenLayers.Feature.Vector.style[\"select\"]),\n- \"temporary\": new OpenLayers.Style(\n- OpenLayers.Feature.Vector.style[\"temporary\"]),\n- \"delete\": new OpenLayers.Style(\n- OpenLayers.Feature.Vector.style[\"delete\"])\n- };\n-\n- // take whatever the user passed as style parameter and convert it\n- // into parts of stylemap.\n- if (style instanceof OpenLayers.Style) {\n- // user passed a style object\n- this.styles[\"default\"] = style;\n- this.styles[\"select\"] = style;\n- this.styles[\"temporary\"] = style;\n- this.styles[\"delete\"] = style;\n- } else if (typeof style == \"object\") {\n- for (var key in style) {\n- if (style[key] instanceof OpenLayers.Style) {\n- // user passed a hash of style objects\n- this.styles[key] = style[key];\n- } else if (typeof style[key] == \"object\") {\n- // user passsed a hash of style hashes\n- this.styles[key] = new OpenLayers.Style(style[key]);\n- } else {\n- // user passed a style hash (i.e. symbolizer)\n- this.styles[\"default\"] = new OpenLayers.Style(style);\n- this.styles[\"select\"] = new OpenLayers.Style(style);\n- this.styles[\"temporary\"] = new OpenLayers.Style(style);\n- this.styles[\"delete\"] = new OpenLayers.Style(style);\n- break;\n- }\n- }\n- }\n- OpenLayers.Util.extend(this, options);\n+ setLayerZIndex: function(layer, zIdx) {\n+ layer.setZIndex(\n+ this.Z_INDEX_BASE[layer.isBaseLayer ? 'BaseLayer' : 'Overlay'] +\n+ zIdx * 5);\n },\n \n /**\n- * Method: destroy\n+ * Method: resetLayersZIndex\n+ * Reset each layer's z-index based on layer's array index\n */\n- destroy: function() {\n- for (var key in this.styles) {\n- this.styles[key].destroy();\n+ resetLayersZIndex: function() {\n+ for (var i = 0, len = this.layers.length; i < len; i++) {\n+ var layer = this.layers[i];\n+ this.setLayerZIndex(layer, i);\n }\n- this.styles = null;\n },\n \n /**\n- * Method: createSymbolizer\n- * Creates the symbolizer for a feature for a render intent.\n- * \n+ * APIMethod: addLayer\n+ *\n * Parameters:\n- * feature - {} The feature to evaluate the rules\n- * of the intended style against.\n- * intent - {String} The intent determines the symbolizer that will be\n- * used to draw the feature. Well known intents are \"default\"\n- * (for just drawing the features), \"select\" (for selected\n- * features) and \"temporary\" (for drawing features).\n- * \n+ * layer - {} \n+ *\n * Returns:\n- * {Object} symbolizer hash\n+ * {Boolean} True if the layer has been added to the map.\n */\n- createSymbolizer: function(feature, intent) {\n- if (!feature) {\n- feature = new OpenLayers.Feature.Vector();\n+ addLayer: function(layer) {\n+ for (var i = 0, len = this.layers.length; i < len; i++) {\n+ if (this.layers[i] == layer) {\n+ return false;\n+ }\n }\n- if (!this.styles[intent]) {\n- intent = \"default\";\n+ if (this.events.triggerEvent(\"preaddlayer\", {\n+ layer: layer\n+ }) === false) {\n+ return false;\n }\n- feature.renderIntent = intent;\n- var defaultSymbolizer = {};\n- if (this.extendDefault && intent != \"default\") {\n- defaultSymbolizer = this.styles[\"default\"].createSymbolizer(feature);\n+ if (this.allOverlays) {\n+ layer.isBaseLayer = false;\n }\n- return OpenLayers.Util.extend(defaultSymbolizer,\n- this.styles[intent].createSymbolizer(feature));\n+\n+ layer.div.className = \"olLayerDiv\";\n+ layer.div.style.overflow = \"\";\n+ this.setLayerZIndex(layer, this.layers.length);\n+\n+ if (layer.isFixed) {\n+ this.viewPortDiv.appendChild(layer.div);\n+ } else {\n+ this.layerContainerDiv.appendChild(layer.div);\n+ }\n+ this.layers.push(layer);\n+ layer.setMap(this);\n+\n+ if (layer.isBaseLayer || (this.allOverlays && !this.baseLayer)) {\n+ if (this.baseLayer == null) {\n+ // set the first baselaye we add as the baselayer\n+ this.setBaseLayer(layer);\n+ } else {\n+ layer.setVisibility(false);\n+ }\n+ } else {\n+ layer.redraw();\n+ }\n+\n+ this.events.triggerEvent(\"addlayer\", {\n+ layer: layer\n+ });\n+ layer.events.triggerEvent(\"added\", {\n+ map: this,\n+ layer: layer\n+ });\n+ layer.afterAdd();\n+\n+ return true;\n },\n \n /**\n- * Method: addUniqueValueRules\n- * Convenience method to create comparison rules for unique values of a\n- * property. The rules will be added to the style object for a specified\n- * rendering intent. This method is a shortcut for creating something like\n- * the \"unique value legends\" familiar from well known desktop GIS systems\n- * \n+ * APIMethod: addLayers \n+ *\n * Parameters:\n- * renderIntent - {String} rendering intent to add the rules to\n- * property - {String} values of feature attributes to create the\n- * rules for\n- * symbolizers - {Object} Hash of symbolizers, keyed by the desired\n- * property values \n- * context - {Object} An optional object with properties that\n- * symbolizers' property values should be evaluated\n- * against. If no context is specified, feature.attributes\n- * will be used\n+ * layers - {Array()} \n */\n- addUniqueValueRules: function(renderIntent, property, symbolizers, context) {\n- var rules = [];\n- for (var value in symbolizers) {\n- rules.push(new OpenLayers.Rule({\n- symbolizer: symbolizers[value],\n- context: context,\n- filter: new OpenLayers.Filter.Comparison({\n- type: OpenLayers.Filter.Comparison.EQUAL_TO,\n- property: property,\n- value: value\n- })\n- }));\n+ addLayers: function(layers) {\n+ for (var i = 0, len = layers.length; i < len; i++) {\n+ this.addLayer(layers[i]);\n }\n- this.styles[renderIntent].addRules(rules);\n },\n \n- CLASS_NAME: \"OpenLayers.StyleMap\"\n-});\n-/* ======================================================================\n- OpenLayers/Icon.js\n- ====================================================================== */\n+ /** \n+ * APIMethod: removeLayer\n+ * Removes a layer from the map by removing its visual element (the \n+ * layer.div property), then removing it from the map's internal list \n+ * of layers, setting the layer's map property to null. \n+ * \n+ * a \"removelayer\" event is triggered.\n+ * \n+ * very worthy of mention is that simply removing a layer from a map\n+ * will not cause the removal of any popups which may have been created\n+ * by the layer. this is due to the fact that it was decided at some\n+ * point that popups would not belong to layers. thus there is no way \n+ * for us to know here to which layer the popup belongs.\n+ * \n+ * A simple solution to this is simply to call destroy() on the layer.\n+ * the default OpenLayers.Layer class's destroy() function\n+ * automatically takes care to remove itself from whatever map it has\n+ * been attached to. \n+ * \n+ * The correct solution is for the layer itself to register an \n+ * event-handler on \"removelayer\" and when it is called, if it \n+ * recognizes itself as the layer being removed, then it cycles through\n+ * its own personal list of popups, removing them from the map.\n+ * \n+ * Parameters:\n+ * layer - {} \n+ * setNewBaseLayer - {Boolean} Default is true\n+ */\n+ removeLayer: function(layer, setNewBaseLayer) {\n+ if (this.events.triggerEvent(\"preremovelayer\", {\n+ layer: layer\n+ }) === false) {\n+ return;\n+ }\n+ if (setNewBaseLayer == null) {\n+ setNewBaseLayer = true;\n+ }\n \n-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for\n- * full list of contributors). Published under the 2-clause BSD license.\n- * See license.txt in the OpenLayers distribution or repository for the\n- * full text of the license. */\n+ if (layer.isFixed) {\n+ this.viewPortDiv.removeChild(layer.div);\n+ } else {\n+ this.layerContainerDiv.removeChild(layer.div);\n+ }\n+ OpenLayers.Util.removeItem(this.layers, layer);\n+ layer.removeMap(this);\n+ layer.map = null;\n \n-/**\n- * @requires OpenLayers/BaseTypes/Class.js\n- */\n+ // if we removed the base layer, need to set a new one\n+ if (this.baseLayer == layer) {\n+ this.baseLayer = null;\n+ if (setNewBaseLayer) {\n+ for (var i = 0, len = this.layers.length; i < len; i++) {\n+ var iLayer = this.layers[i];\n+ if (iLayer.isBaseLayer || this.allOverlays) {\n+ this.setBaseLayer(iLayer);\n+ break;\n+ }\n+ }\n+ }\n+ }\n \n-/**\n- * Class: OpenLayers.Icon\n- * \n- * The icon represents a graphical icon on the screen. Typically used in\n- * conjunction with a to represent markers on a screen.\n- *\n- * An icon has a url, size and position. It also contains an offset which \n- * allows the center point to be represented correctly. This can be\n- * provided either as a fixed offset or a function provided to calculate\n- * the desired offset. \n- * \n- */\n-OpenLayers.Icon = OpenLayers.Class({\n+ this.resetLayersZIndex();\n \n- /** \n- * Property: url \n- * {String} image url\n- */\n- url: null,\n+ this.events.triggerEvent(\"removelayer\", {\n+ layer: layer\n+ });\n+ layer.events.triggerEvent(\"removed\", {\n+ map: this,\n+ layer: layer\n+ });\n+ },\n \n- /** \n- * Property: size \n- * {|Object} An OpenLayers.Size or\n- * an object with a 'w' and 'h' properties.\n+ /**\n+ * APIMethod: getNumLayers\n+ * \n+ * Returns:\n+ * {Int} The number of layers attached to the map.\n */\n- size: null,\n+ getNumLayers: function() {\n+ return this.layers.length;\n+ },\n \n /** \n- * Property: offset \n- * {|Object} distance in pixels to offset the\n- * image when being rendered. An OpenLayers.Pixel or an object\n- * with a 'x' and 'y' properties.\n+ * APIMethod: getLayerIndex\n+ *\n+ * Parameters:\n+ * layer - {}\n+ *\n+ * Returns:\n+ * {Integer} The current (zero-based) index of the given layer in the map's\n+ * layer stack. Returns -1 if the layer isn't on the map.\n */\n- offset: null,\n+ getLayerIndex: function(layer) {\n+ return OpenLayers.Util.indexOf(this.layers, layer);\n+ },\n \n /** \n- * Property: calculateOffset \n- * {Function} Function to calculate the offset (based on the size)\n+ * APIMethod: setLayerIndex\n+ * Move the given layer to the specified (zero-based) index in the layer\n+ * list, changing its z-index in the map display. Use\n+ * map.getLayerIndex() to find out the current index of a layer. Note\n+ * that this cannot (or at least should not) be effectively used to\n+ * raise base layers above overlays.\n+ *\n+ * Parameters:\n+ * layer - {} \n+ * idx - {int} \n */\n- calculateOffset: null,\n+ setLayerIndex: function(layer, idx) {\n+ var base = this.getLayerIndex(layer);\n+ if (idx < 0) {\n+ idx = 0;\n+ } else if (idx > this.layers.length) {\n+ idx = this.layers.length;\n+ }\n+ if (base != idx) {\n+ this.layers.splice(base, 1);\n+ this.layers.splice(idx, 0, layer);\n+ for (var i = 0, len = this.layers.length; i < len; i++) {\n+ this.setLayerZIndex(this.layers[i], i);\n+ }\n+ this.events.triggerEvent(\"changelayer\", {\n+ layer: layer,\n+ property: \"order\"\n+ });\n+ if (this.allOverlays) {\n+ if (idx === 0) {\n+ this.setBaseLayer(layer);\n+ } else if (this.baseLayer !== this.layers[0]) {\n+ this.setBaseLayer(this.layers[0]);\n+ }\n+ }\n+ }\n+ },\n \n /** \n- * Property: imageDiv \n- * {DOMElement} \n+ * APIMethod: raiseLayer\n+ * Change the index of the given layer by delta. If delta is positive, \n+ * the layer is moved up the map's layer stack; if delta is negative,\n+ * the layer is moved down. Again, note that this cannot (or at least\n+ * should not) be effectively used to raise base layers above overlays.\n+ *\n+ * Paremeters:\n+ * layer - {} \n+ * delta - {int} \n */\n- imageDiv: null,\n+ raiseLayer: function(layer, delta) {\n+ var idx = this.getLayerIndex(layer) + delta;\n+ this.setLayerIndex(layer, idx);\n+ },\n \n /** \n- * Property: px \n- * {|Object} An OpenLayers.Pixel or an object\n- * with a 'x' and 'y' properties.\n+ * APIMethod: setBaseLayer\n+ * Allows user to specify one of the currently-loaded layers as the Map's\n+ * new base layer.\n+ * \n+ * Parameters:\n+ * newBaseLayer - {}\n */\n- px: null,\n+ setBaseLayer: function(newBaseLayer) {\n \n- /** \n- * Constructor: OpenLayers.Icon\n- * Creates an icon, which is an image tag in a div. \n- *\n- * url - {String} \n- * size - {|Object} An OpenLayers.Size or an\n- * object with a 'w' and 'h'\n- * properties.\n- * offset - {|Object} An OpenLayers.Pixel or an\n- * object with a 'x' and 'y'\n- * properties.\n- * calculateOffset - {Function} \n- */\n- initialize: function(url, size, offset, calculateOffset) {\n- this.url = url;\n- this.size = size || {\n- w: 20,\n- h: 20\n- };\n- this.offset = offset || {\n- x: -(this.size.w / 2),\n- y: -(this.size.h / 2)\n- };\n- this.calculateOffset = calculateOffset;\n+ if (newBaseLayer != this.baseLayer) {\n \n- var id = OpenLayers.Util.createUniqueID(\"OL_Icon_\");\n- this.imageDiv = OpenLayers.Util.createAlphaImageDiv(id);\n- },\n+ // ensure newBaseLayer is already loaded\n+ if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) {\n \n- /** \n- * Method: destroy\n- * Nullify references and remove event listeners to prevent circular \n- * references and memory leaks\n- */\n- destroy: function() {\n- // erase any drawn elements\n- this.erase();\n+ // preserve center and scale when changing base layers\n+ var center = this.getCachedCenter();\n+ var newResolution = OpenLayers.Util.getResolutionFromScale(\n+ this.getScale(), newBaseLayer.units\n+ );\n \n- OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);\n- this.imageDiv.innerHTML = \"\";\n- this.imageDiv = null;\n+ // make the old base layer invisible \n+ if (this.baseLayer != null && !this.allOverlays) {\n+ this.baseLayer.setVisibility(false);\n+ }\n+\n+ // set new baselayer\n+ this.baseLayer = newBaseLayer;\n+\n+ if (!this.allOverlays || this.baseLayer.visibility) {\n+ this.baseLayer.setVisibility(true);\n+ // Layer may previously have been visible but not in range.\n+ // In this case we need to redraw it to make it visible.\n+ if (this.baseLayer.inRange === false) {\n+ this.baseLayer.redraw();\n+ }\n+ }\n+\n+ // recenter the map\n+ if (center != null) {\n+ // new zoom level derived from old scale\n+ var newZoom = this.getZoomForResolution(\n+ newResolution || this.resolution, true\n+ );\n+ // zoom and force zoom change\n+ this.setCenter(center, newZoom, false, true);\n+ }\n+\n+ this.events.triggerEvent(\"changebaselayer\", {\n+ layer: this.baseLayer\n+ });\n+ }\n+ }\n },\n \n- /** \n- * Method: clone\n+\n+ /********************************************************/\n+ /* */\n+ /* Control Functions */\n+ /* */\n+ /* The following functions deal with adding and */\n+ /* removing Controls to and from the Map */\n+ /* */\n+ /********************************************************/\n+\n+ /**\n+ * APIMethod: addControl\n+ * Add the passed over control to the map. Optionally \n+ * position the control at the given pixel.\n * \n- * Returns:\n- * {} A fresh copy of the icon.\n+ * Parameters:\n+ * control - {}\n+ * px - {}\n */\n- clone: function() {\n- return new OpenLayers.Icon(this.url,\n- this.size,\n- this.offset,\n- this.calculateOffset);\n+ addControl: function(control, px) {\n+ this.controls.push(control);\n+ this.addControlToMap(control, px);\n },\n \n /**\n- * Method: setSize\n- * \n+ * APIMethod: addControls\n+ * Add all of the passed over controls to the map. \n+ * You can pass over an optional second array\n+ * with pixel-objects to position the controls.\n+ * The indices of the two arrays should match and\n+ * you can add null as pixel for those controls \n+ * you want to be autopositioned. \n+ * \n * Parameters:\n- * size - {|Object} An OpenLayers.Size or\n- * an object with a 'w' and 'h' properties.\n+ * controls - {Array()}\n+ * pixels - {Array()}\n */\n- setSize: function(size) {\n- if (size != null) {\n- this.size = size;\n+ addControls: function(controls, pixels) {\n+ var pxs = (arguments.length === 1) ? [] : pixels;\n+ for (var i = 0, len = controls.length; i < len; i++) {\n+ var ctrl = controls[i];\n+ var px = (pxs[i]) ? pxs[i] : null;\n+ this.addControl(ctrl, px);\n }\n- this.draw();\n },\n \n /**\n- * Method: setUrl\n+ * Method: addControlToMap\n * \n * Parameters:\n- * url - {String} \n+ * \n+ * control - {}\n+ * px - {}\n */\n- setUrl: function(url) {\n- if (url != null) {\n- this.url = url;\n+ addControlToMap: function(control, px) {\n+ // If a control doesn't have a div at this point, it belongs in the\n+ // viewport.\n+ control.outsideViewport = (control.div != null);\n+\n+ // If the map has a displayProjection, and the control doesn't, set \n+ // the display projection.\n+ if (this.displayProjection && !control.displayProjection) {\n+ control.displayProjection = this.displayProjection;\n+ }\n+\n+ control.setMap(this);\n+ var div = control.draw(px);\n+ if (div) {\n+ if (!control.outsideViewport) {\n+ div.style.zIndex = this.Z_INDEX_BASE['Control'] +\n+ this.controls.length;\n+ this.viewPortDiv.appendChild(div);\n+ }\n+ }\n+ if (control.autoActivate) {\n+ control.activate();\n }\n- this.draw();\n },\n \n- /** \n- * Method: draw\n- * Move the div to the given pixel.\n+ /**\n+ * APIMethod: getControl\n * \n * Parameters:\n- * px - {|Object} An OpenLayers.Pixel or an\n- * object with a 'x' and 'y' properties.\n+ * id - {String} ID of the control to return.\n * \n * Returns:\n- * {DOMElement} A new DOM Image of this icon set at the location passed-in\n+ * {} The control from the map's list of controls \n+ * which has a matching 'id'. If none found, \n+ * returns null.\n */\n- draw: function(px) {\n- OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,\n- null,\n- null,\n- this.size,\n- this.url,\n- \"absolute\");\n- this.moveTo(px);\n- return this.imageDiv;\n+ getControl: function(id) {\n+ var returnControl = null;\n+ for (var i = 0, len = this.controls.length; i < len; i++) {\n+ var control = this.controls[i];\n+ if (control.id == id) {\n+ returnControl = control;\n+ break;\n+ }\n+ }\n+ return returnControl;\n },\n \n /** \n- * Method: erase\n- * Erase the underlying image element.\n+ * APIMethod: removeControl\n+ * Remove a control from the map. Removes the control both from the map \n+ * object's internal array of controls, as well as from the map's \n+ * viewPort (assuming the control was not added outsideViewport)\n+ * \n+ * Parameters:\n+ * control - {} The control to remove.\n */\n- erase: function() {\n- if (this.imageDiv != null && this.imageDiv.parentNode != null) {\n- OpenLayers.Element.remove(this.imageDiv);\n+ removeControl: function(control) {\n+ //make sure control is non-null and actually part of our map\n+ if ((control) && (control == this.getControl(control.id))) {\n+ if (control.div && (control.div.parentNode == this.viewPortDiv)) {\n+ this.viewPortDiv.removeChild(control.div);\n+ }\n+ OpenLayers.Util.removeItem(this.controls, control);\n }\n },\n \n+ /********************************************************/\n+ /* */\n+ /* Popup Functions */\n+ /* */\n+ /* The following functions deal with adding and */\n+ /* removing Popups to and from the Map */\n+ /* */\n+ /********************************************************/\n+\n /** \n- * Method: setOpacity\n- * Change the icon's opacity\n- *\n+ * APIMethod: addPopup\n+ * \n * Parameters:\n- * opacity - {float} \n+ * popup - {}\n+ * exclusive - {Boolean} If true, closes all other popups first\n */\n- setOpacity: function(opacity) {\n- OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null,\n- null, null, null, null, opacity);\n-\n- },\n+ addPopup: function(popup, exclusive) {\n \n- /**\n- * Method: moveTo\n- * move icon to passed in px.\n- *\n- * Parameters:\n- * px - {|Object} the pixel position to move to.\n- * An OpenLayers.Pixel or an object with a 'x' and 'y' properties.\n- */\n- moveTo: function(px) {\n- //if no px passed in, use stored location\n- if (px != null) {\n- this.px = px;\n+ if (exclusive) {\n+ //remove all other popups from screen\n+ for (var i = this.popups.length - 1; i >= 0; --i) {\n+ this.removePopup(this.popups[i]);\n+ }\n }\n \n- if (this.imageDiv != null) {\n- if (this.px == null) {\n- this.display(false);\n- } else {\n- if (this.calculateOffset) {\n- this.offset = this.calculateOffset(this.size);\n- }\n- OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, {\n- x: this.px.x + this.offset.x,\n- y: this.px.y + this.offset.y\n- });\n- }\n+ popup.map = this;\n+ this.popups.push(popup);\n+ var popupDiv = popup.draw();\n+ if (popupDiv) {\n+ popupDiv.style.zIndex = this.Z_INDEX_BASE['Popup'] +\n+ this.popups.length;\n+ this.layerContainerDiv.appendChild(popupDiv);\n }\n },\n \n /** \n- * Method: display\n- * Hide or show the icon\n- *\n+ * APIMethod: removePopup\n+ * \n * Parameters:\n- * display - {Boolean} \n+ * popup - {}\n */\n- display: function(display) {\n- this.imageDiv.style.display = (display) ? \"\" : \"none\";\n+ removePopup: function(popup) {\n+ OpenLayers.Util.removeItem(this.popups, popup);\n+ if (popup.div) {\n+ try {\n+ this.layerContainerDiv.removeChild(popup.div);\n+ } catch (e) {} // Popups sometimes apparently get disconnected\n+ // from the layerContainerDiv, and cause complaints.\n+ }\n+ popup.map = null;\n },\n \n+ /********************************************************/\n+ /* */\n+ /* Container Div Functions */\n+ /* */\n+ /* The following functions deal with the access to */\n+ /* and maintenance of the size of the container div */\n+ /* */\n+ /********************************************************/\n \n /**\n- * APIMethod: isDrawn\n+ * APIMethod: getSize\n * \n * Returns:\n- * {Boolean} Whether or not the icon is drawn.\n+ * {} An object that represents the \n+ * size, in pixels, of the div into which OpenLayers \n+ * has been loaded. \n+ * Note - A clone() of this locally cached variable is\n+ * returned, so as not to allow users to modify it.\n */\n- isDrawn: function() {\n- // nodeType 11 for ie, whose nodes *always* have a parentNode\n- // (of type document fragment)\n- var isDrawn = (this.imageDiv && this.imageDiv.parentNode &&\n- (this.imageDiv.parentNode.nodeType != 11));\n-\n- return isDrawn;\n+ getSize: function() {\n+ var size = null;\n+ if (this.size != null) {\n+ size = this.size.clone();\n+ }\n+ return size;\n },\n \n- CLASS_NAME: \"OpenLayers.Icon\"\n-});\n-/* ======================================================================\n- OpenLayers/Marker.js\n- ====================================================================== */\n-\n-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for\n- * full list of contributors). Published under the 2-clause BSD license.\n- * See license.txt in the OpenLayers distribution or repository for the\n- * full text of the license. */\n-\n-\n-/**\n- * @requires OpenLayers/BaseTypes/Class.js\n- * @requires OpenLayers/Events.js\n- * @requires OpenLayers/Icon.js\n- */\n-\n-/**\n- * Class: OpenLayers.Marker\n- * Instances of OpenLayers.Marker are a combination of a \n- * and an . \n- *\n- * Markers are generally added to a special layer called\n- * .\n- *\n- * Example:\n- * (code)\n- * var markers = new OpenLayers.Layer.Markers( \"Markers\" );\n- * map.addLayer(markers);\n- *\n- * var size = new OpenLayers.Size(21,25);\n- * var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);\n- * var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset);\n- * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon));\n- * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon.clone()));\n- *\n- * (end)\n- *\n- * Note that if you pass an icon into the Marker constructor, it will take\n- * that icon and use it. This means that you should not share icons between\n- * markers -- you use them once, but you should clone() for any additional\n- * markers using that same icon.\n- */\n-OpenLayers.Marker = OpenLayers.Class({\n-\n- /** \n- * Property: icon \n- * {} The icon used by this marker.\n+ /**\n+ * APIMethod: updateSize\n+ * This function should be called by any external code which dynamically\n+ * changes the size of the map div (because mozilla wont let us catch \n+ * the \"onresize\" for an element)\n */\n- icon: null,\n+ updateSize: function() {\n+ // the div might have moved on the page, also\n+ var newSize = this.getCurrentSize();\n+ if (newSize && !isNaN(newSize.h) && !isNaN(newSize.w)) {\n+ this.events.clearMouseCache();\n+ var oldSize = this.getSize();\n+ if (oldSize == null) {\n+ this.size = oldSize = newSize;\n+ }\n+ if (!newSize.equals(oldSize)) {\n \n- /** \n- * Property: lonlat \n- * {} location of object\n- */\n- lonlat: null,\n+ // store the new size\n+ this.size = newSize;\n \n- /** \n- * Property: events \n- * {} the event handler.\n- */\n- events: null,\n+ //notify layers of mapresize\n+ for (var i = 0, len = this.layers.length; i < len; i++) {\n+ this.layers[i].onMapResize();\n+ }\n \n- /** \n- * Property: map \n- * {} the map this marker is attached to\n- */\n- map: null,\n+ var center = this.getCachedCenter();\n \n- /** \n- * Constructor: OpenLayers.Marker\n- *\n- * Parameters:\n- * lonlat - {} the position of this marker\n- * icon - {} the icon for this marker\n- */\n- initialize: function(lonlat, icon) {\n- this.lonlat = lonlat;\n+ if (this.baseLayer != null && center != null) {\n+ var zoom = this.getZoom();\n+ this.zoom = null;\n+ this.setCenter(center, zoom);\n+ }\n \n- var newIcon = (icon) ? icon : OpenLayers.Marker.defaultIcon();\n- if (this.icon == null) {\n- this.icon = newIcon;\n- } else {\n- this.icon.url = newIcon.url;\n- this.icon.size = newIcon.size;\n- this.icon.offset = newIcon.offset;\n- this.icon.calculateOffset = newIcon.calculateOffset;\n+ }\n }\n- this.events = new OpenLayers.Events(this, this.icon.imageDiv);\n+ this.events.triggerEvent(\"updatesize\");\n },\n \n /**\n- * APIMethod: destroy\n- * Destroy the marker. You must first remove the marker from any \n- * layer which it has been added to, or you will get buggy behavior.\n- * (This can not be done within the marker since the marker does not\n- * know which layer it is attached to.)\n+ * Method: getCurrentSize\n+ * \n+ * Returns:\n+ * {} A new object with the dimensions \n+ * of the map div\n */\n- destroy: function() {\n- // erase any drawn features\n- this.erase();\n-\n- this.map = null;\n+ getCurrentSize: function() {\n \n- this.events.destroy();\n- this.events = null;\n+ var size = new OpenLayers.Size(this.div.clientWidth,\n+ this.div.clientHeight);\n \n- if (this.icon != null) {\n- this.icon.destroy();\n- this.icon = null;\n+ if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) {\n+ size.w = this.div.offsetWidth;\n+ size.h = this.div.offsetHeight;\n+ }\n+ if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) {\n+ size.w = parseInt(this.div.style.width);\n+ size.h = parseInt(this.div.style.height);\n }\n+ return size;\n },\n \n /** \n- * Method: draw\n- * Calls draw on the icon, and returns that output.\n+ * Method: calculateBounds\n * \n * Parameters:\n- * px - {}\n+ * center - {} Default is this.getCenter()\n+ * resolution - {float} Default is this.getResolution() \n * \n * Returns:\n- * {DOMElement} A new DOM Image with this marker's icon set at the \n- * location passed-in\n+ * {} A bounds based on resolution, center, and \n+ * current mapsize.\n */\n- draw: function(px) {\n- return this.icon.draw(px);\n- },\n+ calculateBounds: function(center, resolution) {\n \n- /** \n- * Method: erase\n- * Erases any drawn elements for this marker.\n- */\n- erase: function() {\n- if (this.icon != null) {\n- this.icon.erase();\n+ var extent = null;\n+\n+ if (center == null) {\n+ center = this.getCachedCenter();\n+ }\n+ if (resolution == null) {\n+ resolution = this.getResolution();\n }\n- },\n \n- /**\n- * Method: moveTo\n- * Move the marker to the new location.\n- *\n- * Parameters:\n- * px - {|Object} the pixel position to move to.\n- * An OpenLayers.Pixel or an object with a 'x' and 'y' properties.\n- */\n- moveTo: function(px) {\n- if ((px != null) && (this.icon != null)) {\n- this.icon.moveTo(px);\n+ if ((center != null) && (resolution != null)) {\n+ var halfWDeg = (this.size.w * resolution) / 2;\n+ var halfHDeg = (this.size.h * resolution) / 2;\n+\n+ extent = new OpenLayers.Bounds(center.lon - halfWDeg,\n+ center.lat - halfHDeg,\n+ center.lon + halfWDeg,\n+ center.lat + halfHDeg);\n }\n- this.lonlat = this.map.getLonLatFromLayerPx(px);\n+\n+ return extent;\n },\n \n+\n+ /********************************************************/\n+ /* */\n+ /* Zoom, Center, Pan Functions */\n+ /* */\n+ /* The following functions handle the validation, */\n+ /* getting and setting of the Zoom Level and Center */\n+ /* as well as the panning of the Map */\n+ /* */\n+ /********************************************************/\n /**\n- * APIMethod: isDrawn\n+ * APIMethod: getCenter\n * \n * Returns:\n- * {Boolean} Whether or not the marker is drawn.\n+ * {}\n */\n- isDrawn: function() {\n- var isDrawn = (this.icon && this.icon.isDrawn());\n- return isDrawn;\n+ getCenter: function() {\n+ var center = null;\n+ var cachedCenter = this.getCachedCenter();\n+ if (cachedCenter) {\n+ center = cachedCenter.clone();\n+ }\n+ return center;\n },\n \n /**\n- * Method: onScreen\n+ * Method: getCachedCenter\n *\n * Returns:\n- * {Boolean} Whether or not the marker is currently visible on screen.\n+ * {}\n */\n- onScreen: function() {\n-\n- var onScreen = false;\n- if (this.map) {\n- var screenBounds = this.map.getExtent();\n- onScreen = screenBounds.containsLonLat(this.lonlat);\n+ getCachedCenter: function() {\n+ if (!this.center && this.size) {\n+ this.center = this.getLonLatFromViewPortPx({\n+ x: this.size.w / 2,\n+ y: this.size.h / 2\n+ });\n }\n- return onScreen;\n+ return this.center;\n },\n \n /**\n- * Method: inflate\n- * Englarges the markers icon by the specified ratio.\n- *\n- * Parameters:\n- * inflate - {float} the ratio to enlarge the marker by (passing 2\n- * will double the size).\n- */\n- inflate: function(inflate) {\n- if (this.icon) {\n- this.icon.setSize({\n- w: this.icon.size.w * inflate,\n- h: this.icon.size.h * inflate\n- });\n- }\n- },\n-\n- /** \n- * Method: setOpacity\n- * Change the opacity of the marker by changin the opacity of \n- * its icon\n- * \n- * Parameters:\n- * opacity - {float} Specified as fraction (0.4, etc)\n- */\n- setOpacity: function(opacity) {\n- this.icon.setOpacity(opacity);\n- },\n-\n- /**\n- * Method: setUrl\n- * Change URL of the Icon Image.\n- * \n- * url - {String} \n- */\n- setUrl: function(url) {\n- this.icon.setUrl(url);\n- },\n-\n- /** \n- * Method: display\n- * Hide or show the icon\n- * \n- * display - {Boolean} \n- */\n- display: function(display) {\n- this.icon.display(display);\n- },\n-\n- CLASS_NAME: \"OpenLayers.Marker\"\n-});\n-\n-\n-/**\n- * Function: defaultIcon\n- * Creates a default .\n- * \n- * Returns:\n- * {} A default OpenLayers.Icon to use for a marker\n- */\n-OpenLayers.Marker.defaultIcon = function() {\n- return new OpenLayers.Icon(OpenLayers.Util.getImageLocation(\"marker.png\"), {\n- w: 21,\n- h: 25\n- }, {\n- x: -10.5,\n- y: -25\n- });\n-};\n-\n-\n-/* ======================================================================\n- OpenLayers/Request/XMLHttpRequest.js\n- ====================================================================== */\n-\n-// XMLHttpRequest.js Copyright (C) 2010 Sergey Ilinsky (http://www.ilinsky.com)\n-//\n-// Licensed under the Apache License, Version 2.0 (the \"License\");\n-// you may not use this file except in compliance with the License.\n-// You may obtain a copy of the License at\n-//\n-// http://www.apache.org/licenses/LICENSE-2.0\n-//\n-// Unless required by applicable law or agreed to in writing, software\n-// distributed under the License is distributed on an \"AS IS\" BASIS,\n-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n-// See the License for the specific language governing permissions and\n-// limitations under the License.\n-\n-/**\n- * @requires OpenLayers/Request.js\n- */\n-\n-(function() {\n-\n- // Save reference to earlier defined object implementation (if any)\n- var oXMLHttpRequest = window.XMLHttpRequest;\n-\n- // Define on browser type\n- var bGecko = !!window.controllers,\n- bIE = window.document.all && !window.opera,\n- bIE7 = bIE && window.navigator.userAgent.match(/MSIE 7.0/);\n-\n- // Enables \"XMLHttpRequest()\" call next to \"new XMLHttpReques()\"\n- function fXMLHttpRequest() {\n- this._object = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject(\"Microsoft.XMLHTTP\");\n- this._listeners = [];\n- };\n-\n- // Constructor\n- function cXMLHttpRequest() {\n- return new fXMLHttpRequest;\n- };\n- cXMLHttpRequest.prototype = fXMLHttpRequest.prototype;\n-\n- // BUGFIX: Firefox with Firebug installed would break pages if not executed\n- if (bGecko && oXMLHttpRequest.wrapped)\n- cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped;\n-\n- // Constants\n- cXMLHttpRequest.UNSENT = 0;\n- cXMLHttpRequest.OPENED = 1;\n- cXMLHttpRequest.HEADERS_RECEIVED = 2;\n- cXMLHttpRequest.LOADING = 3;\n- cXMLHttpRequest.DONE = 4;\n-\n- // Public Properties\n- cXMLHttpRequest.prototype.readyState = cXMLHttpRequest.UNSENT;\n- cXMLHttpRequest.prototype.responseText = '';\n- cXMLHttpRequest.prototype.responseXML = null;\n- cXMLHttpRequest.prototype.status = 0;\n- cXMLHttpRequest.prototype.statusText = '';\n-\n- // Priority proposal\n- cXMLHttpRequest.prototype.priority = \"NORMAL\";\n-\n- // Instance-level Events Handlers\n- cXMLHttpRequest.prototype.onreadystatechange = null;\n-\n- // Class-level Events Handlers\n- cXMLHttpRequest.onreadystatechange = null;\n- cXMLHttpRequest.onopen = null;\n- cXMLHttpRequest.onsend = null;\n- cXMLHttpRequest.onabort = null;\n-\n- // Public Methods\n- cXMLHttpRequest.prototype.open = function(sMethod, sUrl, bAsync, sUser, sPassword) {\n- // Delete headers, required when object is reused\n- delete this._headers;\n-\n- // When bAsync parameter value is omitted, use true as default\n- if (arguments.length < 3)\n- bAsync = true;\n-\n- // Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests\n- this._async = bAsync;\n-\n- // Set the onreadystatechange handler\n- var oRequest = this,\n- nState = this.readyState,\n- fOnUnload;\n-\n- // BUGFIX: IE - memory leak on page unload (inter-page leak)\n- if (bIE && bAsync) {\n- fOnUnload = function() {\n- if (nState != cXMLHttpRequest.DONE) {\n- fCleanTransport(oRequest);\n- // Safe to abort here since onreadystatechange handler removed\n- oRequest.abort();\n- }\n- };\n- window.attachEvent(\"onunload\", fOnUnload);\n- }\n-\n- // Add method sniffer\n- if (cXMLHttpRequest.onopen)\n- cXMLHttpRequest.onopen.apply(this, arguments);\n-\n- if (arguments.length > 4)\n- this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);\n- else\n- if (arguments.length > 3)\n- this._object.open(sMethod, sUrl, bAsync, sUser);\n- else\n- this._object.open(sMethod, sUrl, bAsync);\n-\n- this.readyState = cXMLHttpRequest.OPENED;\n- fReadyStateChange(this);\n-\n- this._object.onreadystatechange = function() {\n- if (bGecko && !bAsync)\n- return;\n-\n- // Synchronize state\n- oRequest.readyState = oRequest._object.readyState;\n-\n- //\n- fSynchronizeValues(oRequest);\n-\n- // BUGFIX: Firefox fires unnecessary DONE when aborting\n- if (oRequest._aborted) {\n- // Reset readyState to UNSENT\n- oRequest.readyState = cXMLHttpRequest.UNSENT;\n-\n- // Return now\n- return;\n- }\n-\n- if (oRequest.readyState == cXMLHttpRequest.DONE) {\n- // Free up queue\n- delete oRequest._data;\n- /* if (bAsync)\n- fQueue_remove(oRequest);*/\n- //\n- fCleanTransport(oRequest);\n- // Uncomment this block if you need a fix for IE cache\n- /*\n- // BUGFIX: IE - cache issue\n- if (!oRequest._object.getResponseHeader(\"Date\")) {\n- // Save object to cache\n- oRequest._cached = oRequest._object;\n-\n- // Instantiate a new transport object\n- cXMLHttpRequest.call(oRequest);\n-\n- // Re-send request\n- if (sUser) {\n- if (sPassword)\n- oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);\n- else\n- oRequest._object.open(sMethod, sUrl, bAsync, sUser);\n- }\n- else\n- oRequest._object.open(sMethod, sUrl, bAsync);\n- oRequest._object.setRequestHeader(\"If-Modified-Since\", oRequest._cached.getResponseHeader(\"Last-Modified\") || new window.Date(0));\n- // Copy headers set\n- if (oRequest._headers)\n- for (var sHeader in oRequest._headers)\n- if (typeof oRequest._headers[sHeader] == \"string\") // Some frameworks prototype objects with functions\n- oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]);\n-\n- oRequest._object.onreadystatechange = function() {\n- // Synchronize state\n- oRequest.readyState = oRequest._object.readyState;\n-\n- if (oRequest._aborted) {\n- //\n- oRequest.readyState = cXMLHttpRequest.UNSENT;\n-\n- // Return\n- return;\n- }\n-\n- if (oRequest.readyState == cXMLHttpRequest.DONE) {\n- // Clean Object\n- fCleanTransport(oRequest);\n-\n- // get cached request\n- if (oRequest.status == 304)\n- oRequest._object = oRequest._cached;\n-\n- //\n- delete oRequest._cached;\n-\n- //\n- fSynchronizeValues(oRequest);\n-\n- //\n- fReadyStateChange(oRequest);\n-\n- // BUGFIX: IE - memory leak in interrupted\n- if (bIE && bAsync)\n- window.detachEvent(\"onunload\", fOnUnload);\n- }\n- };\n- oRequest._object.send(null);\n-\n- // Return now - wait until re-sent request is finished\n- return;\n- };\n- */\n- // BUGFIX: IE - memory leak in interrupted\n- if (bIE && bAsync)\n- window.detachEvent(\"onunload\", fOnUnload);\n- }\n-\n- // BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice\n- if (nState != oRequest.readyState)\n- fReadyStateChange(oRequest);\n-\n- nState = oRequest.readyState;\n- }\n- };\n-\n- function fXMLHttpRequest_send(oRequest) {\n- oRequest._object.send(oRequest._data);\n-\n- // BUGFIX: Gecko - missing readystatechange calls in synchronous requests\n- if (bGecko && !oRequest._async) {\n- oRequest.readyState = cXMLHttpRequest.OPENED;\n-\n- // Synchronize state\n- fSynchronizeValues(oRequest);\n-\n- // Simulate missing states\n- while (oRequest.readyState < cXMLHttpRequest.DONE) {\n- oRequest.readyState++;\n- fReadyStateChange(oRequest);\n- // Check if we are aborted\n- if (oRequest._aborted)\n- return;\n- }\n- }\n- };\n- cXMLHttpRequest.prototype.send = function(vData) {\n- // Add method sniffer\n- if (cXMLHttpRequest.onsend)\n- cXMLHttpRequest.onsend.apply(this, arguments);\n-\n- if (!arguments.length)\n- vData = null;\n-\n- // BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required\n- // BUGFIX: IE - rewrites any custom mime-type to \"text/xml\" in case an XMLNode is sent\n- // BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard)\n- if (vData && vData.nodeType) {\n- vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml;\n- if (!this._headers[\"Content-Type\"])\n- this._object.setRequestHeader(\"Content-Type\", \"application/xml\");\n- }\n-\n- this._data = vData;\n- /*\n- // Add to queue\n- if (this._async)\n- fQueue_add(this);\n- else*/\n- fXMLHttpRequest_send(this);\n- };\n- cXMLHttpRequest.prototype.abort = function() {\n- // Add method sniffer\n- if (cXMLHttpRequest.onabort)\n- cXMLHttpRequest.onabort.apply(this, arguments);\n-\n- // BUGFIX: Gecko - unnecessary DONE when aborting\n- if (this.readyState > cXMLHttpRequest.UNSENT)\n- this._aborted = true;\n-\n- this._object.abort();\n-\n- // BUGFIX: IE - memory leak\n- fCleanTransport(this);\n-\n- this.readyState = cXMLHttpRequest.UNSENT;\n-\n- delete this._data;\n- /* if (this._async)\n- fQueue_remove(this);*/\n- };\n- cXMLHttpRequest.prototype.getAllResponseHeaders = function() {\n- return this._object.getAllResponseHeaders();\n- };\n- cXMLHttpRequest.prototype.getResponseHeader = function(sName) {\n- return this._object.getResponseHeader(sName);\n- };\n- cXMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) {\n- // BUGFIX: IE - cache issue\n- if (!this._headers)\n- this._headers = {};\n- this._headers[sName] = sValue;\n-\n- return this._object.setRequestHeader(sName, sValue);\n- };\n-\n- // EventTarget interface implementation\n- cXMLHttpRequest.prototype.addEventListener = function(sName, fHandler, bUseCapture) {\n- for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)\n- if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)\n- return;\n- // Add listener\n- this._listeners.push([sName, fHandler, bUseCapture]);\n- };\n-\n- cXMLHttpRequest.prototype.removeEventListener = function(sName, fHandler, bUseCapture) {\n- for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)\n- if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)\n- break;\n- // Remove listener\n- if (oListener)\n- this._listeners.splice(nIndex, 1);\n- };\n-\n- cXMLHttpRequest.prototype.dispatchEvent = function(oEvent) {\n- var oEventPseudo = {\n- 'type': oEvent.type,\n- 'target': this,\n- 'currentTarget': this,\n- 'eventPhase': 2,\n- 'bubbles': oEvent.bubbles,\n- 'cancelable': oEvent.cancelable,\n- 'timeStamp': oEvent.timeStamp,\n- 'stopPropagation': function() {}, // There is no flow\n- 'preventDefault': function() {}, // There is no default action\n- 'initEvent': function() {} // Original event object should be initialized\n- };\n-\n- // Execute onreadystatechange\n- if (oEventPseudo.type == \"readystatechange\" && this.onreadystatechange)\n- (this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]);\n-\n- // Execute listeners\n- for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)\n- if (oListener[0] == oEventPseudo.type && !oListener[2])\n- (oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]);\n- };\n-\n- //\n- cXMLHttpRequest.prototype.toString = function() {\n- return '[' + \"object\" + ' ' + \"XMLHttpRequest\" + ']';\n- };\n-\n- cXMLHttpRequest.toString = function() {\n- return '[' + \"XMLHttpRequest\" + ']';\n- };\n-\n- // Helper function\n- function fReadyStateChange(oRequest) {\n- // Sniffing code\n- if (cXMLHttpRequest.onreadystatechange)\n- cXMLHttpRequest.onreadystatechange.apply(oRequest);\n-\n- // Fake event\n- oRequest.dispatchEvent({\n- 'type': \"readystatechange\",\n- 'bubbles': false,\n- 'cancelable': false,\n- 'timeStamp': new Date + 0\n- });\n- };\n-\n- function fGetDocument(oRequest) {\n- var oDocument = oRequest.responseXML,\n- sResponse = oRequest.responseText;\n- // Try parsing responseText\n- if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader(\"Content-Type\").match(/[^\\/]+\\/[^\\+]+\\+xml/)) {\n- oDocument = new window.ActiveXObject(\"Microsoft.XMLDOM\");\n- oDocument.async = false;\n- oDocument.validateOnParse = false;\n- oDocument.loadXML(sResponse);\n- }\n- // Check if there is no error in document\n- if (oDocument)\n- if ((bIE && oDocument.parseError != 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == \"parsererror\"))\n- return null;\n- return oDocument;\n- };\n-\n- function fSynchronizeValues(oRequest) {\n- try {\n- oRequest.responseText = oRequest._object.responseText;\n- } catch (e) {}\n- try {\n- oRequest.responseXML = fGetDocument(oRequest._object);\n- } catch (e) {}\n- try {\n- oRequest.status = oRequest._object.status;\n- } catch (e) {}\n- try {\n- oRequest.statusText = oRequest._object.statusText;\n- } catch (e) {}\n- };\n-\n- function fCleanTransport(oRequest) {\n- // BUGFIX: IE - memory leak (on-page leak)\n- oRequest._object.onreadystatechange = new window.Function;\n- };\n- /*\n- // Queue manager\n- var oQueuePending = {\"CRITICAL\":[],\"HIGH\":[],\"NORMAL\":[],\"LOW\":[],\"LOWEST\":[]},\n- aQueueRunning = [];\n- function fQueue_add(oRequest) {\n- oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : \"NORMAL\"].push(oRequest);\n- //\n- setTimeout(fQueue_process);\n- };\n-\n- function fQueue_remove(oRequest) {\n- for (var nIndex = 0, bFound = false; nIndex < aQueueRunning.length; nIndex++)\n- if (bFound)\n- aQueueRunning[nIndex - 1] = aQueueRunning[nIndex];\n- else\n- if (aQueueRunning[nIndex] == oRequest)\n- bFound = true;\n- if (bFound)\n- aQueueRunning.length--;\n- //\n- setTimeout(fQueue_process);\n- };\n-\n- function fQueue_process() {\n- if (aQueueRunning.length < 6) {\n- for (var sPriority in oQueuePending) {\n- if (oQueuePending[sPriority].length) {\n- var oRequest = oQueuePending[sPriority][0];\n- oQueuePending[sPriority] = oQueuePending[sPriority].slice(1);\n- //\n- aQueueRunning.push(oRequest);\n- // Send request\n- fXMLHttpRequest_send(oRequest);\n- break;\n- }\n- }\n- }\n- };\n- */\n- // Internet Explorer 5.0 (missing apply)\n- if (!window.Function.prototype.apply) {\n- window.Function.prototype.apply = function(oRequest, oArguments) {\n- if (!oArguments)\n- oArguments = [];\n- oRequest.__func = this;\n- oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);\n- delete oRequest.__func;\n- };\n- };\n-\n- // Register new object with window\n- /**\n- * Class: OpenLayers.Request.XMLHttpRequest\n- * Standard-compliant (W3C) cross-browser implementation of the\n- * XMLHttpRequest object. From\n- * http://code.google.com/p/xmlhttprequest/.\n- */\n- if (!OpenLayers.Request) {\n- /**\n- * This allows for OpenLayers/Request.js to be included\n- * before or after this script.\n- */\n- OpenLayers.Request = {};\n- }\n- OpenLayers.Request.XMLHttpRequest = cXMLHttpRequest;\n-})();\n-/* ======================================================================\n- OpenLayers/Request.js\n- ====================================================================== */\n-\n-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for\n- * full list of contributors). Published under the 2-clause BSD license.\n- * See license.txt in the OpenLayers distribution or repository for the\n- * full text of the license. */\n-\n-/**\n- * @requires OpenLayers/Events.js\n- * @requires OpenLayers/Request/XMLHttpRequest.js\n- */\n-\n-/**\n- * TODO: deprecate me\n- * Use OpenLayers.Request.proxy instead.\n- */\n-OpenLayers.ProxyHost = \"\";\n-\n-/**\n- * Namespace: OpenLayers.Request\n- * The OpenLayers.Request namespace contains convenience methods for working\n- * with XMLHttpRequests. These methods work with a cross-browser\n- * W3C compliant class.\n- */\n-if (!OpenLayers.Request) {\n- /**\n- * This allows for OpenLayers/Request/XMLHttpRequest.js to be included\n- * before or after this script.\n- */\n- OpenLayers.Request = {};\n-}\n-OpenLayers.Util.extend(OpenLayers.Request, {\n-\n- /**\n- * Constant: DEFAULT_CONFIG\n- * {Object} Default configuration for all requests.\n- */\n- DEFAULT_CONFIG: {\n- method: \"GET\",\n- url: window.location.href,\n- async: true,\n- user: undefined,\n- password: undefined,\n- params: null,\n- proxy: OpenLayers.ProxyHost,\n- headers: {},\n- data: null,\n- callback: function() {},\n- success: null,\n- failure: null,\n- scope: null\n- },\n-\n- /**\n- * Constant: URL_SPLIT_REGEX\n- */\n- URL_SPLIT_REGEX: /([^:]*:)\\/\\/([^:]*:?[^@]*@)?([^:\\/\\?]*):?([^\\/\\?]*)/,\n-\n- /**\n- * APIProperty: events\n- * {} An events object that handles all \n- * events on the {} object.\n- *\n- * All event listeners will receive an event object with three properties:\n- * request - {} The request object.\n- * config - {Object} The config object sent to the specific request method.\n- * requestUrl - {String} The request url.\n- * \n- * Supported event types:\n- * complete - Triggered when we have a response from the request, if a\n- * listener returns false, no further response processing will take\n- * place.\n- * success - Triggered when the HTTP response has a success code (200-299).\n- * failure - Triggered when the HTTP response does not have a success code.\n- */\n- events: new OpenLayers.Events(this),\n-\n- /**\n- * Method: makeSameOrigin\n- * Using the specified proxy, returns a same origin url of the provided url.\n- *\n- * Parameters:\n- * url - {String} An arbitrary url\n- * proxy {String|Function} The proxy to use to make the provided url a\n- * same origin url.\n- *\n- * Returns\n- * {String} the same origin url. If no proxy is provided, the returned url\n- * will be the same as the provided url.\n- */\n- makeSameOrigin: function(url, proxy) {\n- var sameOrigin = url.indexOf(\"http\") !== 0;\n- var urlParts = !sameOrigin && url.match(this.URL_SPLIT_REGEX);\n- if (urlParts) {\n- var location = window.location;\n- sameOrigin =\n- urlParts[1] == location.protocol &&\n- urlParts[3] == location.hostname;\n- var uPort = urlParts[4],\n- lPort = location.port;\n- if (uPort != 80 && uPort != \"\" || lPort != \"80\" && lPort != \"\") {\n- sameOrigin = sameOrigin && uPort == lPort;\n- }\n- }\n- if (!sameOrigin) {\n- if (proxy) {\n- if (typeof proxy == \"function\") {\n- url = proxy(url);\n- } else {\n- url = proxy + encodeURIComponent(url);\n- }\n- }\n- }\n- return url;\n- },\n-\n- /**\n- * APIMethod: issue\n- * Create a new XMLHttpRequest object, open it, set any headers, bind\n- * a callback to done state, and send any data. It is recommended that\n- * you use one , , , , , or .\n- * This method is only documented to provide detail on the configuration\n- * options available to all request methods.\n- *\n- * Parameters:\n- * config - {Object} Object containing properties for configuring the\n- * request. Allowed configuration properties are described below.\n- * This object is modified and should not be reused.\n- *\n- * Allowed config properties:\n- * method - {String} One of GET, POST, PUT, DELETE, HEAD, or\n- * OPTIONS. Default is GET.\n- * url - {String} URL for the request.\n- * async - {Boolean} Open an asynchronous request. Default is true.\n- * user - {String} User for relevant authentication scheme. Set\n- * to null to clear current user.\n- * password - {String} Password for relevant authentication scheme.\n- * Set to null to clear current password.\n- * proxy - {String} Optional proxy. Defaults to\n- * .\n- * params - {Object} Any key:value pairs to be appended to the\n- * url as a query string. Assumes url doesn't already include a query\n- * string or hash. Typically, this is only appropriate for \n- * requests where the query string will be appended to the url.\n- * Parameter values that are arrays will be\n- * concatenated with a comma (note that this goes against form-encoding)\n- * as is done with .\n- * headers - {Object} Object with header:value pairs to be set on\n- * the request.\n- * data - {String | Document} Optional data to send with the request.\n- * Typically, this is only used with and requests.\n- * Make sure to provide the appropriate \"Content-Type\" header for your\n- * data. For and requests, the content type defaults to\n- * \"application-xml\". If your data is a different content type, or\n- * if you are using a different HTTP method, set the \"Content-Type\"\n- * header to match your data type.\n- * callback - {Function} Function to call when request is done.\n- * To determine if the request failed, check request.status (200\n- * indicates success).\n- * success - {Function} Optional function to call if request status is in\n- * the 200s. This will be called in addition to callback above and\n- * would typically only be used as an alternative.\n- * failure - {Function} Optional function to call if request status is not\n- * in the 200s. This will be called in addition to callback above and\n- * would typically only be used as an alternative.\n- * scope - {Object} If callback is a public method on some object,\n- * set the scope to that object.\n- *\n- * Returns:\n- * {XMLHttpRequest} Request object. To abort the request before a response\n- * is received, call abort() on the request object.\n- */\n- issue: function(config) {\n- // apply default config - proxy host may have changed\n- var defaultConfig = OpenLayers.Util.extend(\n- this.DEFAULT_CONFIG, {\n- proxy: OpenLayers.ProxyHost\n- }\n- );\n- config = config || {};\n- config.headers = config.headers || {};\n- config = OpenLayers.Util.applyDefaults(config, defaultConfig);\n- config.headers = OpenLayers.Util.applyDefaults(config.headers, defaultConfig.headers);\n- // Always set the \"X-Requested-With\" header to signal that this request\n- // was issued through the XHR-object. Since header keys are case \n- // insensitive and we want to allow overriding of the \"X-Requested-With\"\n- // header through the user we cannot use applyDefaults, but have to \n- // check manually whether we were called with a \"X-Requested-With\"\n- // header.\n- var customRequestedWithHeader = false,\n- headerKey;\n- for (headerKey in config.headers) {\n- if (config.headers.hasOwnProperty(headerKey)) {\n- if (headerKey.toLowerCase() === 'x-requested-with') {\n- customRequestedWithHeader = true;\n- }\n- }\n- }\n- if (customRequestedWithHeader === false) {\n- // we did not have a custom \"X-Requested-With\" header\n- config.headers['X-Requested-With'] = 'XMLHttpRequest';\n- }\n-\n- // create request, open, and set headers\n- var request = new OpenLayers.Request.XMLHttpRequest();\n- var url = OpenLayers.Util.urlAppend(config.url,\n- OpenLayers.Util.getParameterString(config.params || {}));\n- url = OpenLayers.Request.makeSameOrigin(url, config.proxy);\n- request.open(\n- config.method, url, config.async, config.user, config.password\n- );\n- for (var header in config.headers) {\n- request.setRequestHeader(header, config.headers[header]);\n- }\n-\n- var events = this.events;\n-\n- // we want to execute runCallbacks with \"this\" as the\n- // execution scope\n- var self = this;\n-\n- request.onreadystatechange = function() {\n- if (request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {\n- var proceed = events.triggerEvent(\n- \"complete\", {\n- request: request,\n- config: config,\n- requestUrl: url\n- }\n- );\n- if (proceed !== false) {\n- self.runCallbacks({\n- request: request,\n- config: config,\n- requestUrl: url\n- });\n- }\n- }\n- };\n-\n- // send request (optionally with data) and return\n- // call in a timeout for asynchronous requests so the return is\n- // available before readyState == 4 for cached docs\n- if (config.async === false) {\n- request.send(config.data);\n- } else {\n- window.setTimeout(function() {\n- if (request.readyState !== 0) { // W3C: 0-UNSENT\n- request.send(config.data);\n- }\n- }, 0);\n- }\n- return request;\n- },\n-\n- /**\n- * Method: runCallbacks\n- * Calls the complete, success and failure callbacks. Application\n- * can listen to the \"complete\" event, have the listener \n- * display a confirm window and always return false, and\n- * execute OpenLayers.Request.runCallbacks if the user\n- * hits \"yes\" in the confirm window.\n- *\n- * Parameters:\n- * options - {Object} Hash containing request, config and requestUrl keys\n- */\n- runCallbacks: function(options) {\n- var request = options.request;\n- var config = options.config;\n-\n- // bind callbacks to readyState 4 (done)\n- var complete = (config.scope) ?\n- OpenLayers.Function.bind(config.callback, config.scope) :\n- config.callback;\n-\n- // optional success callback\n- var success;\n- if (config.success) {\n- success = (config.scope) ?\n- OpenLayers.Function.bind(config.success, config.scope) :\n- config.success;\n- }\n-\n- // optional failure callback\n- var failure;\n- if (config.failure) {\n- failure = (config.scope) ?\n- OpenLayers.Function.bind(config.failure, config.scope) :\n- config.failure;\n- }\n-\n- if (OpenLayers.Util.createUrlObject(config.url).protocol == \"file:\" &&\n- request.responseText) {\n- request.status = 200;\n- }\n- complete(request);\n-\n- if (!request.status || (request.status >= 200 && request.status < 300)) {\n- this.events.triggerEvent(\"success\", options);\n- if (success) {\n- success(request);\n- }\n- }\n- if (request.status && (request.status < 200 || request.status >= 300)) {\n- this.events.triggerEvent(\"failure\", options);\n- if (failure) {\n- failure(request);\n- }\n- }\n- },\n-\n- /**\n- * APIMethod: GET\n- * Send an HTTP GET request. Additional configuration properties are\n- * documented in the method, with the method property set\n- * to GET.\n- *\n- * Parameters:\n- * config - {Object} Object with properties for configuring the request.\n- * See the method for documentation of allowed properties.\n- * This object is modified and should not be reused.\n- * \n- * Returns:\n- * {XMLHttpRequest} Request object.\n- */\n- GET: function(config) {\n- config = OpenLayers.Util.extend(config, {\n- method: \"GET\"\n- });\n- return OpenLayers.Request.issue(config);\n- },\n-\n- /**\n- * APIMethod: POST\n- * Send a POST request. Additional configuration properties are\n- * documented in the method, with the method property set\n- * to POST and \"Content-Type\" header set to \"application/xml\".\n- *\n- * Parameters:\n- * config - {Object} Object with properties for configuring the request.\n- * See the method for documentation of allowed properties. The\n- * default \"Content-Type\" header will be set to \"application-xml\" if\n- * none is provided. This object is modified and should not be reused.\n- * \n- * Returns:\n- * {XMLHttpRequest} Request object.\n- */\n- POST: function(config) {\n- config = OpenLayers.Util.extend(config, {\n- method: \"POST\"\n- });\n- // set content type to application/xml if it isn't already set\n- config.headers = config.headers ? config.headers : {};\n- if (!(\"CONTENT-TYPE\" in OpenLayers.Util.upperCaseObject(config.headers))) {\n- config.headers[\"Content-Type\"] = \"application/xml\";\n- }\n- return OpenLayers.Request.issue(config);\n- },\n-\n- /**\n- * APIMethod: PUT\n- * Send an HTTP PUT request. Additional configuration properties are\n- * documented in the method, with the method property set\n- * to PUT and \"Content-Type\" header set to \"application/xml\".\n- *\n- * Parameters:\n- * config - {Object} Object with properties for configuring the request.\n- * See the method for documentation of allowed properties. The\n- * default \"Content-Type\" header will be set to \"application-xml\" if\n- * none is provided. This object is modified and should not be reused.\n- * \n- * Returns:\n- * {XMLHttpRequest} Request object.\n- */\n- PUT: function(config) {\n- config = OpenLayers.Util.extend(config, {\n- method: \"PUT\"\n- });\n- // set content type to application/xml if it isn't already set\n- config.headers = config.headers ? config.headers : {};\n- if (!(\"CONTENT-TYPE\" in OpenLayers.Util.upperCaseObject(config.headers))) {\n- config.headers[\"Content-Type\"] = \"application/xml\";\n- }\n- return OpenLayers.Request.issue(config);\n- },\n-\n- /**\n- * APIMethod: DELETE\n- * Send an HTTP DELETE request. Additional configuration properties are\n- * documented in the method, with the method property set\n- * to DELETE.\n- *\n- * Parameters:\n- * config - {Object} Object with properties for configuring the request.\n- * See the method for documentation of allowed properties.\n- * This object is modified and should not be reused.\n- * \n- * Returns:\n- * {XMLHttpRequest} Request object.\n- */\n- DELETE: function(config) {\n- config = OpenLayers.Util.extend(config, {\n- method: \"DELETE\"\n- });\n- return OpenLayers.Request.issue(config);\n- },\n-\n- /**\n- * APIMethod: HEAD\n- * Send an HTTP HEAD request. Additional configuration properties are\n- * documented in the method, with the method property set\n- * to HEAD.\n- *\n- * Parameters:\n- * config - {Object} Object with properties for configuring the request.\n- * See the method for documentation of allowed properties.\n- * This object is modified and should not be reused.\n- * \n- * Returns:\n- * {XMLHttpRequest} Request object.\n- */\n- HEAD: function(config) {\n- config = OpenLayers.Util.extend(config, {\n- method: \"HEAD\"\n- });\n- return OpenLayers.Request.issue(config);\n- },\n-\n- /**\n- * APIMethod: OPTIONS\n- * Send an HTTP OPTIONS request. Additional configuration properties are\n- * documented in the method, with the method property set\n- * to OPTIONS.\n- *\n- * Parameters:\n- * config - {Object} Object with properties for configuring the request.\n- * See the method for documentation of allowed properties.\n- * This object is modified and should not be reused.\n- * \n- * Returns:\n- * {XMLHttpRequest} Request object.\n- */\n- OPTIONS: function(config) {\n- config = OpenLayers.Util.extend(config, {\n- method: \"OPTIONS\"\n- });\n- return OpenLayers.Request.issue(config);\n- }\n-\n-});\n-/* ======================================================================\n- OpenLayers/Format.js\n- ====================================================================== */\n-\n-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for\n- * full list of contributors). Published under the 2-clause BSD license.\n- * See license.txt in the OpenLayers distribution or repository for the\n- * full text of the license. */\n-\n-/**\n- * @requires OpenLayers/BaseTypes/Class.js\n- * @requires OpenLayers/Util.js\n- */\n-\n-/**\n- * Class: OpenLayers.Format\n- * Base class for format reading/writing a variety of formats. Subclasses\n- * of OpenLayers.Format are expected to have read and write methods.\n- */\n-OpenLayers.Format = OpenLayers.Class({\n-\n- /**\n- * Property: options\n- * {Object} A reference to options passed to the constructor.\n- */\n- options: null,\n-\n- /**\n- * APIProperty: externalProjection\n- * {} When passed a externalProjection and\n- * internalProjection, the format will reproject the geometries it\n- * reads or writes. The externalProjection is the projection used by\n- * the content which is passed into read or which comes out of write.\n- * In order to reproject, a projection transformation function for the\n- * specified projections must be available. This support may be \n- * provided via proj4js or via a custom transformation function. See\n- * {} for more information on\n- * custom transformations.\n- */\n- externalProjection: null,\n-\n- /**\n- * APIProperty: internalProjection\n- * {} When passed a externalProjection and\n- * internalProjection, the format will reproject the geometries it\n- * reads or writes. The internalProjection is the projection used by\n- * the geometries which are returned by read or which are passed into\n- * write. In order to reproject, a projection transformation function\n- * for the specified projections must be available. This support may be\n- * provided via proj4js or via a custom transformation function. See\n- * {} for more information on\n- * custom transformations.\n- */\n- internalProjection: null,\n-\n- /**\n- * APIProperty: data\n- * {Object} When is true, this is the parsed string sent to\n- * .\n- */\n- data: null,\n-\n- /**\n- * APIProperty: keepData\n- * {Object} Maintain a reference () to the most recently read data.\n- * Default is false.\n- */\n- keepData: false,\n-\n- /**\n- * Constructor: OpenLayers.Format\n- * Instances of this class are not useful. See one of the subclasses.\n- *\n- * Parameters:\n- * options - {Object} An optional object with properties to set on the\n- * format\n- *\n- * Valid options:\n- * keepData - {Boolean} If true, upon , the data property will be\n- * set to the parsed object (e.g. the json or xml object).\n- *\n- * Returns:\n- * An instance of OpenLayers.Format\n- */\n- initialize: function(options) {\n- OpenLayers.Util.extend(this, options);\n- this.options = options;\n- },\n-\n- /**\n- * APIMethod: destroy\n- * Clean up.\n- */\n- destroy: function() {},\n-\n- /**\n- * Method: read\n- * Read data from a string, and return an object whose type depends on the\n- * subclass. \n- * \n- * Parameters:\n- * data - {string} Data to read/parse.\n- *\n- * Returns:\n- * Depends on the subclass\n- */\n- read: function(data) {\n- throw new Error('Read not implemented.');\n- },\n-\n- /**\n- * Method: write\n- * Accept an object, and return a string. \n- *\n- * Parameters:\n- * object - {Object} Object to be serialized\n- *\n- * Returns:\n- * {String} A string representation of the object.\n- */\n- write: function(object) {\n- throw new Error('Write not implemented.');\n- },\n-\n- CLASS_NAME: \"OpenLayers.Format\"\n-});\n-/* ======================================================================\n- OpenLayers/Util/vendorPrefix.js\n- ====================================================================== */\n-\n-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for\n- * full list of contributors). Published under the 2-clause BSD license.\n- * See license.txt in the OpenLayers distribution or repository for the\n- * full text of the license. */\n-\n-/**\n- * @requires OpenLayers/SingleFile.js\n- */\n-\n-OpenLayers.Util = OpenLayers.Util || {};\n-/**\n- * Namespace: OpenLayers.Util.vendorPrefix\n- * A collection of utility functions to detect vendor prefixed features\n- */\n-OpenLayers.Util.vendorPrefix = (function() {\n- \"use strict\";\n-\n- var VENDOR_PREFIXES = [\"\", \"O\", \"ms\", \"Moz\", \"Webkit\"],\n- divStyle = document.createElement(\"div\").style,\n- cssCache = {},\n- jsCache = {};\n-\n-\n- /**\n- * Function: domToCss\n- * Converts a upper camel case DOM style property name to a CSS property\n- * i.e. transformOrigin -> transform-origin\n- * or WebkitTransformOrigin -> -webkit-transform-origin\n- *\n- * Parameters:\n- * prefixedDom - {String} The property to convert\n- *\n- * Returns:\n- * {String} The CSS property\n- */\n- function domToCss(prefixedDom) {\n- if (!prefixedDom) {\n- return null;\n- }\n- return prefixedDom.\n- replace(/([A-Z])/g, function(c) {\n- return \"-\" + c.toLowerCase();\n- }).\n- replace(/^ms-/, \"-ms-\");\n- }\n-\n- /**\n- * APIMethod: css\n- * Detect which property is used for a CSS property\n- *\n- * Parameters:\n- * property - {String} The standard (unprefixed) CSS property name\n- *\n- * Returns:\n- * {String} The standard CSS property, prefixed property or null if not\n- * supported\n- */\n- function css(property) {\n- if (cssCache[property] === undefined) {\n- var domProperty = property.\n- replace(/(-[\\s\\S])/g, function(c) {\n- return c.charAt(1).toUpperCase();\n- });\n- var prefixedDom = style(domProperty);\n- cssCache[property] = domToCss(prefixedDom);\n- }\n- return cssCache[property];\n- }\n-\n- /**\n- * APIMethod: js\n- * Detect which property is used for a JS property/method\n- *\n- * Parameters:\n- * obj - {Object} The object to test on\n- * property - {String} The standard (unprefixed) JS property name\n- *\n- * Returns:\n- * {String} The standard JS property, prefixed property or null if not\n- * supported\n- */\n- function js(obj, property) {\n- if (jsCache[property] === undefined) {\n- var tmpProp,\n- i = 0,\n- l = VENDOR_PREFIXES.length,\n- prefix,\n- isStyleObj = (typeof obj.cssText !== \"undefined\");\n-\n- jsCache[property] = null;\n- for (; i < l; i++) {\n- prefix = VENDOR_PREFIXES[i];\n- if (prefix) {\n- if (!isStyleObj) {\n- // js prefix should be lower-case, while style\n- // properties have upper case on first character\n- prefix = prefix.toLowerCase();\n- }\n- tmpProp = prefix + property.charAt(0).toUpperCase() + property.slice(1);\n- } else {\n- tmpProp = property;\n- }\n-\n- if (obj[tmpProp] !== undefined) {\n- jsCache[property] = tmpProp;\n- break;\n- }\n- }\n- }\n- return jsCache[property];\n- }\n-\n- /**\n- * APIMethod: style\n- * Detect which property is used for a DOM style property\n- *\n- * Parameters:\n- * property - {String} The standard (unprefixed) style property name\n- *\n- * Returns:\n- * {String} The standard style property, prefixed property or null if not\n- * supported\n- */\n- function style(property) {\n- return js(divStyle, property);\n- }\n-\n- return {\n- css: css,\n- js: js,\n- style: style,\n-\n- // used for testing\n- cssCache: cssCache,\n- jsCache: jsCache\n- };\n-}());\n-/* ======================================================================\n- OpenLayers/Animation.js\n- ====================================================================== */\n-\n-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for\n- * full list of contributors). Published under the 2-clause BSD license.\n- * See license.txt in the OpenLayers distribution or repository for the\n- * full text of the license. */\n-\n-/**\n- * @requires OpenLayers/SingleFile.js\n- * @requires OpenLayers/Util/vendorPrefix.js\n- */\n-\n-/**\n- * Namespace: OpenLayers.Animation\n- * A collection of utility functions for executing methods that repaint a \n- * portion of the browser window. These methods take advantage of the\n- * browser's scheduled repaints where requestAnimationFrame is available.\n- */\n-OpenLayers.Animation = (function(window) {\n-\n- /**\n- * Property: isNative\n- * {Boolean} true if a native requestAnimationFrame function is available\n- */\n- var requestAnimationFrame = OpenLayers.Util.vendorPrefix.js(window, \"requestAnimationFrame\");\n- var isNative = !!(requestAnimationFrame);\n-\n- /**\n- * Function: requestFrame\n- * Schedule a function to be called at the next available animation frame.\n- * Uses the native method where available. Where requestAnimationFrame is\n- * not available, setTimeout will be called with a 16ms delay.\n- *\n- * Parameters:\n- * callback - {Function} The function to be called at the next animation frame.\n- * element - {DOMElement} Optional element that visually bounds the animation.\n- */\n- var requestFrame = (function() {\n- var request = window[requestAnimationFrame] ||\n- function(callback, element) {\n- window.setTimeout(callback, 16);\n- };\n- // bind to window to avoid illegal invocation of native function\n- return function(callback, element) {\n- request.apply(window, [callback, element]);\n- };\n- })();\n-\n- // private variables for animation loops\n- var counter = 0;\n- var loops = {};\n-\n- /**\n- * Function: start\n- * Executes a method with in series for some \n- * duration.\n- *\n- * Parameters:\n- * callback - {Function} The function to be called at the next animation frame.\n- * duration - {Number} Optional duration for the loop. If not provided, the\n- * animation loop will execute indefinitely.\n- * element - {DOMElement} Optional element that visually bounds the animation.\n- *\n- * Returns:\n- * {Number} Identifier for the animation loop. Used to stop animations with\n- * .\n- */\n- function start(callback, duration, element) {\n- duration = duration > 0 ? duration : Number.POSITIVE_INFINITY;\n- var id = ++counter;\n- var start = +new Date;\n- loops[id] = function() {\n- if (loops[id] && +new Date - start <= duration) {\n- callback();\n- if (loops[id]) {\n- requestFrame(loops[id], element);\n- }\n- } else {\n- delete loops[id];\n- }\n- };\n- requestFrame(loops[id], element);\n- return id;\n- }\n-\n- /**\n- * Function: stop\n- * Terminates an animation loop started with .\n- *\n- * Parameters:\n- * id - {Number} Identifier returned from .\n- */\n- function stop(id) {\n- delete loops[id];\n- }\n-\n- return {\n- isNative: isNative,\n- requestFrame: requestFrame,\n- start: start,\n- stop: stop\n- };\n-\n-})(window);\n-/* ======================================================================\n- OpenLayers/Protocol.js\n- ====================================================================== */\n-\n-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for\n- * full list of contributors). Published under the 2-clause BSD license.\n- * See license.txt in the OpenLayers distribution or repository for the\n- * full text of the license. */\n-\n-/**\n- * @requires OpenLayers/BaseTypes/Class.js\n- */\n-\n-/**\n- * Class: OpenLayers.Protocol\n- * Abstract vector layer protocol class. Not to be instantiated directly. Use\n- * one of the protocol subclasses instead.\n- */\n-OpenLayers.Protocol = OpenLayers.Class({\n-\n- /**\n- * Property: format\n- * {} The format used by this protocol.\n- */\n- format: null,\n-\n- /**\n- * Property: options\n- * {Object} Any options sent to the constructor.\n- */\n- options: null,\n-\n- /**\n- * Property: autoDestroy\n- * {Boolean} The creator of the protocol can set autoDestroy to false\n- * to fully control when the protocol is destroyed. Defaults to\n- * true.\n- */\n- autoDestroy: true,\n-\n- /**\n- * Property: defaultFilter\n- * {} Optional default filter to read requests\n- */\n- defaultFilter: null,\n-\n- /**\n- * Constructor: OpenLayers.Protocol\n- * Abstract class for vector protocols. Create instances of a subclass.\n- *\n- * Parameters:\n- * options - {Object} Optional object whose properties will be set on the\n- * instance.\n- */\n- initialize: function(options) {\n- options = options || {};\n- OpenLayers.Util.extend(this, options);\n- this.options = options;\n- },\n-\n- /**\n- * Method: mergeWithDefaultFilter\n- * Merge filter passed to the read method with the default one\n- *\n- * Parameters:\n- * filter - {}\n- */\n- mergeWithDefaultFilter: function(filter) {\n- var merged;\n- if (filter && this.defaultFilter) {\n- merged = new OpenLayers.Filter.Logical({\n- type: OpenLayers.Filter.Logical.AND,\n- filters: [this.defaultFilter, filter]\n- });\n- } else {\n- merged = filter || this.defaultFilter || undefined;\n- }\n- return merged;\n- },\n-\n- /**\n- * APIMethod: destroy\n- * Clean up the protocol.\n- */\n- destroy: function() {\n- this.options = null;\n- this.format = null;\n- },\n-\n- /**\n- * APIMethod: read\n- * Construct a request for reading new features.\n- *\n- * Parameters:\n- * options - {Object} Optional object for configuring the request.\n- *\n- * Returns:\n- * {} An \n- * object, the same object will be passed to the callback function passed\n- * if one exists in the options object.\n- */\n- read: function(options) {\n- options = options || {};\n- options.filter = this.mergeWithDefaultFilter(options.filter);\n- },\n-\n-\n- /**\n- * APIMethod: create\n- * Construct a request for writing newly created features.\n- *\n- * Parameters:\n- * features - {Array({})} or\n- * {}\n- * options - {Object} Optional object for configuring the request.\n- *\n- * Returns:\n- * {} An \n- * object, the same object will be passed to the callback function passed\n- * if one exists in the options object.\n- */\n- create: function() {},\n-\n- /**\n- * APIMethod: update\n- * Construct a request updating modified features.\n- *\n- * Parameters:\n- * features - {Array({})} or\n- * {}\n- * options - {Object} Optional object for configuring the request.\n- *\n- * Returns:\n- * {} An \n- * object, the same object will be passed to the callback function passed\n- * if one exists in the options object.\n- */\n- update: function() {},\n-\n- /**\n- * APIMethod: delete\n- * Construct a request deleting a removed feature.\n- *\n- * Parameters:\n- * feature - {}\n- * options - {Object} Optional object for configuring the request.\n- *\n- * Returns:\n- * {} An \n- * object, the same object will be passed to the callback function passed\n- * if one exists in the options object.\n- */\n- \"delete\": function() {},\n-\n- /**\n- * APIMethod: commit\n- * Go over the features and for each take action\n- * based on the feature state. Possible actions are create,\n- * update and delete.\n- *\n- * Parameters:\n- * features - {Array({})}\n- * options - {Object} Object whose possible keys are \"create\", \"update\",\n- * \"delete\", \"callback\" and \"scope\", the values referenced by the\n- * first three are objects as passed to the \"create\", \"update\", and\n- * \"delete\" methods, the value referenced by the \"callback\" key is\n- * a function which is called when the commit operation is complete\n- * using the scope referenced by the \"scope\" key.\n- *\n- * Returns:\n- * {Array({})} An array of\n- * objects.\n- */\n- commit: function() {},\n-\n- /**\n- * Method: abort\n- * Abort an ongoing request.\n- *\n- * Parameters:\n- * response - {}\n- */\n- abort: function(response) {},\n-\n- /**\n- * Method: createCallback\n- * Returns a function that applies the given public method with resp and\n- * options arguments.\n- *\n- * Parameters:\n- * method - {Function} The method to be applied by the callback.\n- * response - {} The protocol response object.\n- * options - {Object} Options sent to the protocol method\n- */\n- createCallback: function(method, response, options) {\n- return OpenLayers.Function.bind(function() {\n- method.apply(this, [response, options]);\n- }, this);\n- },\n-\n- CLASS_NAME: \"OpenLayers.Protocol\"\n-});\n-\n-/**\n- * Class: OpenLayers.Protocol.Response\n- * Protocols return Response objects to their users.\n- */\n-OpenLayers.Protocol.Response = OpenLayers.Class({\n- /**\n- * Property: code\n- * {Number} - OpenLayers.Protocol.Response.SUCCESS or\n- * OpenLayers.Protocol.Response.FAILURE\n- */\n- code: null,\n-\n- /**\n- * Property: requestType\n- * {String} The type of request this response corresponds to. Either\n- * \"create\", \"read\", \"update\" or \"delete\".\n- */\n- requestType: null,\n-\n- /**\n- * Property: last\n- * {Boolean} - true if this is the last response expected in a commit,\n- * false otherwise, defaults to true.\n- */\n- last: true,\n-\n- /**\n- * Property: features\n- * {Array({})} or {}\n- * The features returned in the response by the server. Depending on the \n- * protocol's read payload, either features or data will be populated.\n- */\n- features: null,\n-\n- /**\n- * Property: data\n- * {Object}\n- * The data returned in the response by the server. Depending on the \n- * protocol's read payload, either features or data will be populated.\n- */\n- data: null,\n-\n- /**\n- * Property: reqFeatures\n- * {Array({})} or {}\n- * The features provided by the user and placed in the request by the\n- * protocol.\n- */\n- reqFeatures: null,\n-\n- /**\n- * Property: priv\n- */\n- priv: null,\n-\n- /**\n- * Property: error\n- * {Object} The error object in case a service exception was encountered.\n- */\n- error: null,\n-\n- /**\n- * Constructor: OpenLayers.Protocol.Response\n- *\n- * Parameters:\n- * options - {Object} Optional object whose properties will be set on the\n- * instance.\n- */\n- initialize: function(options) {\n- OpenLayers.Util.extend(this, options);\n- },\n-\n- /**\n- * Method: success\n- *\n- * Returns:\n- * {Boolean} - true on success, false otherwise\n- */\n- success: function() {\n- return this.code > 0;\n- },\n-\n- CLASS_NAME: \"OpenLayers.Protocol.Response\"\n-});\n-\n-OpenLayers.Protocol.Response.SUCCESS = 1;\n-OpenLayers.Protocol.Response.FAILURE = 0;\n-/* ======================================================================\n- OpenLayers/Tween.js\n- ====================================================================== */\n-\n-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for\n- * full list of contributors). Published under the 2-clause BSD license.\n- * See license.txt in the OpenLayers distribution or repository for the\n- * full text of the license. */\n-\n-/**\n- * @requires OpenLayers/BaseTypes/Class.js\n- * @requires OpenLayers/Animation.js\n- */\n-\n-/**\n- * Namespace: OpenLayers.Tween\n- */\n-OpenLayers.Tween = OpenLayers.Class({\n-\n- /**\n- * APIProperty: easing\n- * {(Function)} Easing equation used for the animation\n- * Defaultly set to OpenLayers.Easing.Expo.easeOut\n- */\n- easing: null,\n-\n- /**\n- * APIProperty: begin\n- * {Object} Values to start the animation with\n- */\n- begin: null,\n-\n- /**\n- * APIProperty: finish\n- * {Object} Values to finish the animation with\n- */\n- finish: null,\n-\n- /**\n- * APIProperty: duration\n- * {int} duration of the tween (number of steps)\n- */\n- duration: null,\n-\n- /**\n- * APIProperty: callbacks\n- * {Object} An object with start, eachStep and done properties whose values\n- * are functions to be call during the animation. They are passed the\n- * current computed value as argument.\n- */\n- callbacks: null,\n-\n- /**\n- * Property: time\n- * {int} Step counter\n- */\n- time: null,\n-\n- /**\n- * APIProperty: minFrameRate\n- * {Number} The minimum framerate for animations in frames per second. After\n- * each step, the time spent in the animation is compared to the calculated\n- * time at this frame rate. If the animation runs longer than the calculated\n- * time, the next step is skipped. Default is 30.\n- */\n- minFrameRate: null,\n-\n- /**\n- * Property: startTime\n- * {Number} The timestamp of the first execution step. Used for skipping\n- * frames\n- */\n- startTime: null,\n-\n- /**\n- * Property: animationId\n- * {int} Loop id returned by OpenLayers.Animation.start\n- */\n- animationId: null,\n-\n- /**\n- * Property: playing\n- * {Boolean} Tells if the easing is currently playing\n- */\n- playing: false,\n-\n- /** \n- * Constructor: OpenLayers.Tween\n- * Creates a Tween.\n- *\n- * Parameters:\n- * easing - {(Function)} easing function method to use\n- */\n- initialize: function(easing) {\n- this.easing = (easing) ? easing : OpenLayers.Easing.Expo.easeOut;\n- },\n-\n- /**\n- * APIMethod: start\n- * Plays the Tween, and calls the callback method on each step\n- * \n- * Parameters:\n- * begin - {Object} values to start the animation with\n- * finish - {Object} values to finish the animation with\n- * duration - {int} duration of the tween (number of steps)\n- * options - {Object} hash of options (callbacks (start, eachStep, done),\n- * minFrameRate)\n- */\n- start: function(begin, finish, duration, options) {\n- this.playing = true;\n- this.begin = begin;\n- this.finish = finish;\n- this.duration = duration;\n- this.callbacks = options.callbacks;\n- this.minFrameRate = options.minFrameRate || 30;\n- this.time = 0;\n- this.startTime = new Date().getTime();\n- OpenLayers.Animation.stop(this.animationId);\n- this.animationId = null;\n- if (this.callbacks && this.callbacks.start) {\n- this.callbacks.start.call(this, this.begin);\n- }\n- this.animationId = OpenLayers.Animation.start(\n- OpenLayers.Function.bind(this.play, this)\n- );\n- },\n-\n- /**\n- * APIMethod: stop\n- * Stops the Tween, and calls the done callback\n- * Doesn't do anything if animation is already finished\n- */\n- stop: function() {\n- if (!this.playing) {\n- return;\n- }\n-\n- if (this.callbacks && this.callbacks.done) {\n- this.callbacks.done.call(this, this.finish);\n- }\n- OpenLayers.Animation.stop(this.animationId);\n- this.animationId = null;\n- this.playing = false;\n- },\n-\n- /**\n- * Method: play\n- * Calls the appropriate easing method\n- */\n- play: function() {\n- var value = {};\n- for (var i in this.begin) {\n- var b = this.begin[i];\n- var f = this.finish[i];\n- if (b == null || f == null || isNaN(b) || isNaN(f)) {\n- throw new TypeError('invalid value for Tween');\n- }\n-\n- var c = f - b;\n- value[i] = this.easing.apply(this, [this.time, b, c, this.duration]);\n- }\n- this.time++;\n-\n- if (this.callbacks && this.callbacks.eachStep) {\n- // skip frames if frame rate drops below threshold\n- if ((new Date().getTime() - this.startTime) / this.time <= 1000 / this.minFrameRate) {\n- this.callbacks.eachStep.call(this, value);\n- }\n- }\n-\n- if (this.time > this.duration) {\n- this.stop();\n- }\n- },\n-\n- /**\n- * Create empty functions for all easing methods.\n- */\n- CLASS_NAME: \"OpenLayers.Tween\"\n-});\n-\n-/**\n- * Namespace: OpenLayers.Easing\n- * \n- * Credits:\n- * Easing Equations by Robert Penner,