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+ * style - {Object} Optional hash of style properties that will be\n+ * used as default style for this style object. This style\n+ * applies if no rules are specified. Symbolizers defined in\n+ * rules will extend this default style.\n+ * options - {Object} An optional object with properties to set on the\n+ * style.\n *\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+ * Valid options:\n+ * rules - {Array()} List of rules to be added to the\n+ * style.\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+ * Returns:\n+ * {}\n */\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+ initialize: function(style, options) {\n \n- // now override default options \n OpenLayers.Util.extend(this, options);\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- // initialize layers array\n- this.layers = [];\n-\n- this.id = OpenLayers.Util.createUniqueID(\"OpenLayers.Map_\");\n-\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-\n- OpenLayers.Element.addClass(this.div, 'olMap');\n-\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- this.events = new OpenLayers.Events(\n- this, this.viewPortDiv, null, this.fallThrough, {\n- includeXY: true\n- }\n- );\n-\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 (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- for (var i = 0, len = this.controls.length; i < len; i++) {\n- this.addControlToMap(this.controls[i]);\n+ this.rules = [];\n+ if (options && options.rules) {\n+ this.addRules(options.rules);\n }\n \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+ // 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 \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+ this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + \"_\");\n },\n \n /** \n- * APIMethod: getViewport\n- * Get the DOMElement representing the view port.\n- *\n- * Returns:\n- * {DOMElement}\n+ * APIMethod: destroy\n+ * nullify references to prevent circular references and memory leaks\n */\n- getViewport: function() {\n- return this.viewPortDiv;\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+ }\n+ this.rules = null;\n+ this.defaultStyle = null;\n },\n \n /**\n- * APIMethod: render\n- * Render the map to a specified container.\n+ * Method: createSymbolizer\n+ * creates a style by applying all feature-dependent rules to the base\n+ * style.\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- /**\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+ * feature - {} feature to evaluate rules for\n+ * \n+ * Returns:\n+ * {Object} symbolizer hash\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+ createSymbolizer: function(feature) {\n+ var style = this.defaultsPerSymbolizer ? {} : this.createLiterals(\n+ OpenLayers.Util.extend({}, this.defaultStyle), feature);\n \n- if (this.updateSizeDestroy) {\n- OpenLayers.Event.stopObserving(window, 'resize',\n- this.updateSizeDestroy);\n- }\n+ var rules = this.rules;\n \n- this.paddingForPopups = null;\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 \n- if (this.controls != null) {\n- for (var i = this.controls.length - 1; i >= 0; --i) {\n- this.controls[i].destroy();\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+ }\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+ // 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 }\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- if (this.tileManager) {\n- this.tileManager.removeMap(this);\n- this.tileManager = null;\n+ // don't display if there were rules but none applied\n+ if (rules.length > 0 && appliedRules == false) {\n+ style.display = \"none\";\n }\n \n- if (this.eventListeners) {\n- this.events.un(this.eventListeners);\n- this.eventListeners = null;\n+ if (style.label != null && typeof style.label !== \"string\") {\n+ style.label = String(style.label);\n }\n- this.events.destroy();\n- this.events = null;\n \n- this.options = null;\n+ return style;\n },\n \n /**\n- * APIMethod: setOptions\n- * Change the map options\n+ * Method: applySymbolizer\n *\n * Parameters:\n- * options - {Object} Hashtable of options to tag to the map\n- */\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- * APIMethod: getTileSize\n- * Get the tile size for the map\n+ * rule - {}\n+ * style - {Object}\n+ * feature - {}\n *\n * Returns:\n- * {}\n+ * {Object} A style with new symbolizer applied.\n */\n- getTileSize: function() {\n- return this.tileSize;\n- },\n+ applySymbolizer: function(rule, style, feature) {\n+ var symbolizerPrefix = feature.geometry ?\n+ this.getSymbolizerPrefix(feature.geometry) :\n+ OpenLayers.Style.SYMBOLIZER_PREFIXES[0];\n+\n+ var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer;\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+ 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+ }\n+ }\n \n+ // merge the style with the current style\n+ return this.createLiterals(\n+ OpenLayers.Util.extend(style, symbolizer), feature);\n+ },\n \n /**\n- * APIMethod: getBy\n- * Get a list of objects given a property and a match item.\n- *\n+ * Method: createLiterals\n+ * creates literals for all style properties that have an entry in\n+ * .\n+ * \n * Parameters:\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+ * style - {Object} style to create literals for. Will be modified\n+ * inline.\n+ * feature - {Object}\n+ * \n * Returns:\n- * {Array} An array of items where the given property matches the given\n- * criteria.\n+ * {Object} the modified style\n */\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+ 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 },\n \n /**\n- * APIMethod: getLayersBy\n- * Get a list of layers with properties matching the given criteria.\n- *\n- * Parameters:\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+ * 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 * Returns:\n- * {Array()} A list of layers matching the given criteria.\n- * An empty array is returned if no matches are found.\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- getLayersBy: function(property, match) {\n- return this.getBy(\"layers\", property, match);\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 },\n \n /**\n- * APIMethod: getLayersByName\n- * Get a list of layers with names matching the given name.\n- *\n+ * Method: addPropertyStyles\n+ * \n * Parameters:\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+ * 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 * Returns:\n- * {Array()} A list of layers matching the given name.\n- * An empty array is returned if no matches are found.\n+ * {Object} propertyStyles hash\n */\n- getLayersByName: function(match) {\n- return this.getLayersBy(\"name\", match);\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 },\n \n /**\n- * APIMethod: getLayersByClass\n- * Get a list of layers of a given class (CLASS_NAME).\n- *\n+ * APIMethod: addRules\n+ * Adds rules to this style.\n+ * \n * Parameters:\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- * {Array()} A list of layers matching the given class.\n- * An empty array is returned if no matches are found.\n+ * rules - {Array()}\n */\n- getLayersByClass: function(match) {\n- return this.getLayersBy(\"CLASS_NAME\", match);\n+ addRules: function(rules) {\n+ Array.prototype.push.apply(this.rules, rules);\n+ this.propertyStyles = this.findPropertyStyles();\n },\n \n /**\n- * APIMethod: getControlsBy\n- * Get a list of controls with properties matching the given criteria.\n- *\n+ * APIMethod: setDefaultStyle\n+ * Sets the default style for this style object.\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- * {Array()} A list of controls matching the given\n- * criteria. An empty array is returned if no matches are found.\n+ * style - {Object} Hash of style properties\n */\n- getControlsBy: function(property, match) {\n- return this.getBy(\"controls\", property, match);\n+ setDefaultStyle: function(style) {\n+ this.defaultStyle = style;\n+ this.propertyStyles = this.findPropertyStyles();\n },\n \n /**\n- * APIMethod: getControlsByClass\n- * Get a list of controls of a given class (CLASS_NAME).\n- *\n+ * Method: getSymbolizerPrefix\n+ * Returns the correct symbolizer prefix according to the\n+ * geometry type of the passed geometry\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+ * geometry - {}\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+ * {String} key of the according symbolizer\n */\n- getControlsByClass: function(match) {\n- return this.getControlsBy(\"CLASS_NAME\", match);\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 },\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- * APIMethod: getLayer\n- * Get a layer based on its id\n- *\n- * Parameters:\n- * id - {String} A layer id\n- *\n+ * APIMethod: clone\n+ * Clones this style.\n+ * \n * Returns:\n- * {} The Layer with the corresponding id from the map's \n- * layer collection, or null if not found.\n+ * {} Clone of this style.\n */\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+ 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- return foundLayer;\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 },\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- * Method: setLayerZIndex\n- * \n- * Parameters:\n- * layer - {} \n- * zIdx - {int} \n+ * Property: styles\n+ * {Object} Hash of {}, keyed by names of well known\n+ * rendering intents (e.g. \"default\", \"temporary\", \"select\", \"delete\").\n */\n- setLayerZIndex: function(layer, zIdx) {\n- layer.setZIndex(\n- this.Z_INDEX_BASE[layer.isBaseLayer ? 'BaseLayer' : 'Overlay'] +\n- zIdx * 5);\n- },\n+ styles: null,\n \n /**\n- * Method: resetLayersZIndex\n- * Reset each layer's z-index based on layer's array index\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 */\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- },\n+ extendDefault: true,\n \n /**\n- * APIMethod: addLayer\n- *\n+ * Constructor: OpenLayers.StyleMap\n+ * \n * Parameters:\n- * layer - {} \n- *\n- * Returns:\n- * {Boolean} True if the layer has been added to the map.\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 */\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.events.triggerEvent(\"preaddlayer\", {\n- layer: layer\n- }) === false) {\n- return false;\n- }\n- if (this.allOverlays) {\n- layer.isBaseLayer = false;\n- }\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+ 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- 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+ // 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- } 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+ OpenLayers.Util.extend(this, options);\n },\n \n /**\n- * APIMethod: addLayers \n- *\n- * Parameters:\n- * layers - {Array()} \n+ * Method: destroy\n */\n- addLayers: function(layers) {\n- for (var i = 0, len = layers.length; i < len; i++) {\n- this.addLayer(layers[i]);\n+ destroy: function() {\n+ for (var key in this.styles) {\n+ this.styles[key].destroy();\n }\n+ this.styles = null;\n },\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+ * Method: createSymbolizer\n+ * Creates the symbolizer for a feature for a render intent.\n * \n * Parameters:\n- * layer - {} \n- * setNewBaseLayer - {Boolean} Default is true\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+ * Returns:\n+ * {Object} symbolizer hash\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+ createSymbolizer: function(feature, intent) {\n+ if (!feature) {\n+ feature = new OpenLayers.Feature.Vector();\n }\n-\n- if (layer.isFixed) {\n- this.viewPortDiv.removeChild(layer.div);\n- } else {\n- this.layerContainerDiv.removeChild(layer.div);\n+ if (!this.styles[intent]) {\n+ intent = \"default\";\n }\n- OpenLayers.Util.removeItem(this.layers, layer);\n- layer.removeMap(this);\n- layer.map = null;\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+ feature.renderIntent = intent;\n+ var defaultSymbolizer = {};\n+ if (this.extendDefault && intent != \"default\") {\n+ defaultSymbolizer = this.styles[\"default\"].createSymbolizer(feature);\n }\n-\n- this.resetLayersZIndex();\n-\n- this.events.triggerEvent(\"removelayer\", {\n- layer: layer\n- });\n- layer.events.triggerEvent(\"removed\", {\n- map: this,\n- layer: layer\n- });\n+ return OpenLayers.Util.extend(defaultSymbolizer,\n+ this.styles[intent].createSymbolizer(feature));\n },\n \n /**\n- * APIMethod: getNumLayers\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- * Returns:\n- * {Int} The number of layers attached to the map.\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 */\n- getNumLayers: function() {\n- return this.layers.length;\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+ }\n+ this.styles[renderIntent].addRules(rules);\n },\n \n+ CLASS_NAME: \"OpenLayers.StyleMap\"\n+});\n+/* ======================================================================\n+ OpenLayers/Icon.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.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+\n /** \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+ * Property: url \n+ * {String} image url\n */\n- getLayerIndex: function(layer) {\n- return OpenLayers.Util.indexOf(this.layers, layer);\n- },\n+ url: null,\n \n /** \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+ * Property: size \n+ * {|Object} An OpenLayers.Size or\n+ * an object with a 'w' and 'h' properties.\n */\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+ size: null,\n \n /** \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+ * 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 */\n- raiseLayer: function(layer, delta) {\n- var idx = this.getLayerIndex(layer) + delta;\n- this.setLayerIndex(layer, idx);\n- },\n+ offset: null,\n \n /** \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+ * Property: calculateOffset \n+ * {Function} Function to calculate the offset (based on the size)\n */\n- setBaseLayer: function(newBaseLayer) {\n-\n- if (newBaseLayer != this.baseLayer) {\n-\n- // ensure newBaseLayer is already loaded\n- if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) {\n-\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- // make the old base layer invisible \n- if (this.baseLayer != null && !this.allOverlays) {\n- this.baseLayer.setVisibility(false);\n- }\n+ calculateOffset: null,\n \n- // set new baselayer\n- this.baseLayer = newBaseLayer;\n+ /** \n+ * Property: imageDiv \n+ * {DOMElement} \n+ */\n+ imageDiv: null,\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+ * Property: px \n+ * {|Object} An OpenLayers.Pixel or an object\n+ * with a 'x' and 'y' properties.\n+ */\n+ px: null,\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+ * 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 \n- this.events.triggerEvent(\"changebaselayer\", {\n- layer: this.baseLayer\n- });\n- }\n- }\n+ var id = OpenLayers.Util.createUniqueID(\"OL_Icon_\");\n+ this.imageDiv = OpenLayers.Util.createAlphaImageDiv(id);\n },\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 \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+ OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);\n+ this.imageDiv.innerHTML = \"\";\n+ this.imageDiv = null;\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+ * Method: clone\n * \n- * Parameters:\n- * control - {}\n- * px - {}\n+ * Returns:\n+ * {} A fresh copy of the icon.\n */\n- addControl: function(control, px) {\n- this.controls.push(control);\n- this.addControlToMap(control, px);\n+ clone: function() {\n+ return new OpenLayers.Icon(this.url,\n+ this.size,\n+ this.offset,\n+ this.calculateOffset);\n },\n \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+ * Method: setSize\n+ * \n * Parameters:\n- * controls - {Array()}\n- * pixels - {Array()}\n+ * size - {|Object} An OpenLayers.Size or\n+ * an object with a 'w' and 'h' properties.\n */\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+ setSize: function(size) {\n+ if (size != null) {\n+ this.size = size;\n }\n+ this.draw();\n },\n \n /**\n- * Method: addControlToMap\n+ * Method: setUrl\n * \n * Parameters:\n- * \n- * control - {}\n- * px - {}\n+ * url - {String} \n */\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+ setUrl: function(url) {\n+ if (url != null) {\n+ this.url = url;\n }\n+ this.draw();\n },\n \n- /**\n- * APIMethod: getControl\n+ /** \n+ * Method: draw\n+ * Move the div to the given pixel.\n * \n * Parameters:\n- * id - {String} ID of the control to return.\n+ * px - {|Object} An OpenLayers.Pixel or an\n+ * object with a 'x' and 'y' properties.\n * \n * Returns:\n- * {} The control from the map's list of controls \n- * which has a matching 'id'. If none found, \n- * returns null.\n+ * {DOMElement} A new DOM Image of this icon set at the location passed-in\n */\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+ 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 },\n \n /** \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+ * Method: erase\n+ * Erase the underlying image element.\n */\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+ erase: function() {\n+ if (this.imageDiv != null && this.imageDiv.parentNode != null) {\n+ OpenLayers.Element.remove(this.imageDiv);\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- * APIMethod: addPopup\n- * \n+ * Method: setOpacity\n+ * Change the icon's opacity\n+ *\n * Parameters:\n- * popup - {}\n- * exclusive - {Boolean} If true, closes all other popups first\n+ * opacity - {float} \n */\n- addPopup: function(popup, exclusive) {\n+ setOpacity: function(opacity) {\n+ OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null,\n+ null, null, null, null, opacity);\n \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+ /**\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 }\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+ 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 }\n },\n \n /** \n- * APIMethod: removePopup\n- * \n+ * Method: display\n+ * Hide or show the icon\n+ *\n * Parameters:\n- * popup - {}\n+ * display - {Boolean} \n */\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+ display: function(display) {\n+ this.imageDiv.style.display = (display) ? \"\" : \"none\";\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: getSize\n+ * APIMethod: isDrawn\n * \n * Returns:\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+ * {Boolean} Whether or not the icon is drawn.\n */\n- getSize: function() {\n- var size = null;\n- if (this.size != null) {\n- size = this.size.clone();\n- }\n- return size;\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 },\n \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+ 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- 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+ icon: null,\n \n- // store the new size\n- this.size = newSize;\n+ /** \n+ * Property: lonlat \n+ * {} location of object\n+ */\n+ lonlat: null,\n \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+ * Property: events \n+ * {} the event handler.\n+ */\n+ events: null,\n \n- var center = this.getCachedCenter();\n+ /** \n+ * Property: map \n+ * {} the map this marker is attached to\n+ */\n+ map: null,\n \n- if (this.baseLayer != null && center != null) {\n- var zoom = this.getZoom();\n- this.zoom = null;\n- this.setCenter(center, zoom);\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 \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- this.events.triggerEvent(\"updatesize\");\n+ this.events = new OpenLayers.Events(this, this.icon.imageDiv);\n },\n \n /**\n- * Method: getCurrentSize\n- * \n- * Returns:\n- * {} A new object with the dimensions \n- * of the map div\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 */\n- getCurrentSize: function() {\n+ destroy: function() {\n+ // erase any drawn features\n+ this.erase();\n \n- var size = new OpenLayers.Size(this.div.clientWidth,\n- this.div.clientHeight);\n+ this.map = null;\n \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+ this.events.destroy();\n+ this.events = null;\n+\n+ if (this.icon != null) {\n+ this.icon.destroy();\n+ this.icon = null;\n }\n- return size;\n },\n \n /** \n- * Method: calculateBounds\n+ * Method: draw\n+ * Calls draw on the icon, and returns that output.\n * \n * Parameters:\n- * center - {} Default is this.getCenter()\n- * resolution - {float} Default is this.getResolution() \n+ * px - {}\n * \n * Returns:\n- * {} A bounds based on resolution, center, and \n- * current mapsize.\n+ * {DOMElement} A new DOM Image with this marker's icon set at the \n+ * location passed-in\n */\n- calculateBounds: function(center, resolution) {\n-\n- var extent = null;\n+ draw: function(px) {\n+ return this.icon.draw(px);\n+ },\n \n- if (center == null) {\n- center = this.getCachedCenter();\n- }\n- if (resolution == null) {\n- resolution = this.getResolution();\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 }\n+ },\n \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+ * 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 }\n-\n- return extent;\n+ this.lonlat = this.map.getLonLatFromLayerPx(px);\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: getCenter\n+ * APIMethod: isDrawn\n * \n * Returns:\n- * {}\n+ * {Boolean} Whether or not the marker is drawn.\n */\n- getCenter: function() {\n- var center = null;\n- var cachedCenter = this.getCachedCenter();\n- if (cachedCenter) {\n- center = cachedCenter.clone();\n- }\n- return center;\n+ isDrawn: function() {\n+ var isDrawn = (this.icon && this.icon.isDrawn());\n+ return isDrawn;\n },\n \n /**\n- * Method: getCachedCenter\n+ * Method: onScreen\n *\n * Returns:\n- * {}\n+ * {Boolean} Whether or not the marker is currently visible on screen.\n */\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+ onScreen: function() {\n+\n+ var onScreen = false;\n+ if (this.map) {\n+ var screenBounds = this.map.getExtent();\n+ onScreen = screenBounds.containsLonLat(this.lonlat);\n }\n- return this.center;\n+ return onScreen;\n },\n \n /**\n- * APIMethod: getZoom\n- * \n- * Returns:\n- * {Integer}\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,