{"diffoscope-json-version": 1, "source1": "/srv/reproducible-results/rbuild-debian/r-b-build.59zYmMjR/b1/openlayers_2.13.1+ds2-10_amd64.changes", "source2": "/srv/reproducible-results/rbuild-debian/r-b-build.59zYmMjR/b2/openlayers_2.13.1+ds2-10_amd64.changes", "unified_diff": null, "details": [{"source1": "Files", "source2": "Files", "unified_diff": "@@ -1,2 +1,2 @@\n \n- b8f862d3ec74ba06200c117bb86bd490 715748 javascript optional libjs-openlayers_2.13.1+ds2-10_all.deb\n+ ed0d68076b09c8e93a24f9653872d0fa 706992 javascript optional libjs-openlayers_2.13.1+ds2-10_all.deb\n"}, {"source1": "libjs-openlayers_2.13.1+ds2-10_all.deb", "source2": "libjs-openlayers_2.13.1+ds2-10_all.deb", "unified_diff": null, "details": [{"source1": "file list", "source2": "file list", "unified_diff": "@@ -1,3 +1,3 @@\n -rw-r--r-- 0 0 0 4 2023-01-14 13:27:41.000000 debian-binary\n--rw-r--r-- 0 0 0 3684 2023-01-14 13:27:41.000000 control.tar.xz\n--rw-r--r-- 0 0 0 711872 2023-01-14 13:27:41.000000 data.tar.xz\n+-rw-r--r-- 0 0 0 3680 2023-01-14 13:27:41.000000 control.tar.xz\n+-rw-r--r-- 0 0 0 703120 2023-01-14 13:27:41.000000 data.tar.xz\n"}, {"source1": "control.tar.xz", "source2": "control.tar.xz", "unified_diff": null, "details": [{"source1": "control.tar", "source2": "control.tar", "unified_diff": null, "details": [{"source1": "./md5sums", "source2": "./md5sums", "unified_diff": null, "details": [{"source1": "./md5sums", "source2": "./md5sums", "comments": ["Files differ"], "unified_diff": null}]}]}]}, {"source1": "data.tar.xz", "source2": "data.tar.xz", "unified_diff": null, "details": [{"source1": "data.tar", "source2": "data.tar", "unified_diff": null, "details": [{"source1": "./usr/share/javascript/openlayers/OpenLayers.js", "source2": "./usr/share/javascript/openlayers/OpenLayers.js", "unified_diff": null, "details": [{"source1": "js-beautify {}", "source2": "js-beautify {}", "unified_diff": "@@ -136,14 +136,394 @@\n * (code)\n * \n * (end code)\n */\n ImgPath: ''\n };\n /* ======================================================================\n+ OpenLayers/BaseTypes/Class.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+/**\n+ * Constructor: OpenLayers.Class\n+ * Base class used to construct all other classes. Includes support for \n+ * multiple inheritance. \n+ * \n+ * This constructor is new in OpenLayers 2.5. At OpenLayers 3.0, the old \n+ * syntax for creating classes and dealing with inheritance \n+ * will be removed.\n+ * \n+ * To create a new OpenLayers-style class, use the following syntax:\n+ * (code)\n+ * var MyClass = OpenLayers.Class(prototype);\n+ * (end)\n+ *\n+ * To create a new OpenLayers-style class with multiple inheritance, use the\n+ * following syntax:\n+ * (code)\n+ * var MyClass = OpenLayers.Class(Class1, Class2, prototype);\n+ * (end)\n+ * \n+ * Note that instanceof reflection will only reveal Class1 as superclass.\n+ *\n+ */\n+OpenLayers.Class = function() {\n+ var len = arguments.length;\n+ var P = arguments[0];\n+ var F = arguments[len - 1];\n+\n+ var C = typeof F.initialize == \"function\" ?\n+ F.initialize :\n+ function() {\n+ P.prototype.initialize.apply(this, arguments);\n+ };\n+\n+ if (len > 1) {\n+ var newArgs = [C, P].concat(\n+ Array.prototype.slice.call(arguments).slice(1, len - 1), F);\n+ OpenLayers.inherit.apply(null, newArgs);\n+ } else {\n+ C.prototype = F;\n+ }\n+ return C;\n+};\n+\n+/**\n+ * Function: OpenLayers.inherit\n+ *\n+ * Parameters:\n+ * C - {Object} the class that inherits\n+ * P - {Object} the superclass to inherit from\n+ *\n+ * In addition to the mandatory C and P parameters, an arbitrary number of\n+ * objects can be passed, which will extend C.\n+ */\n+OpenLayers.inherit = function(C, P) {\n+ var F = function() {};\n+ F.prototype = P.prototype;\n+ C.prototype = new F;\n+ var i, l, o;\n+ for (i = 2, l = arguments.length; i < l; i++) {\n+ o = arguments[i];\n+ if (typeof o === \"function\") {\n+ o = o.prototype;\n+ }\n+ OpenLayers.Util.extend(C.prototype, o);\n+ }\n+};\n+\n+/**\n+ * APIFunction: extend\n+ * Copy all properties of a source object to a destination object. Modifies\n+ * the passed in destination object. Any properties on the source object\n+ * that are set to undefined will not be (re)set on the destination object.\n+ *\n+ * Parameters:\n+ * destination - {Object} The object that will be modified\n+ * source - {Object} The object with properties to be set on the destination\n+ *\n+ * Returns:\n+ * {Object} The destination object.\n+ */\n+OpenLayers.Util = OpenLayers.Util || {};\n+OpenLayers.Util.extend = function(destination, source) {\n+ destination = destination || {};\n+ if (source) {\n+ for (var property in source) {\n+ var value = source[property];\n+ if (value !== undefined) {\n+ destination[property] = value;\n+ }\n+ }\n+\n+ /**\n+ * IE doesn't include the toString property when iterating over an object's\n+ * properties with the for(property in object) syntax. Explicitly check if\n+ * the source has its own toString property.\n+ */\n+\n+ /*\n+ * FF/Windows < 2.0.0.13 reports \"Illegal operation on WrappedNative\n+ * prototype object\" when calling hawOwnProperty if the source object\n+ * is an instance of window.Event.\n+ */\n+\n+ var sourceIsEvt = typeof window.Event == \"function\" &&\n+ source instanceof window.Event;\n+\n+ if (!sourceIsEvt &&\n+ source.hasOwnProperty && source.hasOwnProperty(\"toString\")) {\n+ destination.toString = source.toString;\n+ }\n+ }\n+ return destination;\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+ * Property: url \n+ * {String} image url\n+ */\n+ url: null,\n+\n+ /** \n+ * Property: size \n+ * {|Object} An OpenLayers.Size or\n+ * an object with a 'w' and 'h' properties.\n+ */\n+ size: null,\n+\n+ /** \n+ * Property: offset \n+ * {|Object} distance in pixels to offset the\n+ * image when being rendered. An OpenLayers.Pixel or an object\n+ * with a 'x' and 'y' properties.\n+ */\n+ offset: null,\n+\n+ /** \n+ * Property: calculateOffset \n+ * {Function} Function to calculate the offset (based on the size)\n+ */\n+ calculateOffset: null,\n+\n+ /** \n+ * Property: imageDiv \n+ * {DOMElement} \n+ */\n+ imageDiv: null,\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+ /** \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+ 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+ OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);\n+ this.imageDiv.innerHTML = \"\";\n+ this.imageDiv = null;\n+ },\n+\n+ /** \n+ * Method: clone\n+ * \n+ * Returns:\n+ * {} A fresh copy of the icon.\n+ */\n+ clone: function() {\n+ return new OpenLayers.Icon(this.url,\n+ this.size,\n+ this.offset,\n+ this.calculateOffset);\n+ },\n+\n+ /**\n+ * Method: setSize\n+ * \n+ * Parameters:\n+ * size - {|Object} An OpenLayers.Size or\n+ * an object with a 'w' and 'h' properties.\n+ */\n+ setSize: function(size) {\n+ if (size != null) {\n+ this.size = size;\n+ }\n+ this.draw();\n+ },\n+\n+ /**\n+ * Method: setUrl\n+ * \n+ * Parameters:\n+ * url - {String} \n+ */\n+ setUrl: function(url) {\n+ if (url != null) {\n+ this.url = url;\n+ }\n+ this.draw();\n+ },\n+\n+ /** \n+ * Method: draw\n+ * Move the div to the given pixel.\n+ * \n+ * Parameters:\n+ * px - {|Object} An OpenLayers.Pixel or an\n+ * object with a 'x' and 'y' properties.\n+ * \n+ * Returns:\n+ * {DOMElement} A new DOM Image of this icon set at the location passed-in\n+ */\n+ draw: function(px) {\n+ OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,\n+ null,\n+ null,\n+ this.size,\n+ this.url,\n+ \"absolute\");\n+ this.moveTo(px);\n+ return this.imageDiv;\n+ },\n+\n+ /** \n+ * Method: erase\n+ * Erase the underlying image element.\n+ */\n+ erase: function() {\n+ if (this.imageDiv != null && this.imageDiv.parentNode != null) {\n+ OpenLayers.Element.remove(this.imageDiv);\n+ }\n+ },\n+\n+ /** \n+ * Method: setOpacity\n+ * Change the icon's opacity\n+ *\n+ * Parameters:\n+ * opacity - {float} \n+ */\n+ setOpacity: function(opacity) {\n+ OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null,\n+ null, null, null, null, opacity);\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+ 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+ * Method: display\n+ * Hide or show the icon\n+ *\n+ * Parameters:\n+ * display - {Boolean} \n+ */\n+ display: function(display) {\n+ this.imageDiv.style.display = (display) ? \"\" : \"none\";\n+ },\n+\n+\n+ /**\n+ * APIMethod: isDrawn\n+ * \n+ * Returns:\n+ * {Boolean} Whether or not the icon is drawn.\n+ */\n+ isDrawn: function() {\n+ // nodeType 11 for ie, whose nodes *always* have a parentNode\n+ // (of type document fragment)\n+ var isDrawn = (this.imageDiv && this.imageDiv.parentNode &&\n+ (this.imageDiv.parentNode.nodeType != 11));\n+\n+ return isDrawn;\n+ },\n+\n+ CLASS_NAME: \"OpenLayers.Icon\"\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@@ -383,645 +763,377 @@\n requestFrame: requestFrame,\n start: start,\n stop: stop\n };\n \n })(window);\n /* ======================================================================\n- OpenLayers/BaseTypes/Class.js\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/SingleFile.js\n- */\n-\n-/**\n- * Constructor: OpenLayers.Class\n- * Base class used to construct all other classes. Includes support for \n- * multiple inheritance. \n- * \n- * This constructor is new in OpenLayers 2.5. At OpenLayers 3.0, the old \n- * syntax for creating classes and dealing with inheritance \n- * will be removed.\n- * \n- * To create a new OpenLayers-style class, use the following syntax:\n- * (code)\n- * var MyClass = OpenLayers.Class(prototype);\n- * (end)\n- *\n- * To create a new OpenLayers-style class with multiple inheritance, use the\n- * following syntax:\n- * (code)\n- * var MyClass = OpenLayers.Class(Class1, Class2, prototype);\n- * (end)\n- * \n- * Note that instanceof reflection will only reveal Class1 as superclass.\n- *\n- */\n-OpenLayers.Class = function() {\n- var len = arguments.length;\n- var P = arguments[0];\n- var F = arguments[len - 1];\n-\n- var C = typeof F.initialize == \"function\" ?\n- F.initialize :\n- function() {\n- P.prototype.initialize.apply(this, arguments);\n- };\n-\n- if (len > 1) {\n- var newArgs = [C, P].concat(\n- Array.prototype.slice.call(arguments).slice(1, len - 1), F);\n- OpenLayers.inherit.apply(null, newArgs);\n- } else {\n- C.prototype = F;\n- }\n- return C;\n-};\n-\n-/**\n- * Function: OpenLayers.inherit\n- *\n- * Parameters:\n- * C - {Object} the class that inherits\n- * P - {Object} the superclass to inherit from\n- *\n- * In addition to the mandatory C and P parameters, an arbitrary number of\n- * objects can be passed, which will extend C.\n+ * @requires OpenLayers/BaseTypes/Class.js\n+ * @requires OpenLayers/Animation.js\n */\n-OpenLayers.inherit = function(C, P) {\n- var F = function() {};\n- F.prototype = P.prototype;\n- C.prototype = new F;\n- var i, l, o;\n- for (i = 2, l = arguments.length; i < l; i++) {\n- o = arguments[i];\n- if (typeof o === \"function\") {\n- o = o.prototype;\n- }\n- OpenLayers.Util.extend(C.prototype, o);\n- }\n-};\n \n /**\n- * APIFunction: extend\n- * Copy all properties of a source object to a destination object. Modifies\n- * the passed in destination object. Any properties on the source object\n- * that are set to undefined will not be (re)set on the destination object.\n- *\n- * Parameters:\n- * destination - {Object} The object that will be modified\n- * source - {Object} The object with properties to be set on the destination\n- *\n- * Returns:\n- * {Object} The destination object.\n+ * Namespace: OpenLayers.Tween\n */\n-OpenLayers.Util = OpenLayers.Util || {};\n-OpenLayers.Util.extend = function(destination, source) {\n- destination = destination || {};\n- if (source) {\n- for (var property in source) {\n- var value = source[property];\n- if (value !== undefined) {\n- destination[property] = value;\n- }\n- }\n-\n- /**\n- * IE doesn't include the toString property when iterating over an object's\n- * properties with the for(property in object) syntax. Explicitly check if\n- * the source has its own toString property.\n- */\n-\n- /*\n- * FF/Windows < 2.0.0.13 reports \"Illegal operation on WrappedNative\n- * prototype object\" when calling hawOwnProperty if the source object\n- * is an instance of window.Event.\n- */\n-\n- var sourceIsEvt = typeof window.Event == \"function\" &&\n- source instanceof window.Event;\n+OpenLayers.Tween = OpenLayers.Class({\n \n- if (!sourceIsEvt &&\n- source.hasOwnProperty && source.hasOwnProperty(\"toString\")) {\n- destination.toString = source.toString;\n- }\n- }\n- return destination;\n-};\n-/* ======================================================================\n- OpenLayers/Geometry.js\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-/* 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+ * APIProperty: begin\n+ * {Object} Values to start the animation with\n+ */\n+ begin: null,\n \n-/**\n- * @requires OpenLayers/BaseTypes/Class.js\n- */\n+ /**\n+ * APIProperty: finish\n+ * {Object} Values to finish the animation with\n+ */\n+ finish: null,\n \n-/**\n- * Class: OpenLayers.Geometry\n- * A Geometry is a description of a geographic object. Create an instance of\n- * this class with the constructor. This is a base class,\n- * typical geometry types are described by subclasses of this class.\n- *\n- * Note that if you use the method, you must\n- * explicitly include the OpenLayers.Format.WKT in your build.\n- */\n-OpenLayers.Geometry = OpenLayers.Class({\n+ /**\n+ * APIProperty: duration\n+ * {int} duration of the tween (number of steps)\n+ */\n+ duration: null,\n \n /**\n- * Property: id\n- * {String} A unique identifier for this geometry.\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- id: null,\n+ callbacks: null,\n \n /**\n- * Property: parent\n- * {}This is set when a Geometry is added as component\n- * of another geometry\n+ * Property: time\n+ * {int} Step counter\n */\n- parent: null,\n+ time: null,\n \n /**\n- * Property: bounds \n- * {} The bounds of this geometry\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- bounds: null,\n+ minFrameRate: null,\n \n /**\n- * Constructor: OpenLayers.Geometry\n- * Creates a geometry object. \n+ * Property: startTime\n+ * {Number} The timestamp of the first execution step. Used for skipping\n+ * frames\n */\n- initialize: function() {\n- this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + \"_\");\n- },\n+ startTime: null,\n \n /**\n- * Method: destroy\n- * Destroy this geometry.\n+ * Property: animationId\n+ * {int} Loop id returned by OpenLayers.Animation.start\n */\n- destroy: function() {\n- this.id = null;\n- this.bounds = null;\n- },\n+ animationId: null,\n \n /**\n- * APIMethod: clone\n- * Create a clone of this geometry. Does not set any non-standard\n- * properties of the cloned geometry.\n- * \n- * Returns:\n- * {} An exact clone of this geometry.\n+ * Property: playing\n+ * {Boolean} Tells if the easing is currently playing\n */\n- clone: function() {\n- return new OpenLayers.Geometry();\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- * Method: setBounds\n- * Set the bounds for this Geometry.\n+ * APIMethod: start\n+ * Plays the Tween, and calls the callback method on each step\n * \n * Parameters:\n- * bounds - {} \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- setBounds: function(bounds) {\n- if (bounds) {\n- this.bounds = bounds.clone();\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- * Method: clearBounds\n- * Nullify this components bounds and that of its parent as well.\n+ * APIMethod: stop\n+ * Stops the Tween, and calls the done callback\n+ * Doesn't do anything if animation is already finished\n */\n- clearBounds: function() {\n- this.bounds = null;\n- if (this.parent) {\n- this.parent.clearBounds();\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: extendBounds\n- * Extend the existing bounds to include the new bounds. \n- * If geometry's bounds is not yet set, then set a new Bounds.\n- * \n- * Parameters:\n- * newBounds - {} \n+ * Method: play\n+ * Calls the appropriate easing method\n */\n- extendBounds: function(newBounds) {\n- var bounds = this.getBounds();\n- if (!bounds) {\n- this.setBounds(newBounds);\n- } else {\n- this.bounds.extend(newBounds);\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- * APIMethod: getBounds\n- * Get the bounds for this Geometry. If bounds is not set, it \n- * is calculated again, this makes queries faster.\n- * \n- * Returns:\n- * {}\n+ * Create empty functions for all easing methods.\n */\n- getBounds: function() {\n- if (this.bounds == null) {\n- this.calculateBounds();\n- }\n- return this.bounds;\n- },\n+ CLASS_NAME: \"OpenLayers.Tween\"\n+});\n \n- /** \n- * APIMethod: calculateBounds\n- * Recalculate the bounds for the geometry. \n+/**\n+ * Namespace: OpenLayers.Easing\n+ * \n+ * Credits:\n+ * Easing Equations by Robert Penner, \n+ */\n+OpenLayers.Easing = {\n+ /**\n+ * Create empty functions for all easing methods.\n */\n- calculateBounds: function() {\n- //\n- // This should be overridden by subclasses.\n- //\n- },\n+ CLASS_NAME: \"OpenLayers.Easing\"\n+};\n+\n+/**\n+ * Namespace: OpenLayers.Easing.Linear\n+ */\n+OpenLayers.Easing.Linear = {\n \n /**\n- * APIMethod: distanceTo\n- * Calculate the closest distance between two geometries (on the x-y plane).\n- *\n+ * Function: easeIn\n+ * \n * Parameters:\n- * geometry - {} The target geometry.\n- * options - {Object} Optional properties for configuring the distance\n- * calculation.\n+ * t - {Float} time\n+ * b - {Float} beginning position\n+ * c - {Float} total change\n+ * d - {Float} duration of the transition\n *\n- * Valid options depend on the specific geometry type.\n- * \n * Returns:\n- * {Number | Object} The distance between this geometry and the target.\n- * If details is true, the return will be an object with distance,\n- * x0, y0, x1, and x2 properties. The x0 and y0 properties represent\n- * the coordinates of the closest point on this geometry. The x1 and y1\n- * properties represent the coordinates of the closest point on the\n- * target geometry.\n+ * {Float}\n */\n- distanceTo: function(geometry, options) {},\n+ easeIn: function(t, b, c, d) {\n+ return c * t / d + b;\n+ },\n \n /**\n- * APIMethod: getVertices\n- * Return a list of all points in this geometry.\n- *\n+ * Function: easeOut\n+ * \n * Parameters:\n- * nodes - {Boolean} For lines, only return vertices that are\n- * endpoints. If false, for lines, only vertices that are not\n- * endpoints will be returned. If not provided, all vertices will\n- * be returned.\n+ * t - {Float} time\n+ * b - {Float} beginning position\n+ * c - {Float} total change\n+ * d - {Float} duration of the transition\n *\n * Returns:\n- * {Array} A list of all vertices in the geometry.\n+ * {Float}\n */\n- getVertices: function(nodes) {},\n+ easeOut: function(t, b, c, d) {\n+ return c * t / d + b;\n+ },\n \n /**\n- * Method: atPoint\n- * Note - This is only an approximation based on the bounds of the \n- * geometry.\n+ * Function: easeInOut\n * \n * Parameters:\n- * lonlat - {|Object} OpenLayers.LonLat or an\n- * object with a 'lon' and 'lat' properties.\n- * toleranceLon - {float} Optional tolerance in Geometric Coords\n- * toleranceLat - {float} Optional tolerance in Geographic Coords\n- * \n+ * t - {Float} time\n+ * b - {Float} beginning position\n+ * c - {Float} total change\n+ * d - {Float} duration of the transition\n+ *\n * Returns:\n- * {Boolean} Whether or not the geometry is at the specified location\n+ * {Float}\n */\n- atPoint: function(lonlat, toleranceLon, toleranceLat) {\n- var atPoint = false;\n- var bounds = this.getBounds();\n- if ((bounds != null) && (lonlat != null)) {\n+ easeInOut: function(t, b, c, d) {\n+ return c * t / d + b;\n+ },\n \n- var dX = (toleranceLon != null) ? toleranceLon : 0;\n- var dY = (toleranceLat != null) ? toleranceLat : 0;\n+ CLASS_NAME: \"OpenLayers.Easing.Linear\"\n+};\n \n- var toleranceBounds =\n- new OpenLayers.Bounds(this.bounds.left - dX,\n- this.bounds.bottom - dY,\n- this.bounds.right + dX,\n- this.bounds.top + dY);\n+/**\n+ * Namespace: OpenLayers.Easing.Expo\n+ */\n+OpenLayers.Easing.Expo = {\n \n- atPoint = toleranceBounds.containsLonLat(lonlat);\n- }\n- return atPoint;\n+ /**\n+ * Function: easeIn\n+ * \n+ * Parameters:\n+ * t - {Float} time\n+ * b - {Float} beginning position\n+ * c - {Float} total change\n+ * d - {Float} duration of the transition\n+ *\n+ * Returns:\n+ * {Float}\n+ */\n+ easeIn: function(t, b, c, d) {\n+ return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;\n },\n \n /**\n- * Method: getLength\n- * Calculate the length of this geometry. This method is defined in\n- * subclasses.\n+ * Function: easeOut\n * \n+ * Parameters:\n+ * t - {Float} time\n+ * b - {Float} beginning position\n+ * c - {Float} total change\n+ * d - {Float} duration of the transition\n+ *\n * Returns:\n- * {Float} The length of the collection by summing its parts\n+ * {Float}\n */\n- getLength: function() {\n- //to be overridden by geometries that actually have a length\n- //\n- return 0.0;\n+ easeOut: function(t, b, c, d) {\n+ return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;\n },\n \n /**\n- * Method: getArea\n- * Calculate the area of this geometry. This method is defined in subclasses.\n+ * Function: easeInOut\n * \n+ * Parameters:\n+ * t - {Float} time\n+ * b - {Float} beginning position\n+ * c - {Float} total change\n+ * d - {Float} duration of the transition\n+ *\n * Returns:\n- * {Float} The area of the collection by summing its parts\n+ * {Float}\n */\n- getArea: function() {\n- //to be overridden by geometries that actually have an area\n- //\n- return 0.0;\n+ easeInOut: function(t, b, c, d) {\n+ if (t == 0) return b;\n+ if (t == d) return b + c;\n+ if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;\n+ return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;\n },\n \n+ CLASS_NAME: \"OpenLayers.Easing.Expo\"\n+};\n+\n+/**\n+ * Namespace: OpenLayers.Easing.Quad\n+ */\n+OpenLayers.Easing.Quad = {\n+\n /**\n- * APIMethod: getCentroid\n- * Calculate the centroid of this geometry. This method is defined in subclasses.\n+ * Function: easeIn\n+ * \n+ * Parameters:\n+ * t - {Float} time\n+ * b - {Float} beginning position\n+ * c - {Float} total change\n+ * d - {Float} duration of the transition\n *\n * Returns:\n- * {} The centroid of the collection\n+ * {Float}\n */\n- getCentroid: function() {\n- return null;\n+ easeIn: function(t, b, c, d) {\n+ return c * (t /= d) * t + b;\n },\n \n /**\n- * Method: toString\n- * Returns a text representation of the geometry. If the WKT format is\n- * included in a build, this will be the Well-Known Text \n- * representation.\n+ * Function: easeOut\n+ * \n+ * Parameters:\n+ * t - {Float} time\n+ * b - {Float} beginning position\n+ * c - {Float} total change\n+ * d - {Float} duration of the transition\n *\n * Returns:\n- * {String} String representation of this geometry.\n+ * {Float}\n */\n- toString: function() {\n- var string;\n- if (OpenLayers.Format && OpenLayers.Format.WKT) {\n- string = OpenLayers.Format.WKT.prototype.write(\n- new OpenLayers.Feature.Vector(this)\n- );\n- } else {\n- string = Object.prototype.toString.call(this);\n- }\n- return string;\n+ easeOut: function(t, b, c, d) {\n+ return -c * (t /= d) * (t - 2) + b;\n },\n \n- CLASS_NAME: \"OpenLayers.Geometry\"\n-});\n-\n-/**\n- * Function: OpenLayers.Geometry.fromWKT\n- * Generate a geometry given a Well-Known Text string. For this method to\n- * work, you must include the OpenLayers.Format.WKT in your build \n- * explicitly.\n- *\n- * Parameters:\n- * wkt - {String} A string representing the geometry in Well-Known Text.\n- *\n- * Returns:\n- * {} A geometry of the appropriate class.\n- */\n-OpenLayers.Geometry.fromWKT = function(wkt) {\n- var geom;\n- if (OpenLayers.Format && OpenLayers.Format.WKT) {\n- var format = OpenLayers.Geometry.fromWKT.format;\n- if (!format) {\n- format = new OpenLayers.Format.WKT();\n- OpenLayers.Geometry.fromWKT.format = format;\n- }\n- var result = format.read(wkt);\n- if (result instanceof OpenLayers.Feature.Vector) {\n- geom = result.geometry;\n- } else if (OpenLayers.Util.isArray(result)) {\n- var len = result.length;\n- var components = new Array(len);\n- for (var i = 0; i < len; ++i) {\n- components[i] = result[i].geometry;\n- }\n- geom = new OpenLayers.Geometry.Collection(components);\n- }\n- }\n- return geom;\n-};\n-\n-/**\n- * Method: OpenLayers.Geometry.segmentsIntersect\n- * Determine whether two line segments intersect. Optionally calculates\n- * and returns the intersection point. This function is optimized for\n- * cases where seg1.x2 >= seg2.x1 || seg2.x2 >= seg1.x1. In those\n- * obvious cases where there is no intersection, the function should\n- * not be called.\n- *\n- * Parameters:\n- * seg1 - {Object} Object representing a segment with properties x1, y1, x2,\n- * and y2. The start point is represented by x1 and y1. The end point\n- * is represented by x2 and y2. Start and end are ordered so that x1 < x2.\n- * seg2 - {Object} Object representing a segment with properties x1, y1, x2,\n- * and y2. The start point is represented by x1 and y1. The end point\n- * is represented by x2 and y2. Start and end are ordered so that x1 < x2.\n- * options - {Object} Optional properties for calculating the intersection.\n- *\n- * Valid options:\n- * point - {Boolean} Return the intersection point. If false, the actual\n- * intersection point will not be calculated. If true and the segments\n- * intersect, the intersection point will be returned. If true and\n- * the segments do not intersect, false will be returned. If true and\n- * the segments are coincident, true will be returned.\n- * tolerance - {Number} If a non-null value is provided, if the segments are\n- * within the tolerance distance, this will be considered an intersection.\n- * In addition, if the point option is true and the calculated intersection\n- * is within the tolerance distance of an end point, the endpoint will be\n- * returned instead of the calculated intersection. Further, if the\n- * intersection is within the tolerance of endpoints on both segments, or\n- * if two segment endpoints are within the tolerance distance of eachother\n- * (but no intersection is otherwise calculated), an endpoint on the\n- * first segment provided will be returned.\n- *\n- * Returns:\n- * {Boolean | } The two segments intersect.\n- * If the point argument is true, the return will be the intersection\n- * point or false if none exists. If point is true and the segments\n- * are coincident, return will be true (and the instersection is equal\n- * to the shorter segment).\n- */\n-OpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, options) {\n- var point = options && options.point;\n- var tolerance = options && options.tolerance;\n- var intersection = false;\n- var x11_21 = seg1.x1 - seg2.x1;\n- var y11_21 = seg1.y1 - seg2.y1;\n- var x12_11 = seg1.x2 - seg1.x1;\n- var y12_11 = seg1.y2 - seg1.y1;\n- var y22_21 = seg2.y2 - seg2.y1;\n- var x22_21 = seg2.x2 - seg2.x1;\n- var d = (y22_21 * x12_11) - (x22_21 * y12_11);\n- var n1 = (x22_21 * y11_21) - (y22_21 * x11_21);\n- var n2 = (x12_11 * y11_21) - (y12_11 * x11_21);\n- if (d == 0) {\n- // parallel\n- if (n1 == 0 && n2 == 0) {\n- // coincident\n- intersection = true;\n- }\n- } else {\n- var along1 = n1 / d;\n- var along2 = n2 / d;\n- if (along1 >= 0 && along1 <= 1 && along2 >= 0 && along2 <= 1) {\n- // intersect\n- if (!point) {\n- intersection = true;\n- } else {\n- // calculate the intersection point\n- var x = seg1.x1 + (along1 * x12_11);\n- var y = seg1.y1 + (along1 * y12_11);\n- intersection = new OpenLayers.Geometry.Point(x, y);\n- }\n- }\n- }\n- if (tolerance) {\n- var dist;\n- if (intersection) {\n- if (point) {\n- var segs = [seg1, seg2];\n- var seg, x, y;\n- // check segment endpoints for proximity to intersection\n- // set intersection to first endpoint within the tolerance\n- outer: for (var i = 0; i < 2; ++i) {\n- seg = segs[i];\n- for (var j = 1; j < 3; ++j) {\n- x = seg[\"x\" + j];\n- y = seg[\"y\" + j];\n- dist = Math.sqrt(\n- Math.pow(x - intersection.x, 2) +\n- Math.pow(y - intersection.y, 2)\n- );\n- if (dist < tolerance) {\n- intersection.x = x;\n- intersection.y = y;\n- break outer;\n- }\n- }\n- }\n-\n- }\n- } else {\n- // no calculated intersection, but segments could be within\n- // the tolerance of one another\n- var segs = [seg1, seg2];\n- var source, target, x, y, p, result;\n- // check segment endpoints for proximity to intersection\n- // set intersection to first endpoint within the tolerance\n- outer: for (var i = 0; i < 2; ++i) {\n- source = segs[i];\n- target = segs[(i + 1) % 2];\n- for (var j = 1; j < 3; ++j) {\n- p = {\n- x: source[\"x\" + j],\n- y: source[\"y\" + j]\n- };\n- result = OpenLayers.Geometry.distanceToSegment(p, target);\n- if (result.distance < tolerance) {\n- if (point) {\n- intersection = new OpenLayers.Geometry.Point(p.x, p.y);\n- } else {\n- intersection = true;\n- }\n- break outer;\n- }\n- }\n- }\n- }\n- }\n- return intersection;\n-};\n-\n-/**\n- * Function: OpenLayers.Geometry.distanceToSegment\n- *\n- * Parameters:\n- * point - {Object} An object with x and y properties representing the\n- * point coordinates.\n- * segment - {Object} An object with x1, y1, x2, and y2 properties\n- * representing endpoint coordinates.\n- *\n- * Returns:\n- * {Object} An object with distance, along, x, and y properties. The distance\n- * will be the shortest distance between the input point and segment.\n- * The x and y properties represent the coordinates along the segment\n- * where the shortest distance meets the segment. The along attribute\n- * describes how far between the two segment points the given point is.\n- */\n-OpenLayers.Geometry.distanceToSegment = function(point, segment) {\n- var result = OpenLayers.Geometry.distanceSquaredToSegment(point, segment);\n- result.distance = Math.sqrt(result.distance);\n- return result;\n-};\n+ /**\n+ * Function: easeInOut\n+ * \n+ * Parameters:\n+ * t - {Float} time\n+ * b - {Float} beginning position\n+ * c - {Float} total change\n+ * d - {Float} duration of the transition\n+ *\n+ * Returns:\n+ * {Float}\n+ */\n+ easeInOut: function(t, b, c, d) {\n+ if ((t /= d / 2) < 1) return c / 2 * t * t + b;\n+ return -c / 2 * ((--t) * (t - 2) - 1) + b;\n+ },\n \n-/**\n- * Function: OpenLayers.Geometry.distanceSquaredToSegment\n- *\n- * Usually the distanceToSegment function should be used. This variant however\n- * can be used for comparisons where the exact distance is not important.\n- *\n- * Parameters:\n- * point - {Object} An object with x and y properties representing the\n- * point coordinates.\n- * segment - {Object} An object with x1, y1, x2, and y2 properties\n- * representing endpoint coordinates.\n- *\n- * Returns:\n- * {Object} An object with squared distance, along, x, and y properties.\n- * The distance will be the shortest distance between the input point and\n- * segment. The x and y properties represent the coordinates along the\n- * segment where the shortest distance meets the segment. The along\n- * attribute describes how far between the two segment points the given\n- * point is.\n- */\n-OpenLayers.Geometry.distanceSquaredToSegment = function(point, segment) {\n- var x0 = point.x;\n- var y0 = point.y;\n- var x1 = segment.x1;\n- var y1 = segment.y1;\n- var x2 = segment.x2;\n- var y2 = segment.y2;\n- var dx = x2 - x1;\n- var dy = y2 - y1;\n- var along = ((dx * (x0 - x1)) + (dy * (y0 - y1))) /\n- (Math.pow(dx, 2) + Math.pow(dy, 2));\n- var x, y;\n- if (along <= 0.0) {\n- x = x1;\n- y = y1;\n- } else if (along >= 1.0) {\n- x = x2;\n- y = y2;\n- } else {\n- x = x1 + along * dx;\n- y = y1 + along * dy;\n- }\n- return {\n- distance: Math.pow(x - x0, 2) + Math.pow(y - y0, 2),\n- x: x,\n- y: y,\n- along: along\n- };\n+ CLASS_NAME: \"OpenLayers.Easing.Quad\"\n };\n /* ======================================================================\n OpenLayers/BaseTypes.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@@ -5922,12905 +6034,10200 @@\n \n },\n 'delete': {\n display: \"none\"\n }\n };\n /* ======================================================================\n- OpenLayers/Format.js\n+ OpenLayers/Style.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/Util.js\n+ * @requires OpenLayers/Feature/Vector.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+ * Class: OpenLayers.Style\n+ * This class represents a UserStyle obtained\n+ * from a SLD, containing styling rules.\n */\n-OpenLayers.Format = OpenLayers.Class({\n+OpenLayers.Style = OpenLayers.Class({\n \n /**\n- * Property: options\n- * {Object} A reference to options passed to the constructor.\n+ * Property: id\n+ * {String} A unique id for this session.\n */\n- options: null,\n+ id: 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+ * APIProperty: name\n+ * {String}\n */\n- externalProjection: null,\n+ name: 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+ * Property: title\n+ * {String} Title of this style (set if included in SLD)\n */\n- internalProjection: null,\n+ title: null,\n \n /**\n- * APIProperty: data\n- * {Object} When is true, this is the parsed string sent to\n- * .\n+ * Property: description\n+ * {String} Description of this style (set if abstract is included in SLD)\n */\n- data: null,\n+ description: null,\n \n /**\n- * APIProperty: keepData\n- * {Object} Maintain a reference () to the most recently read data.\n- * Default is false.\n+ * APIProperty: layerName\n+ * {} name of the layer that this style belongs to, usually\n+ * according to the NamedLayer attribute of an SLD document.\n */\n- keepData: false,\n+ layerName: null,\n \n /**\n- * Constructor: OpenLayers.Format\n- * Instances of this class are not useful. See one of the subclasses.\n+ * APIProperty: isDefault\n+ * {Boolean}\n+ */\n+ isDefault: false,\n+\n+ /** \n+ * Property: rules \n+ * {Array()}\n+ */\n+ rules: null,\n+\n+ /**\n+ * APIProperty: context\n+ * {Object} An optional object with properties that symbolizers' property\n+ * values should be evaluated against. If no context is specified,\n+ * feature.attributes will be used\n+ */\n+ context: null,\n+\n+ /**\n+ * Property: defaultStyle\n+ * {Object} hash of style properties to use as default for merging\n+ * rule-based style symbolizers onto. If no rules are defined,\n+ * createSymbolizer will return this style. If is set to\n+ * true, the defaultStyle will only be taken into account if there are\n+ * rules defined.\n+ */\n+ defaultStyle: null,\n+\n+ /**\n+ * Property: defaultsPerSymbolizer\n+ * {Boolean} If set to true, the will extend the symbolizer\n+ * of every rule. Properties of the will also be used to set\n+ * missing symbolizer properties if the symbolizer has stroke, fill or\n+ * graphic set to true. Default is false.\n+ */\n+ defaultsPerSymbolizer: false,\n+\n+ /**\n+ * Property: propertyStyles\n+ * {Hash of Boolean} cache of style properties that need to be parsed for\n+ * propertyNames. Property names are keys, values won't be used.\n+ */\n+ propertyStyles: null,\n+\n+\n+ /** \n+ * Constructor: OpenLayers.Style\n+ * Creates a UserStyle.\n *\n * Parameters:\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- * format\n+ * style.\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+ * rules - {Array()} List of rules to be added to the\n+ * style.\n+ * \n * Returns:\n- * An instance of OpenLayers.Format\n+ * {}\n */\n- initialize: function(options) {\n+ initialize: function(style, options) {\n+\n OpenLayers.Util.extend(this, options);\n- this.options = options;\n+ this.rules = [];\n+ if (options && options.rules) {\n+ this.addRules(options.rules);\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+ this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + \"_\");\n },\n \n- /**\n+ /** \n * APIMethod: destroy\n- * Clean up.\n+ * nullify references to prevent circular references and memory leaks\n */\n- destroy: function() {},\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- * Method: read\n- * Read data from a string, and return an object whose type depends on the\n- * subclass. \n+ * Method: createSymbolizer\n+ * creates a style by applying all feature-dependent rules to the base\n+ * style.\n * \n * Parameters:\n- * data - {string} Data to read/parse.\n- *\n+ * feature - {} feature to evaluate rules for\n+ * \n * Returns:\n- * Depends on the subclass\n+ * {Object} symbolizer hash\n */\n- read: function(data) {\n- throw new Error('Read not implemented.');\n+ createSymbolizer: function(feature) {\n+ var style = this.defaultsPerSymbolizer ? {} : this.createLiterals(\n+ OpenLayers.Util.extend({}, this.defaultStyle), feature);\n+\n+ var rules = this.rules;\n+\n+ var rule, context;\n+ var elseRules = [];\n+ var appliedRules = false;\n+ for (var i = 0, len = rules.length; i < len; i++) {\n+ rule = rules[i];\n+ // does the rule apply?\n+ var applies = rule.evaluate(feature);\n+\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+ }\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+ }\n+\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 (style.label != null && typeof style.label !== \"string\") {\n+ style.label = String(style.label);\n+ }\n+\n+ return style;\n },\n \n /**\n- * Method: write\n- * Accept an object, and return a string. \n+ * Method: applySymbolizer\n *\n * Parameters:\n- * object - {Object} Object to be serialized\n+ * rule - {}\n+ * style - {Object}\n+ * feature - {}\n *\n * Returns:\n- * {String} A string representation of the object.\n+ * {Object} A style with new symbolizer applied.\n */\n- write: function(object) {\n- throw new Error('Write not implemented.');\n- },\n-\n- CLASS_NAME: \"OpenLayers.Format\"\n-});\n-/* ======================================================================\n- OpenLayers/Geometry/Point.js\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-/* 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+ var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer;\n \n-/**\n- * @requires OpenLayers/Geometry.js\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-/**\n- * Class: OpenLayers.Geometry.Point\n- * Point geometry class. \n- * \n- * Inherits from:\n- * - \n- */\n-OpenLayers.Geometry.Point = OpenLayers.Class(OpenLayers.Geometry, {\n+ // merge the style with the current style\n+ return this.createLiterals(\n+ OpenLayers.Util.extend(style, symbolizer), feature);\n+ },\n \n- /** \n- * APIProperty: x \n- * {float} \n+ /**\n+ * Method: createLiterals\n+ * creates literals for all style properties that have an entry in\n+ * .\n+ * \n+ * Parameters:\n+ * style - {Object} style to create literals for. Will be modified\n+ * inline.\n+ * feature - {Object}\n+ * \n+ * Returns:\n+ * {Object} the modified style\n */\n- x: null,\n+ createLiterals: function(style, feature) {\n+ var context = OpenLayers.Util.extend({}, feature.attributes || feature.data);\n+ OpenLayers.Util.extend(context, this.context);\n \n- /** \n- * APIProperty: y \n- * {float} \n- */\n- y: null,\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- * Constructor: OpenLayers.Geometry.Point\n- * Construct a point geometry.\n- *\n- * Parameters:\n- * x - {float} \n- * y - {float}\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+ * {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- initialize: function(x, y) {\n- OpenLayers.Geometry.prototype.initialize.apply(this, arguments);\n+ findPropertyStyles: function() {\n+ var propertyStyles = {};\n \n- this.x = parseFloat(x);\n- this.y = parseFloat(y);\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: clone\n+ * Method: addPropertyStyles\n+ * \n+ * Parameters:\n+ * propertyStyles - {Object} hash to add new property styles to. Will be\n+ * modified inline\n+ * symbolizer - {Object} search this symbolizer for property styles\n * \n * Returns:\n- * {} An exact clone of this OpenLayers.Geometry.Point\n+ * {Object} propertyStyles hash\n */\n- clone: function(obj) {\n- if (obj == null) {\n- obj = new OpenLayers.Geometry.Point(this.x, this.y);\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- // catch any randomly tagged-on properties\n- OpenLayers.Util.applyDefaults(obj, this);\n-\n- return obj;\n+ /**\n+ * APIMethod: addRules\n+ * Adds rules to this style.\n+ * \n+ * Parameters:\n+ * rules - {Array()}\n+ */\n+ addRules: function(rules) {\n+ Array.prototype.push.apply(this.rules, rules);\n+ this.propertyStyles = this.findPropertyStyles();\n },\n \n- /** \n- * Method: calculateBounds\n- * Create a new Bounds based on the lon/lat\n+ /**\n+ * APIMethod: setDefaultStyle\n+ * Sets the default style for this style object.\n+ * \n+ * Parameters:\n+ * style - {Object} Hash of style properties\n */\n- calculateBounds: function() {\n- this.bounds = new OpenLayers.Bounds(this.x, this.y,\n- this.x, this.y);\n+ setDefaultStyle: function(style) {\n+ this.defaultStyle = style;\n+ this.propertyStyles = this.findPropertyStyles();\n },\n \n /**\n- * APIMethod: distanceTo\n- * Calculate the closest distance between two geometries (on the x-y plane).\n- *\n+ * Method: getSymbolizerPrefix\n+ * Returns the correct symbolizer prefix according to the\n+ * geometry type of the passed geometry\n+ * \n * Parameters:\n- * geometry - {} The target geometry.\n- * options - {Object} Optional properties for configuring the distance\n- * calculation.\n- *\n- * Valid options:\n- * details - {Boolean} Return details from the distance calculation.\n- * Default is false.\n- * edge - {Boolean} Calculate the distance from this geometry to the\n- * nearest edge of the target geometry. Default is true. If true,\n- * calling distanceTo from a geometry that is wholly contained within\n- * the target will result in a non-zero distance. If false, whenever\n- * geometries intersect, calling distanceTo will return 0. If false,\n- * details cannot be returned.\n- *\n+ * geometry - {}\n+ * \n * Returns:\n- * {Number | Object} The distance between this geometry and the target.\n- * If details is true, the return will be an object with distance,\n- * x0, y0, x1, and x2 properties. The x0 and y0 properties represent\n- * the coordinates of the closest point on this geometry. The x1 and y1\n- * properties represent the coordinates of the closest point on the\n- * target geometry.\n+ * {String} key of the according symbolizer\n */\n- distanceTo: function(geometry, options) {\n- var edge = !(options && options.edge === false);\n- var details = edge && options && options.details;\n- var distance, x0, y0, x1, y1, result;\n- if (geometry instanceof OpenLayers.Geometry.Point) {\n- x0 = this.x;\n- y0 = this.y;\n- x1 = geometry.x;\n- y1 = geometry.y;\n- distance = Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2));\n- result = !details ?\n- distance : {\n- x0: x0,\n- y0: y0,\n- x1: x1,\n- y1: y1,\n- distance: distance\n- };\n- } else {\n- result = geometry.distanceTo(this, options);\n- if (details) {\n- // switch coord order since this geom is target\n- result = {\n- x0: result.x1,\n- y0: result.y1,\n- x1: result.x0,\n- y1: result.y0,\n- distance: result.distance\n- };\n+ getSymbolizerPrefix: function(geometry) {\n+ var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES;\n+ for (var i = 0, len = prefixes.length; i < len; i++) {\n+ if (geometry.CLASS_NAME.indexOf(prefixes[i]) != -1) {\n+ return prefixes[i];\n }\n }\n- return result;\n },\n \n- /** \n- * APIMethod: equals\n- * Determine whether another geometry is equivalent to this one. Geometries\n- * are considered equivalent if all components have the same coordinates.\n+ /**\n+ * APIMethod: clone\n+ * Clones this style.\n * \n- * Parameters:\n- * geom - {} The geometry to test. \n- *\n * Returns:\n- * {Boolean} The supplied geometry is equivalent to this geometry.\n+ * {} Clone of this style.\n */\n- equals: function(geom) {\n- var equals = false;\n- if (geom != null) {\n- equals = ((this.x == geom.x && this.y == geom.y) ||\n- (isNaN(this.x) && isNaN(this.y) && isNaN(geom.x) && isNaN(geom.y)));\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 equals;\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/Rule.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/Util.js\n+ * @requires OpenLayers/Style.js\n+ */\n+\n+/**\n+ * Class: OpenLayers.Rule\n+ * This class represents an SLD Rule, as being used for rule-based SLD styling.\n+ */\n+OpenLayers.Rule = OpenLayers.Class({\n+\n /**\n- * Method: toShortString\n- *\n- * Returns:\n- * {String} Shortened String representation of Point object. \n- * (ex. \"5, 42\")\n+ * Property: id\n+ * {String} A unique id for this session.\n */\n- toShortString: function() {\n- return (this.x + \", \" + this.y);\n- },\n+ id: null,\n \n /**\n- * APIMethod: move\n- * Moves a geometry by the given displacement along positive x and y axes.\n- * This modifies the position of the geometry and clears the cached\n- * bounds.\n- *\n- * Parameters:\n- * x - {Float} Distance to move geometry in positive x direction. \n- * y - {Float} Distance to move geometry in positive y direction.\n+ * APIProperty: name\n+ * {String} name of this rule\n */\n- move: function(x, y) {\n- this.x = this.x + x;\n- this.y = this.y + y;\n- this.clearBounds();\n- },\n+ name: null,\n \n /**\n- * APIMethod: rotate\n- * Rotate a point around another.\n- *\n- * Parameters:\n- * angle - {Float} Rotation angle in degrees (measured counterclockwise\n- * from the positive x-axis)\n- * origin - {} Center point for the rotation\n+ * Property: title\n+ * {String} Title of this rule (set if included in SLD)\n */\n- rotate: function(angle, origin) {\n- angle *= Math.PI / 180;\n- var radius = this.distanceTo(origin);\n- var theta = angle + Math.atan2(this.y - origin.y, this.x - origin.x);\n- this.x = origin.x + (radius * Math.cos(theta));\n- this.y = origin.y + (radius * Math.sin(theta));\n- this.clearBounds();\n- },\n+ title: null,\n \n /**\n- * APIMethod: getCentroid\n- *\n- * Returns:\n- * {} The centroid of the collection\n+ * Property: description\n+ * {String} Description of this rule (set if abstract is included in SLD)\n */\n- getCentroid: function() {\n- return new OpenLayers.Geometry.Point(this.x, this.y);\n- },\n+ description: null,\n \n /**\n- * APIMethod: resize\n- * Resize a point relative to some origin. For points, this has the effect\n- * of scaling a vector (from the origin to the point). This method is\n- * more useful on geometry collection subclasses.\n+ * Property: context\n+ * {Object} An optional object with properties that the rule should be\n+ * evaluated against. If no context is specified, feature.attributes will\n+ * be used.\n+ */\n+ context: null,\n+\n+ /**\n+ * Property: filter\n+ * {} Optional filter for the rule.\n+ */\n+ filter: null,\n+\n+ /**\n+ * Property: elseFilter\n+ * {Boolean} Determines whether this rule is only to be applied only if\n+ * no other rules match (ElseFilter according to the SLD specification). \n+ * Default is false. For instances of OpenLayers.Rule, if elseFilter is\n+ * false, the rule will always apply. For subclasses, the else property is \n+ * ignored.\n+ */\n+ elseFilter: false,\n+\n+ /**\n+ * Property: symbolizer\n+ * {Object} Symbolizer or hash of symbolizers for this rule. If hash of\n+ * symbolizers, keys are one or more of [\"Point\", \"Line\", \"Polygon\"]. The\n+ * latter if useful if it is required to style e.g. vertices of a line\n+ * with a point symbolizer. Note, however, that this is not implemented\n+ * yet in OpenLayers, but it is the way how symbolizers are defined in\n+ * SLD.\n+ */\n+ symbolizer: null,\n+\n+ /**\n+ * Property: symbolizers\n+ * {Array} Collection of symbolizers associated with this rule. If \n+ * provided at construction, the symbolizers array has precedence\n+ * over the deprecated symbolizer property. Note that multiple \n+ * symbolizers are not currently supported by the vector renderers.\n+ * Rules with multiple symbolizers are currently only useful for\n+ * maintaining elements in an SLD document.\n+ */\n+ symbolizers: null,\n+\n+ /**\n+ * APIProperty: minScaleDenominator\n+ * {Number} or {String} minimum scale at which to draw the feature.\n+ * In the case of a String, this can be a combination of text and\n+ * propertyNames in the form \"literal ${propertyName}\"\n+ */\n+ minScaleDenominator: null,\n+\n+ /**\n+ * APIProperty: maxScaleDenominator\n+ * {Number} or {String} maximum scale at which to draw the feature.\n+ * In the case of a String, this can be a combination of text and\n+ * propertyNames in the form \"literal ${propertyName}\"\n+ */\n+ maxScaleDenominator: null,\n+\n+ /** \n+ * Constructor: OpenLayers.Rule\n+ * Creates a Rule.\n *\n * Parameters:\n- * scale - {Float} Ratio of the new distance from the origin to the old\n- * distance from the origin. A scale of 2 doubles the\n- * distance between the point and origin.\n- * origin - {} Point of origin for resizing\n- * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.\n+ * options - {Object} An optional object with properties to set on the\n+ * rule\n * \n * Returns:\n- * {} - The current geometry. \n+ * {}\n */\n- resize: function(scale, origin, ratio) {\n- ratio = (ratio == undefined) ? 1 : ratio;\n- this.x = origin.x + (scale * ratio * (this.x - origin.x));\n- this.y = origin.y + (scale * (this.y - origin.y));\n- this.clearBounds();\n- return this;\n+ initialize: function(options) {\n+ this.symbolizer = {};\n+ OpenLayers.Util.extend(this, options);\n+ if (this.symbolizers) {\n+ delete this.symbolizer;\n+ }\n+ this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + \"_\");\n+ },\n+\n+ /** \n+ * APIMethod: destroy\n+ * nullify references to prevent circular references and memory leaks\n+ */\n+ destroy: function() {\n+ for (var i in this.symbolizer) {\n+ this.symbolizer[i] = null;\n+ }\n+ this.symbolizer = null;\n+ delete this.symbolizers;\n },\n \n /**\n- * APIMethod: intersects\n- * Determine if the input geometry intersects this one.\n- *\n+ * APIMethod: evaluate\n+ * evaluates this rule for a specific feature\n+ * \n * Parameters:\n- * geometry - {} Any type of geometry.\n- *\n+ * feature - {} feature to apply the rule to.\n+ * \n * Returns:\n- * {Boolean} The input geometry intersects this one.\n+ * {Boolean} true if the rule applies, false if it does not.\n+ * This rule is the default rule and always returns true.\n */\n- intersects: function(geometry) {\n- var intersect = false;\n- if (geometry.CLASS_NAME == \"OpenLayers.Geometry.Point\") {\n- intersect = this.equals(geometry);\n- } else {\n- intersect = geometry.intersects(this);\n+ evaluate: function(feature) {\n+ var context = this.getContext(feature);\n+ var applies = true;\n+\n+ if (this.minScaleDenominator || this.maxScaleDenominator) {\n+ var scale = feature.layer.map.getScale();\n }\n- return intersect;\n+\n+ // check if within minScale/maxScale bounds\n+ if (this.minScaleDenominator) {\n+ applies = scale >= OpenLayers.Style.createLiteral(\n+ this.minScaleDenominator, context);\n+ }\n+ if (applies && this.maxScaleDenominator) {\n+ applies = scale < OpenLayers.Style.createLiteral(\n+ this.maxScaleDenominator, context);\n+ }\n+\n+ // check if optional filter applies\n+ if (applies && this.filter) {\n+ // feature id filters get the feature, others get the context\n+ if (this.filter.CLASS_NAME == \"OpenLayers.Filter.FeatureId\") {\n+ applies = this.filter.evaluate(feature);\n+ } else {\n+ applies = this.filter.evaluate(context);\n+ }\n+ }\n+\n+ return applies;\n },\n \n /**\n- * APIMethod: transform\n- * Translate the x,y properties of the point from source to dest.\n+ * Method: getContext\n+ * Gets the context for evaluating this rule\n * \n- * Parameters:\n- * source - {} \n- * dest - {}\n+ * Paramters:\n+ * feature - {} feature to take the context from if\n+ * none is specified.\n+ */\n+ getContext: function(feature) {\n+ var context = this.context;\n+ if (!context) {\n+ context = feature.attributes || feature.data;\n+ }\n+ if (typeof this.context == \"function\") {\n+ context = this.context(feature);\n+ }\n+ return context;\n+ },\n+\n+ /**\n+ * APIMethod: clone\n+ * Clones this rule.\n * \n * Returns:\n- * {} \n+ * {} Clone of this rule.\n */\n- transform: function(source, dest) {\n- if ((source && dest)) {\n- OpenLayers.Projection.transform(\n- this, source, dest);\n- this.bounds = null;\n+ clone: function() {\n+ var options = OpenLayers.Util.extend({}, this);\n+ if (this.symbolizers) {\n+ // clone symbolizers\n+ var len = this.symbolizers.length;\n+ options.symbolizers = new Array(len);\n+ for (var i = 0; i < len; ++i) {\n+ options.symbolizers[i] = this.symbolizers[i].clone();\n+ }\n+ } else {\n+ // clone symbolizer\n+ options.symbolizer = {};\n+ var value, type;\n+ for (var key in this.symbolizer) {\n+ value = this.symbolizer[key];\n+ type = typeof value;\n+ if (type === \"object\") {\n+ options.symbolizer[key] = OpenLayers.Util.extend({}, value);\n+ } else if (type === \"string\") {\n+ options.symbolizer[key] = value;\n+ }\n+ }\n }\n- return this;\n+ // clone filter\n+ options.filter = this.filter && this.filter.clone();\n+ // clone context\n+ options.context = this.context && OpenLayers.Util.extend({}, this.context);\n+ return new OpenLayers.Rule(options);\n },\n \n+ CLASS_NAME: \"OpenLayers.Rule\"\n+});\n+/* ======================================================================\n+ OpenLayers/Symbolizer.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.Symbolizer\n+ * Base class representing a symbolizer used for feature rendering.\n+ */\n+OpenLayers.Symbolizer = OpenLayers.Class({\n+\n+\n /**\n- * APIMethod: getVertices\n- * Return a list of all points in this geometry.\n+ * APIProperty: zIndex\n+ * {Number} The zIndex determines the rendering order for a symbolizer.\n+ * Symbolizers with larger zIndex values are rendered over symbolizers\n+ * with smaller zIndex values. Default is 0.\n+ */\n+ zIndex: 0,\n+\n+ /**\n+ * Constructor: OpenLayers.Symbolizer\n+ * Instances of this class are not useful. See one of the subclasses.\n *\n * Parameters:\n- * nodes - {Boolean} For lines, only return vertices that are\n- * endpoints. If false, for lines, only vertices that are not\n- * endpoints will be returned. If not provided, all vertices will\n- * be returned.\n+ * config - {Object} An object containing properties to be set on the \n+ * symbolizer. Any documented symbolizer property can be set at \n+ * construction.\n *\n * Returns:\n- * {Array} A list of all vertices in the geometry.\n+ * A new symbolizer.\n */\n- getVertices: function(nodes) {\n- return [this];\n+ initialize: function(config) {\n+ OpenLayers.Util.extend(this, config);\n },\n \n- CLASS_NAME: \"OpenLayers.Geometry.Point\"\n+ /** \n+ * APIMethod: clone\n+ * Create a copy of this symbolizer.\n+ *\n+ * Returns a symbolizer of the same type with the same properties.\n+ */\n+ clone: function() {\n+ var Type = eval(this.CLASS_NAME);\n+ return new Type(OpenLayers.Util.extend({}, this));\n+ },\n+\n+ CLASS_NAME: \"OpenLayers.Symbolizer\"\n+\n });\n+\n /* ======================================================================\n- OpenLayers/Geometry/Collection.js\n+ OpenLayers/Symbolizer/Point.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/Geometry.js\n+ * @requires OpenLayers/Symbolizer.js\n */\n \n /**\n- * Class: OpenLayers.Geometry.Collection\n- * A Collection is exactly what it sounds like: A collection of different \n- * Geometries. These are stored in the local parameter (which\n- * can be passed as a parameter to the constructor). \n- * \n- * As new geometries are added to the collection, they are NOT cloned. \n- * When removing geometries, they need to be specified by reference (ie you \n- * have to pass in the *exact* geometry to be removed).\n- * \n- * The and functions here merely iterate through\n- * the components, summing their respective areas and lengths.\n- *\n- * Create a new instance with the constructor.\n- *\n- * Inherits from:\n- * - \n+ * Class: OpenLayers.Symbolizer.Point\n+ * A symbolizer used to render point features.\n */\n-OpenLayers.Geometry.Collection = OpenLayers.Class(OpenLayers.Geometry, {\n+OpenLayers.Symbolizer.Point = OpenLayers.Class(OpenLayers.Symbolizer, {\n \n /**\n- * APIProperty: components\n- * {Array()} The component parts of this geometry\n+ * APIProperty: strokeColor\n+ * {String} Color for line stroke. This is a RGB hex value (e.g. \"#ff0000\"\n+ * for red).\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- components: null,\n \n /**\n- * Property: componentTypes\n- * {Array(String)} An array of class names representing the types of\n- * components that the collection can include. A null value means the\n- * component types are not restricted.\n+ * APIProperty: strokeOpacity\n+ * {Number} Stroke opacity (0-1).\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- componentTypes: null,\n \n /**\n- * Constructor: OpenLayers.Geometry.Collection\n- * Creates a Geometry Collection -- a list of geoms.\n- *\n- * Parameters: \n- * components - {Array()} Optional array of geometries\n- *\n+ * APIProperty: strokeWidth\n+ * {Number} Pixel stroke width.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- initialize: function(components) {\n- OpenLayers.Geometry.prototype.initialize.apply(this, arguments);\n- this.components = [];\n- if (components != null) {\n- this.addComponents(components);\n- }\n- },\n \n /**\n- * APIMethod: destroy\n- * Destroy this geometry.\n+ * APIProperty: strokeLinecap\n+ * {String} Stroke cap type (\"butt\", \"round\", or \"square\").\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- destroy: function() {\n- this.components.length = 0;\n- this.components = null;\n- OpenLayers.Geometry.prototype.destroy.apply(this, arguments);\n- },\n \n /**\n- * APIMethod: clone\n- * Clone this geometry.\n- *\n- * Returns:\n- * {} An exact clone of this collection\n+ * Property: strokeDashstyle\n+ * {String} Stroke dash style according to the SLD spec. Note that the\n+ * OpenLayers values for strokeDashstyle (\"dot\", \"dash\", \"dashdot\",\n+ * \"longdash\", \"longdashdot\", or \"solid\") will not work in SLD, but\n+ * most SLD patterns will render correctly in OpenLayers.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- clone: function() {\n- var geometry = eval(\"new \" + this.CLASS_NAME + \"()\");\n- for (var i = 0, len = this.components.length; i < len; i++) {\n- geometry.addComponent(this.components[i].clone());\n- }\n \n- // catch any randomly tagged-on properties\n- OpenLayers.Util.applyDefaults(geometry, this);\n+ /**\n+ * APIProperty: fillColor\n+ * {String} RGB hex fill color (e.g. \"#ff0000\" for red).\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n \n- return geometry;\n- },\n+ /**\n+ * APIProperty: fillOpacity\n+ * {Number} Fill opacity (0-1).\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n \n /**\n- * Method: getComponentsString\n- * Get a string representing the components for this collection\n+ * APIProperty: pointRadius\n+ * {Number} Pixel point radius.\n * \n- * Returns:\n- * {String} A string representation of the components of this geometry\n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- getComponentsString: function() {\n- var strings = [];\n- for (var i = 0, len = this.components.length; i < len; i++) {\n- strings.push(this.components[i].toShortString());\n- }\n- return strings.join(\",\");\n- },\n \n /**\n- * APIMethod: calculateBounds\n- * Recalculate the bounds by iterating through the components and \n- * calling calling extendBounds() on each item.\n+ * APIProperty: externalGraphic\n+ * {String} Url to an external graphic that will be used for rendering \n+ * points.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- calculateBounds: function() {\n- this.bounds = null;\n- var bounds = new OpenLayers.Bounds();\n- var components = this.components;\n- if (components) {\n- for (var i = 0, len = components.length; i < len; i++) {\n- bounds.extend(components[i].getBounds());\n- }\n- }\n- // to preserve old behavior, we only set bounds if non-null\n- // in the future, we could add bounds.isEmpty()\n- if (bounds.left != null && bounds.bottom != null &&\n- bounds.right != null && bounds.top != null) {\n- this.setBounds(bounds);\n- }\n- },\n \n /**\n- * APIMethod: addComponents\n- * Add components to this geometry.\n- *\n- * Parameters:\n- * components - {Array()} An array of geometries to add\n+ * APIProperty: graphicWidth\n+ * {Number} Pixel width for sizing an external graphic.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- addComponents: function(components) {\n- if (!(OpenLayers.Util.isArray(components))) {\n- components = [components];\n- }\n- for (var i = 0, len = components.length; i < len; i++) {\n- this.addComponent(components[i]);\n- }\n- },\n \n /**\n- * Method: addComponent\n- * Add a new component (geometry) to the collection. If this.componentTypes\n- * is set, then the component class name must be in the componentTypes array.\n- *\n- * The bounds cache is reset.\n+ * APIProperty: graphicHeight\n+ * {Number} Pixel height for sizing an external graphic.\n * \n- * Parameters:\n- * component - {} A geometry to add\n- * index - {int} Optional index into the array to insert the component\n- *\n- * Returns:\n- * {Boolean} The component geometry was successfully added\n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- addComponent: function(component, index) {\n- var added = false;\n- if (component) {\n- if (this.componentTypes == null ||\n- (OpenLayers.Util.indexOf(this.componentTypes,\n- component.CLASS_NAME) > -1)) {\n \n- if (index != null && (index < this.components.length)) {\n- var components1 = this.components.slice(0, index);\n- var components2 = this.components.slice(index,\n- this.components.length);\n- components1.push(component);\n- this.components = components1.concat(components2);\n- } else {\n- this.components.push(component);\n- }\n- component.parent = this;\n- this.clearBounds();\n- added = true;\n- }\n- }\n- return added;\n- },\n+ /**\n+ * APIProperty: graphicOpacity\n+ * {Number} Opacity (0-1) for an external graphic.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n \n /**\n- * APIMethod: removeComponents\n- * Remove components from this geometry.\n- *\n- * Parameters:\n- * components - {Array()} The components to be removed\n- *\n- * Returns: \n- * {Boolean} A component was removed.\n+ * APIProperty: graphicXOffset\n+ * {Number} Pixel offset along the positive x axis for displacing an \n+ * external graphic.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- removeComponents: function(components) {\n- var removed = false;\n \n- if (!(OpenLayers.Util.isArray(components))) {\n- components = [components];\n- }\n- for (var i = components.length - 1; i >= 0; --i) {\n- removed = this.removeComponent(components[i]) || removed;\n- }\n- return removed;\n- },\n+ /**\n+ * APIProperty: graphicYOffset\n+ * {Number} Pixel offset along the positive y axis for displacing an \n+ * external graphic.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n \n /**\n- * Method: removeComponent\n- * Remove a component from this geometry.\n+ * APIProperty: rotation\n+ * {Number} The rotation of a graphic in the clockwise direction about its \n+ * center point (or any point off center as specified by \n+ * and ).\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n+\n+ /**\n+ * APIProperty: graphicName\n+ * {String} Named graphic to use when rendering points. Supported values \n+ * include \"circle\", \"square\", \"star\", \"x\", \"cross\", and \"triangle\".\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n+\n+ /**\n+ * Constructor: OpenLayers.Symbolizer.Point\n+ * Create a symbolizer for rendering points.\n *\n * Parameters:\n- * component - {} \n+ * config - {Object} An object containing properties to be set on the \n+ * symbolizer. Any documented symbolizer property can be set at \n+ * construction.\n *\n- * Returns: \n- * {Boolean} The component was removed.\n+ * Returns:\n+ * A new point symbolizer.\n */\n- removeComponent: function(component) {\n+ initialize: function(config) {\n+ OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);\n+ },\n \n- OpenLayers.Util.removeItem(this.components, component);\n+ CLASS_NAME: \"OpenLayers.Symbolizer.Point\"\n \n- // clearBounds() so that it gets recalculated on the next call\n- // to this.getBounds();\n- this.clearBounds();\n- return true;\n- },\n+});\n+\n+/* ======================================================================\n+ OpenLayers/Symbolizer/Line.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/Symbolizer.js\n+ */\n+\n+/**\n+ * Class: OpenLayers.Symbolizer.Line\n+ * A symbolizer used to render line features.\n+ */\n+OpenLayers.Symbolizer.Line = OpenLayers.Class(OpenLayers.Symbolizer, {\n \n /**\n- * APIMethod: getLength\n- * Calculate the length of this geometry\n- *\n- * Returns:\n- * {Float} The length of the geometry\n+ * APIProperty: strokeColor\n+ * {String} Color for line stroke. This is a RGB hex value (e.g. \"#ff0000\"\n+ * for red). \n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- getLength: function() {\n- var length = 0.0;\n- for (var i = 0, len = this.components.length; i < len; i++) {\n- length += this.components[i].getLength();\n- }\n- return length;\n- },\n \n /**\n- * APIMethod: getArea\n- * Calculate the area of this geometry. Note how this function is overridden\n- * in .\n- *\n- * Returns:\n- * {Float} The area of the collection by summing its parts\n+ * APIProperty: strokeOpacity\n+ * {Number} Stroke opacity (0-1).\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- getArea: function() {\n- var area = 0.0;\n- for (var i = 0, len = this.components.length; i < len; i++) {\n- area += this.components[i].getArea();\n- }\n- return area;\n- },\n \n- /** \n- * APIMethod: getGeodesicArea\n- * Calculate the approximate area of the polygon were it projected onto\n- * the earth.\n- *\n- * Parameters:\n- * projection - {} The spatial reference system\n- * for the geometry coordinates. If not provided, Geographic/WGS84 is\n- * assumed.\n+ /**\n+ * APIProperty: strokeWidth\n+ * {Number} Pixel stroke width.\n * \n- * Reference:\n- * Robert. G. Chamberlain and William H. Duquette, \"Some Algorithms for\n- * Polygons on a Sphere\", JPL Publication 07-03, Jet Propulsion\n- * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409\n- *\n- * Returns:\n- * {float} The approximate geodesic area of the geometry in square meters.\n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- getGeodesicArea: function(projection) {\n- var area = 0.0;\n- for (var i = 0, len = this.components.length; i < len; i++) {\n- area += this.components[i].getGeodesicArea(projection);\n- }\n- return area;\n- },\n \n /**\n- * APIMethod: getCentroid\n- *\n- * Compute the centroid for this geometry collection.\n+ * APIProperty: strokeLinecap\n+ * {String} Stroke cap type (\"butt\", \"round\", or \"square\").\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n+\n+ /**\n+ * Property: strokeDashstyle\n+ * {String} Stroke dash style according to the SLD spec. Note that the\n+ * OpenLayers values for strokeDashstyle (\"dot\", \"dash\", \"dashdot\",\n+ * \"longdash\", \"longdashdot\", or \"solid\") will not work in SLD, but\n+ * most SLD patterns will render correctly in OpenLayers.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n+\n+ /**\n+ * Constructor: OpenLayers.Symbolizer.Line\n+ * Create a symbolizer for rendering lines.\n *\n * Parameters:\n- * weighted - {Boolean} Perform the getCentroid computation recursively,\n- * returning an area weighted average of all geometries in this collection.\n+ * config - {Object} An object containing properties to be set on the \n+ * symbolizer. Any documented symbolizer property can be set at \n+ * construction.\n *\n * Returns:\n- * {} The centroid of the collection\n+ * A new line symbolizer.\n */\n- getCentroid: function(weighted) {\n- if (!weighted) {\n- return this.components.length && this.components[0].getCentroid();\n- }\n- var len = this.components.length;\n- if (!len) {\n- return false;\n- }\n+ initialize: function(config) {\n+ OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);\n+ },\n \n- var areas = [];\n- var centroids = [];\n- var areaSum = 0;\n- var minArea = Number.MAX_VALUE;\n- var component;\n- for (var i = 0; i < len; ++i) {\n- component = this.components[i];\n- var area = component.getArea();\n- var centroid = component.getCentroid(true);\n- if (isNaN(area) || isNaN(centroid.x) || isNaN(centroid.y)) {\n- continue;\n- }\n- areas.push(area);\n- areaSum += area;\n- minArea = (area < minArea && area > 0) ? area : minArea;\n- centroids.push(centroid);\n- }\n- len = areas.length;\n- if (areaSum === 0) {\n- // all the components in this collection have 0 area\n- // probably a collection of points -- weight all the points the same\n- for (var i = 0; i < len; ++i) {\n- areas[i] = 1;\n- }\n- areaSum = areas.length;\n- } else {\n- // normalize all the areas where the smallest area will get\n- // a value of 1\n- for (var i = 0; i < len; ++i) {\n- areas[i] /= minArea;\n- }\n- areaSum /= minArea;\n- }\n+ CLASS_NAME: \"OpenLayers.Symbolizer.Line\"\n \n- var xSum = 0,\n- ySum = 0,\n- centroid, area;\n- for (var i = 0; i < len; ++i) {\n- centroid = centroids[i];\n- area = areas[i];\n- xSum += centroid.x * area;\n- ySum += centroid.y * area;\n- }\n+});\n \n- return new OpenLayers.Geometry.Point(xSum / areaSum, ySum / areaSum);\n- },\n+/* ======================================================================\n+ OpenLayers/Symbolizer/Polygon.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/Symbolizer.js\n+ */\n+\n+/**\n+ * Class: OpenLayers.Symbolizer.Polygon\n+ * A symbolizer used to render line features.\n+ */\n+OpenLayers.Symbolizer.Polygon = OpenLayers.Class(OpenLayers.Symbolizer, {\n \n /**\n- * APIMethod: getGeodesicLength\n- * Calculate the approximate length of the geometry were it projected onto\n- * the earth.\n- *\n- * projection - {} The spatial reference system\n- * for the geometry coordinates. If not provided, Geographic/WGS84 is\n- * assumed.\n+ * APIProperty: strokeColor\n+ * {String} Color for line stroke. This is a RGB hex value (e.g. \"#ff0000\"\n+ * for red).\n * \n- * Returns:\n- * {Float} The appoximate geodesic length of the geometry in meters.\n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- getGeodesicLength: function(projection) {\n- var length = 0.0;\n- for (var i = 0, len = this.components.length; i < len; i++) {\n- length += this.components[i].getGeodesicLength(projection);\n- }\n- return length;\n- },\n \n /**\n- * APIMethod: move\n- * Moves a geometry by the given displacement along positive x and y axes.\n- * This modifies the position of the geometry and clears the cached\n- * bounds.\n- *\n- * Parameters:\n- * x - {Float} Distance to move geometry in positive x direction. \n- * y - {Float} Distance to move geometry in positive y direction.\n+ * APIProperty: strokeOpacity\n+ * {Number} Stroke opacity (0-1).\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- move: function(x, y) {\n- for (var i = 0, len = this.components.length; i < len; i++) {\n- this.components[i].move(x, y);\n- }\n- },\n \n /**\n- * APIMethod: rotate\n- * Rotate a geometry around some origin\n- *\n- * Parameters:\n- * angle - {Float} Rotation angle in degrees (measured counterclockwise\n- * from the positive x-axis)\n- * origin - {} Center point for the rotation\n+ * APIProperty: strokeWidth\n+ * {Number} Pixel stroke width.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- rotate: function(angle, origin) {\n- for (var i = 0, len = this.components.length; i < len; ++i) {\n- this.components[i].rotate(angle, origin);\n- }\n- },\n \n /**\n- * APIMethod: resize\n- * Resize a geometry relative to some origin. Use this method to apply\n- * a uniform scaling to a geometry.\n- *\n- * Parameters:\n- * scale - {Float} Factor by which to scale the geometry. A scale of 2\n- * doubles the size of the geometry in each dimension\n- * (lines, for example, will be twice as long, and polygons\n- * will have four times the area).\n- * origin - {} Point of origin for resizing\n- * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.\n+ * APIProperty: strokeLinecap\n+ * {String} Stroke cap type (\"butt\", \"round\", or \"square\").\n * \n- * Returns:\n- * {} - The current geometry. \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- resize: function(scale, origin, ratio) {\n- for (var i = 0; i < this.components.length; ++i) {\n- this.components[i].resize(scale, origin, ratio);\n- }\n- return this;\n- },\n \n /**\n- * APIMethod: distanceTo\n- * Calculate the closest distance between two geometries (on the x-y plane).\n+ * Property: strokeDashstyle\n+ * {String} Stroke dash style according to the SLD spec. Note that the\n+ * OpenLayers values for strokeDashstyle (\"dot\", \"dash\", \"dashdot\",\n+ * \"longdash\", \"longdashdot\", or \"solid\") will not work in SLD, but\n+ * most SLD patterns will render correctly in OpenLayers.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n+\n+ /**\n+ * APIProperty: fillColor\n+ * {String} RGB hex fill color (e.g. \"#ff0000\" for red).\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n+\n+ /**\n+ * APIProperty: fillOpacity\n+ * {Number} Fill opacity (0-1).\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n+\n+ /**\n+ * Constructor: OpenLayers.Symbolizer.Polygon\n+ * Create a symbolizer for rendering polygons.\n *\n * Parameters:\n- * geometry - {} The target geometry.\n- * options - {Object} Optional properties for configuring the distance\n- * calculation.\n- *\n- * Valid options:\n- * details - {Boolean} Return details from the distance calculation.\n- * Default is false.\n- * edge - {Boolean} Calculate the distance from this geometry to the\n- * nearest edge of the target geometry. Default is true. If true,\n- * calling distanceTo from a geometry that is wholly contained within\n- * the target will result in a non-zero distance. If false, whenever\n- * geometries intersect, calling distanceTo will return 0. If false,\n- * details cannot be returned.\n+ * config - {Object} An object containing properties to be set on the \n+ * symbolizer. Any documented symbolizer property can be set at \n+ * construction.\n *\n * Returns:\n- * {Number | Object} The distance between this geometry and the target.\n- * If details is true, the return will be an object with distance,\n- * x0, y0, x1, and y1 properties. The x0 and y0 properties represent\n- * the coordinates of the closest point on this geometry. The x1 and y1\n- * properties represent the coordinates of the closest point on the\n- * target geometry.\n+ * A new polygon symbolizer.\n */\n- distanceTo: function(geometry, options) {\n- var edge = !(options && options.edge === false);\n- var details = edge && options && options.details;\n- var result, best, distance;\n- var min = Number.POSITIVE_INFINITY;\n- for (var i = 0, len = this.components.length; i < len; ++i) {\n- result = this.components[i].distanceTo(geometry, options);\n- distance = details ? result.distance : result;\n- if (distance < min) {\n- min = distance;\n- best = result;\n- if (min == 0) {\n- break;\n- }\n- }\n- }\n- return best;\n+ initialize: function(config) {\n+ OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);\n },\n \n+ CLASS_NAME: \"OpenLayers.Symbolizer.Polygon\"\n+\n+});\n+\n+/* ======================================================================\n+ OpenLayers/Symbolizer/Text.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/Symbolizer.js\n+ */\n+\n+/**\n+ * Class: OpenLayers.Symbolizer.Text\n+ * A symbolizer used to render text labels for features.\n+ */\n+OpenLayers.Symbolizer.Text = OpenLayers.Class(OpenLayers.Symbolizer, {\n+\n /** \n- * APIMethod: equals\n- * Determine whether another geometry is equivalent to this one. Geometries\n- * are considered equivalent if all components have the same coordinates.\n+ * APIProperty: label\n+ * {String} The text for the label.\n * \n- * Parameters:\n- * geometry - {} The geometry to test. \n- *\n- * Returns:\n- * {Boolean} The supplied geometry is equivalent to this geometry.\n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- equals: function(geometry) {\n- var equivalent = true;\n- if (!geometry || !geometry.CLASS_NAME ||\n- (this.CLASS_NAME != geometry.CLASS_NAME)) {\n- equivalent = false;\n- } else if (!(OpenLayers.Util.isArray(geometry.components)) ||\n- (geometry.components.length != this.components.length)) {\n- equivalent = false;\n- } else {\n- for (var i = 0, len = this.components.length; i < len; ++i) {\n- if (!this.components[i].equals(geometry.components[i])) {\n- equivalent = false;\n- break;\n- }\n- }\n- }\n- return equivalent;\n- },\n \n- /**\n- * APIMethod: transform\n- * Reproject the components geometry from source to dest.\n+ /** \n+ * APIProperty: fontFamily\n+ * {String} The font family for the label.\n * \n- * Parameters:\n- * source - {} \n- * dest - {}\n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n+\n+ /** \n+ * APIProperty: fontSize\n+ * {String} The font size for the label.\n * \n- * Returns:\n- * {} \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n+ */\n+\n+ /** \n+ * APIProperty: fontWeight\n+ * {String} The font weight for the label.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- transform: function(source, dest) {\n- if (source && dest) {\n- for (var i = 0, len = this.components.length; i < len; i++) {\n- var component = this.components[i];\n- component.transform(source, dest);\n- }\n- this.bounds = null;\n- }\n- return this;\n- },\n \n /**\n- * APIMethod: intersects\n- * Determine if the input geometry intersects this one.\n- *\n- * Parameters:\n- * geometry - {} Any type of geometry.\n- *\n- * Returns:\n- * {Boolean} The input geometry intersects this one.\n+ * Property: fontStyle\n+ * {String} The font style for the label.\n+ * \n+ * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults.\n */\n- intersects: function(geometry) {\n- var intersect = false;\n- for (var i = 0, len = this.components.length; i < len; ++i) {\n- intersect = geometry.intersects(this.components[i]);\n- if (intersect) {\n- break;\n- }\n- }\n- return intersect;\n- },\n \n /**\n- * APIMethod: getVertices\n- * Return a list of all points in this geometry.\n+ * Constructor: OpenLayers.Symbolizer.Text\n+ * Create a symbolizer for rendering text labels.\n *\n * Parameters:\n- * nodes - {Boolean} For lines, only return vertices that are\n- * endpoints. If false, for lines, only vertices that are not\n- * endpoints will be returned. If not provided, all vertices will\n- * be returned.\n+ * config - {Object} An object containing properties to be set on the \n+ * symbolizer. Any documented symbolizer property can be set at \n+ * construction.\n *\n * Returns:\n- * {Array} A list of all vertices in the geometry.\n+ * A new text symbolizer.\n */\n- getVertices: function(nodes) {\n- var vertices = [];\n- for (var i = 0, len = this.components.length; i < len; ++i) {\n- Array.prototype.push.apply(\n- vertices, this.components[i].getVertices(nodes)\n- );\n- }\n- return vertices;\n+ initialize: function(config) {\n+ OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);\n },\n \n+ CLASS_NAME: \"OpenLayers.Symbolizer.Text\"\n \n- CLASS_NAME: \"OpenLayers.Geometry.Collection\"\n });\n+\n /* ======================================================================\n- OpenLayers/Geometry/MultiPoint.js\n+ OpenLayers/Symbolizer/Raster.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/Geometry/Collection.js\n- * @requires OpenLayers/Geometry/Point.js\n+ * @requires OpenLayers/Symbolizer.js\n */\n \n /**\n- * Class: OpenLayers.Geometry.MultiPoint\n- * MultiPoint is a collection of Points. Create a new instance with the\n- * constructor.\n- *\n- * Inherits from:\n- * - \n- * - \n+ * Class: OpenLayers.Symbolizer.Raster\n+ * A symbolizer used to render raster images.\n */\n-OpenLayers.Geometry.MultiPoint = OpenLayers.Class(\n- OpenLayers.Geometry.Collection, {\n-\n- /**\n- * Property: componentTypes\n- * {Array(String)} An array of class names representing the types of\n- * components that the collection can include. A null value means the\n- * component types are not restricted.\n- */\n- componentTypes: [\"OpenLayers.Geometry.Point\"],\n-\n- /**\n- * Constructor: OpenLayers.Geometry.MultiPoint\n- * Create a new MultiPoint Geometry\n- *\n- * Parameters:\n- * components - {Array()} \n- *\n- * Returns:\n- * {}\n- */\n+OpenLayers.Symbolizer.Raster = OpenLayers.Class(OpenLayers.Symbolizer, {\n \n- /**\n- * APIMethod: addPoint\n- * Wrapper for \n- *\n- * Parameters:\n- * point - {} Point to be added\n- * index - {Integer} Optional index\n- */\n- addPoint: function(point, index) {\n- this.addComponent(point, index);\n- },\n+ /**\n+ * Constructor: OpenLayers.Symbolizer.Raster\n+ * Create a symbolizer for rendering rasters.\n+ *\n+ * Parameters:\n+ * config - {Object} An object containing properties to be set on the \n+ * symbolizer. Any documented symbolizer property can be set at \n+ * construction.\n+ *\n+ * Returns:\n+ * A new raster symbolizer.\n+ */\n+ initialize: function(config) {\n+ OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments);\n+ },\n \n- /**\n- * APIMethod: removePoint\n- * Wrapper for \n- *\n- * Parameters:\n- * point - {} Point to be removed\n- */\n- removePoint: function(point) {\n- this.removeComponent(point);\n- },\n+ CLASS_NAME: \"OpenLayers.Symbolizer.Raster\"\n \n- CLASS_NAME: \"OpenLayers.Geometry.MultiPoint\"\n- });\n+});\n /* ======================================================================\n- OpenLayers/Geometry/Curve.js\n+ OpenLayers/Style2.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/Geometry/MultiPoint.js\n+ * @requires OpenLayers/BaseTypes/Class.js\n+ * @requires OpenLayers/Rule.js\n+ * @requires OpenLayers/Symbolizer/Point.js\n+ * @requires OpenLayers/Symbolizer/Line.js\n+ * @requires OpenLayers/Symbolizer/Polygon.js\n+ * @requires OpenLayers/Symbolizer/Text.js\n+ * @requires OpenLayers/Symbolizer/Raster.js\n */\n \n /**\n- * Class: OpenLayers.Geometry.Curve\n- * A Curve is a MultiPoint, whose points are assumed to be connected. To \n- * this end, we provide a \"getLength()\" function, which iterates through \n- * the points, summing the distances between them. \n- * \n- * Inherits: \n- * - \n+ * Class: OpenLayers.Style2\n+ * This class represents a collection of rules for rendering features.\n */\n-OpenLayers.Geometry.Curve = OpenLayers.Class(OpenLayers.Geometry.MultiPoint, {\n+OpenLayers.Style2 = OpenLayers.Class({\n \n /**\n- * Property: componentTypes\n- * {Array(String)} An array of class names representing the types of \n- * components that the collection can include. A null \n- * value means the component types are not restricted.\n+ * Property: id\n+ * {String} A unique id for this session.\n */\n- componentTypes: [\"OpenLayers.Geometry.Point\"],\n+ id: null,\n \n /**\n- * Constructor: OpenLayers.Geometry.Curve\n- * \n- * Parameters:\n- * point - {Array()}\n+ * APIProperty: name\n+ * {String} Style identifier.\n */\n+ name: null,\n \n /**\n- * APIMethod: getLength\n- * \n+ * APIProperty: title\n+ * {String} Title of this style.\n+ */\n+ title: null,\n+\n+ /**\n+ * APIProperty: description\n+ * {String} Description of this style.\n+ */\n+ description: null,\n+\n+ /**\n+ * APIProperty: layerName\n+ * {} Name of the layer that this style belongs to, usually\n+ * according to the NamedLayer attribute of an SLD document.\n+ */\n+ layerName: null,\n+\n+ /**\n+ * APIProperty: isDefault\n+ * {Boolean}\n+ */\n+ isDefault: false,\n+\n+ /** \n+ * APIProperty: rules \n+ * {Array()} Collection of rendering rules.\n+ */\n+ rules: null,\n+\n+ /** \n+ * Constructor: OpenLayers.Style2\n+ * Creates a style representing a collection of rendering rules.\n+ *\n+ * Parameters:\n+ * config - {Object} An object containing properties to be set on the \n+ * style. Any documented properties may be set at construction.\n+ *\n * Returns:\n- * {Float} The length of the curve\n+ * {} A new style object.\n */\n- getLength: function() {\n- var length = 0.0;\n- if (this.components && (this.components.length > 1)) {\n- for (var i = 1, len = this.components.length; i < len; i++) {\n- length += this.components[i - 1].distanceTo(this.components[i]);\n- }\n+ initialize: function(config) {\n+ OpenLayers.Util.extend(this, config);\n+ this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + \"_\");\n+ },\n+\n+ /** \n+ * APIMethod: destroy\n+ * nullify references to prevent circular references and memory leaks\n+ */\n+ destroy: function() {\n+ for (var i = 0, len = this.rules.length; i < len; i++) {\n+ this.rules[i].destroy();\n }\n- return length;\n+ delete this.rules;\n },\n \n /**\n- * APIMethod: getGeodesicLength\n- * Calculate the approximate length of the geometry were it projected onto\n- * the earth.\n- *\n- * projection - {} The spatial reference system\n- * for the geometry coordinates. If not provided, Geographic/WGS84 is\n- * assumed.\n+ * APIMethod: clone\n+ * Clones this style.\n * \n * Returns:\n- * {Float} The appoximate geodesic length of the geometry in meters.\n+ * {} Clone of this style.\n */\n- getGeodesicLength: function(projection) {\n- var geom = this; // so we can work with a clone if needed\n- if (projection) {\n- var gg = new OpenLayers.Projection(\"EPSG:4326\");\n- if (!gg.equals(projection)) {\n- geom = this.clone().transform(projection, gg);\n- }\n- }\n- var length = 0.0;\n- if (geom.components && (geom.components.length > 1)) {\n- var p1, p2;\n- for (var i = 1, len = geom.components.length; i < len; i++) {\n- p1 = geom.components[i - 1];\n- p2 = geom.components[i];\n- // this returns km and requires lon/lat properties\n- length += OpenLayers.Util.distVincenty({\n- lon: p1.x,\n- lat: p1.y\n- }, {\n- lon: p2.x,\n- lat: p2.y\n- });\n+ clone: function() {\n+ var config = OpenLayers.Util.extend({}, this);\n+ // clone rules\n+ if (this.rules) {\n+ config.rules = [];\n+ for (var i = 0, len = this.rules.length; i < len; ++i) {\n+ config.rules.push(this.rules[i].clone());\n }\n }\n- // convert to m\n- return length * 1000;\n+ return new OpenLayers.Style2(config);\n },\n \n- CLASS_NAME: \"OpenLayers.Geometry.Curve\"\n+ CLASS_NAME: \"OpenLayers.Style2\"\n });\n /* ======================================================================\n- OpenLayers/Geometry/LineString.js\n+ OpenLayers/Kinetic.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/Geometry/Curve.js\n+ * @requires OpenLayers/BaseTypes/Class.js\n+ * @requires OpenLayers/Animation.js\n */\n \n-/**\n- * Class: OpenLayers.Geometry.LineString\n- * A LineString is a Curve which, once two points have been added to it, can \n- * never be less than two points long.\n- * \n- * Inherits from:\n- * - \n- */\n-OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, {\n+OpenLayers.Kinetic = OpenLayers.Class({\n \n /**\n- * Constructor: OpenLayers.Geometry.LineString\n- * Create a new LineString geometry\n+ * Property: threshold\n+ * In most cases changing the threshold isn't needed.\n+ * In px/ms, default to 0.\n+ */\n+ threshold: 0,\n+\n+ /**\n+ * Property: deceleration\n+ * {Float} the deseleration in px/ms\u00b2, default to 0.0035.\n+ */\n+ deceleration: 0.0035,\n+\n+ /**\n+ * Property: nbPoints\n+ * {Integer} the number of points we use to calculate the kinetic\n+ * initial values.\n+ */\n+ nbPoints: 100,\n+\n+ /**\n+ * Property: delay\n+ * {Float} time to consider to calculate the kinetic initial values.\n+ * In ms, default to 200.\n+ */\n+ delay: 200,\n+\n+ /**\n+ * Property: points\n+ * List of points use to calculate the kinetic initial values.\n+ */\n+ points: undefined,\n+\n+ /**\n+ * Property: timerId\n+ * ID of the timer.\n+ */\n+ timerId: undefined,\n+\n+ /**\n+ * Constructor: OpenLayers.Kinetic\n *\n * Parameters:\n- * points - {Array()} An array of points used to\n- * generate the linestring\n- *\n+ * options - {Object}\n */\n+ initialize: function(options) {\n+ OpenLayers.Util.extend(this, options);\n+ },\n \n /**\n- * APIMethod: removeComponent\n- * Only allows removal of a point if there are three or more points in \n- * the linestring. (otherwise the result would be just a single point)\n- *\n- * Parameters: \n- * point - {} The point to be removed\n- *\n- * Returns: \n- * {Boolean} The component was removed.\n+ * Method: begin\n+ * Begins the dragging.\n */\n- removeComponent: function(point) {\n- var removed = this.components && (this.components.length > 2);\n- if (removed) {\n- OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,\n- arguments);\n- }\n- return removed;\n+ begin: function() {\n+ OpenLayers.Animation.stop(this.timerId);\n+ this.timerId = undefined;\n+ this.points = [];\n },\n \n /**\n- * APIMethod: intersects\n- * Test for instersection between two geometries. This is a cheapo\n- * implementation of the Bently-Ottmann algorigithm. It doesn't\n- * really keep track of a sweep line data structure. It is closer\n- * to the brute force method, except that segments are sorted and\n- * potential intersections are only calculated when bounding boxes\n- * intersect.\n+ * Method: update\n+ * Updates during the dragging.\n *\n * Parameters:\n- * geometry - {}\n- *\n- * Returns:\n- * {Boolean} The input geometry intersects this geometry.\n+ * xy - {} The new position.\n */\n- intersects: function(geometry) {\n- var intersect = false;\n- var type = geometry.CLASS_NAME;\n- if (type == \"OpenLayers.Geometry.LineString\" ||\n- type == \"OpenLayers.Geometry.LinearRing\" ||\n- type == \"OpenLayers.Geometry.Point\") {\n- var segs1 = this.getSortedSegments();\n- var segs2;\n- if (type == \"OpenLayers.Geometry.Point\") {\n- segs2 = [{\n- x1: geometry.x,\n- y1: geometry.y,\n- x2: geometry.x,\n- y2: geometry.y\n- }];\n- } else {\n- segs2 = geometry.getSortedSegments();\n- }\n- var seg1, seg1x1, seg1x2, seg1y1, seg1y2,\n- seg2, seg2y1, seg2y2;\n- // sweep right\n- outer: for (var i = 0, len = segs1.length; i < len; ++i) {\n- seg1 = segs1[i];\n- seg1x1 = seg1.x1;\n- seg1x2 = seg1.x2;\n- seg1y1 = seg1.y1;\n- seg1y2 = seg1.y2;\n- inner: for (var j = 0, jlen = segs2.length; j < jlen; ++j) {\n- seg2 = segs2[j];\n- if (seg2.x1 > seg1x2) {\n- // seg1 still left of seg2\n- break;\n- }\n- if (seg2.x2 < seg1x1) {\n- // seg2 still left of seg1\n- continue;\n- }\n- seg2y1 = seg2.y1;\n- seg2y2 = seg2.y2;\n- if (Math.min(seg2y1, seg2y2) > Math.max(seg1y1, seg1y2)) {\n- // seg2 above seg1\n- continue;\n- }\n- if (Math.max(seg2y1, seg2y2) < Math.min(seg1y1, seg1y2)) {\n- // seg2 below seg1\n- continue;\n- }\n- if (OpenLayers.Geometry.segmentsIntersect(seg1, seg2)) {\n- intersect = true;\n- break outer;\n- }\n- }\n- }\n- } else {\n- intersect = geometry.intersects(this);\n+ update: function(xy) {\n+ this.points.unshift({\n+ xy: xy,\n+ tick: new Date().getTime()\n+ });\n+ if (this.points.length > this.nbPoints) {\n+ this.points.pop();\n }\n- return intersect;\n },\n \n /**\n- * Method: getSortedSegments\n+ * Method: end\n+ * Ends the dragging, start the kinetic.\n+ *\n+ * Parameters:\n+ * xy - {} The last position.\n *\n * Returns:\n- * {Array} An array of segment objects. Segment objects have properties\n- * x1, y1, x2, and y2. The start point is represented by x1 and y1.\n- * The end point is represented by x2 and y2. Start and end are\n- * ordered so that x1 < x2.\n+ * {Object} An object with two properties: \"speed\", and \"theta\". The\n+ * \"speed\" and \"theta\" values are to be passed to the move \n+ * function when starting the animation.\n */\n- getSortedSegments: function() {\n- var numSeg = this.components.length - 1;\n- var segments = new Array(numSeg),\n- point1, point2;\n- for (var i = 0; i < numSeg; ++i) {\n- point1 = this.components[i];\n- point2 = this.components[i + 1];\n- if (point1.x < point2.x) {\n- segments[i] = {\n- x1: point1.x,\n- y1: point1.y,\n- x2: point2.x,\n- y2: point2.y\n- };\n- } else {\n- segments[i] = {\n- x1: point2.x,\n- y1: point2.y,\n- x2: point1.x,\n- y2: point1.y\n- };\n+ end: function(xy) {\n+ var last, now = new Date().getTime();\n+ for (var i = 0, l = this.points.length, point; i < l; i++) {\n+ point = this.points[i];\n+ if (now - point.tick > this.delay) {\n+ break;\n }\n+ last = point;\n }\n- // more efficient to define this somewhere static\n- function byX1(seg1, seg2) {\n- return seg1.x1 - seg2.x1;\n+ if (!last) {\n+ return;\n }\n- return segments.sort(byX1);\n+ var time = new Date().getTime() - last.tick;\n+ var dist = Math.sqrt(Math.pow(xy.x - last.xy.x, 2) +\n+ Math.pow(xy.y - last.xy.y, 2));\n+ var speed = dist / time;\n+ if (speed == 0 || speed < this.threshold) {\n+ return;\n+ }\n+ var theta = Math.asin((xy.y - last.xy.y) / dist);\n+ if (last.xy.x <= xy.x) {\n+ theta = Math.PI - theta;\n+ }\n+ return {\n+ speed: speed,\n+ theta: theta\n+ };\n },\n \n /**\n- * Method: splitWithSegment\n- * Split this geometry with the given segment.\n+ * Method: move\n+ * Launch the kinetic move pan.\n *\n * Parameters:\n- * seg - {Object} An object with x1, y1, x2, and y2 properties referencing\n- * segment endpoint coordinates.\n- * options - {Object} Properties of this object will be used to determine\n- * how the split is conducted.\n- *\n- * Valid options:\n- * edge - {Boolean} Allow splitting when only edges intersect. Default is\n- * true. If false, a vertex on the source segment must be within the\n- * tolerance distance of the intersection to be considered a split.\n- * tolerance - {Number} If a non-null value is provided, intersections\n- * within the tolerance distance of one of the source segment's\n- * endpoints will be assumed to occur at the endpoint.\n- *\n- * Returns:\n- * {Object} An object with *lines* and *points* properties. If the given\n- * segment intersects this linestring, the lines array will reference\n- * geometries that result from the split. The points array will contain\n- * all intersection points. Intersection points are sorted along the\n- * segment (in order from x1,y1 to x2,y2).\n+ * info - {Object} An object with two properties, \"speed\", and \"theta\".\n+ * These values are those returned from the \"end\" call.\n+ * callback - {Function} Function called on every step of the animation,\n+ * receives x, y (values to pan), end (is the last point).\n */\n- splitWithSegment: function(seg, options) {\n- var edge = !(options && options.edge === false);\n- var tolerance = options && options.tolerance;\n- var lines = [];\n- var verts = this.getVertices();\n- var points = [];\n- var intersections = [];\n- var split = false;\n- var vert1, vert2, point;\n- var node, vertex, target;\n- var interOptions = {\n- point: true,\n- tolerance: tolerance\n- };\n- var result = null;\n- for (var i = 0, stop = verts.length - 2; i <= stop; ++i) {\n- vert1 = verts[i];\n- points.push(vert1.clone());\n- vert2 = verts[i + 1];\n- target = {\n- x1: vert1.x,\n- y1: vert1.y,\n- x2: vert2.x,\n- y2: vert2.y\n- };\n- point = OpenLayers.Geometry.segmentsIntersect(\n- seg, target, interOptions\n- );\n- if (point instanceof OpenLayers.Geometry.Point) {\n- if ((point.x === seg.x1 && point.y === seg.y1) ||\n- (point.x === seg.x2 && point.y === seg.y2) ||\n- point.equals(vert1) || point.equals(vert2)) {\n- vertex = true;\n- } else {\n- vertex = false;\n- }\n- if (vertex || edge) {\n- // push intersections different than the previous\n- if (!point.equals(intersections[intersections.length - 1])) {\n- intersections.push(point.clone());\n- }\n- if (i === 0) {\n- if (point.equals(vert1)) {\n- continue;\n- }\n- }\n- if (point.equals(vert2)) {\n- continue;\n- }\n- split = true;\n- if (!point.equals(vert1)) {\n- points.push(point);\n- }\n- lines.push(new OpenLayers.Geometry.LineString(points));\n- points = [point.clone()];\n- }\n+ move: function(info, callback) {\n+ var v0 = info.speed;\n+ var fx = Math.cos(info.theta);\n+ var fy = -Math.sin(info.theta);\n+\n+ var initialTime = new Date().getTime();\n+\n+ var lastX = 0;\n+ var lastY = 0;\n+\n+ var timerCallback = function() {\n+ if (this.timerId == null) {\n+ return;\n }\n- }\n- if (split) {\n- points.push(vert2.clone());\n- lines.push(new OpenLayers.Geometry.LineString(points));\n- }\n- if (intersections.length > 0) {\n- // sort intersections along segment\n- var xDir = seg.x1 < seg.x2 ? 1 : -1;\n- var yDir = seg.y1 < seg.y2 ? 1 : -1;\n- result = {\n- lines: lines,\n- points: intersections.sort(function(p1, p2) {\n- return (xDir * p1.x - xDir * p2.x) || (yDir * p1.y - yDir * p2.y);\n- })\n- };\n- }\n- return result;\n+\n+ var t = new Date().getTime() - initialTime;\n+\n+ var p = (-this.deceleration * Math.pow(t, 2)) / 2.0 + v0 * t;\n+ var x = p * fx;\n+ var y = p * fy;\n+\n+ var args = {};\n+ args.end = false;\n+ var v = -this.deceleration * t + v0;\n+\n+ if (v <= 0) {\n+ OpenLayers.Animation.stop(this.timerId);\n+ this.timerId = null;\n+ args.end = true;\n+ }\n+\n+ args.x = x - lastX;\n+ args.y = y - lastY;\n+ lastX = x;\n+ lastY = y;\n+ callback(args.x, args.y, args.end);\n+ };\n+\n+ this.timerId = OpenLayers.Animation.start(\n+ OpenLayers.Function.bind(timerCallback, this)\n+ );\n },\n \n+ CLASS_NAME: \"OpenLayers.Kinetic\"\n+});\n+/* ======================================================================\n+ OpenLayers/Events.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/Util.js\n+ */\n+\n+/**\n+ * Namespace: OpenLayers.Event\n+ * Utility functions for event handling.\n+ */\n+OpenLayers.Event = {\n+\n+ /** \n+ * Property: observers \n+ * {Object} A hashtable cache of the event observers. Keyed by\n+ * element._eventCacheID \n+ */\n+ observers: false,\n+\n /**\n- * Method: split\n- * Use this geometry (the source) to attempt to split a target geometry.\n+ * Constant: KEY_SPACE\n+ * {int}\n+ */\n+ KEY_SPACE: 32,\n+\n+ /** \n+ * Constant: KEY_BACKSPACE \n+ * {int} \n+ */\n+ KEY_BACKSPACE: 8,\n+\n+ /** \n+ * Constant: KEY_TAB \n+ * {int} \n+ */\n+ KEY_TAB: 9,\n+\n+ /** \n+ * Constant: KEY_RETURN \n+ * {int} \n+ */\n+ KEY_RETURN: 13,\n+\n+ /** \n+ * Constant: KEY_ESC \n+ * {int} \n+ */\n+ KEY_ESC: 27,\n+\n+ /** \n+ * Constant: KEY_LEFT \n+ * {int} \n+ */\n+ KEY_LEFT: 37,\n+\n+ /** \n+ * Constant: KEY_UP \n+ * {int} \n+ */\n+ KEY_UP: 38,\n+\n+ /** \n+ * Constant: KEY_RIGHT \n+ * {int} \n+ */\n+ KEY_RIGHT: 39,\n+\n+ /** \n+ * Constant: KEY_DOWN \n+ * {int} \n+ */\n+ KEY_DOWN: 40,\n+\n+ /** \n+ * Constant: KEY_DELETE \n+ * {int} \n+ */\n+ KEY_DELETE: 46,\n+\n+\n+ /**\n+ * Method: element\n+ * Cross browser event element detection.\n * \n * Parameters:\n- * target - {} The target geometry.\n- * options - {Object} Properties of this object will be used to determine\n- * how the split is conducted.\n- *\n- * Valid options:\n- * mutual - {Boolean} Split the source geometry in addition to the target\n- * geometry. Default is false.\n- * edge - {Boolean} Allow splitting when only edges intersect. Default is\n- * true. If false, a vertex on the source must be within the tolerance\n- * distance of the intersection to be considered a split.\n- * tolerance - {Number} If a non-null value is provided, intersections\n- * within the tolerance distance of an existing vertex on the source\n- * will be assumed to occur at the vertex.\n+ * event - {Event} \n * \n * Returns:\n- * {Array} A list of geometries (of this same type as the target) that\n- * result from splitting the target with the source geometry. The\n- * source and target geometry will remain unmodified. If no split\n- * results, null will be returned. If mutual is true and a split\n- * results, return will be an array of two arrays - the first will be\n- * all geometries that result from splitting the source geometry and\n- * the second will be all geometries that result from splitting the\n- * target geometry.\n+ * {DOMElement} The element that caused the event \n */\n- split: function(target, options) {\n- var results = null;\n- var mutual = options && options.mutual;\n- var sourceSplit, targetSplit, sourceParts, targetParts;\n- if (target instanceof OpenLayers.Geometry.LineString) {\n- var verts = this.getVertices();\n- var vert1, vert2, seg, splits, lines, point;\n- var points = [];\n- sourceParts = [];\n- for (var i = 0, stop = verts.length - 2; i <= stop; ++i) {\n- vert1 = verts[i];\n- vert2 = verts[i + 1];\n- seg = {\n- x1: vert1.x,\n- y1: vert1.y,\n- x2: vert2.x,\n- y2: vert2.y\n- };\n- targetParts = targetParts || [target];\n- if (mutual) {\n- points.push(vert1.clone());\n- }\n- for (var j = 0; j < targetParts.length; ++j) {\n- splits = targetParts[j].splitWithSegment(seg, options);\n- if (splits) {\n- // splice in new features\n- lines = splits.lines;\n- if (lines.length > 0) {\n- lines.unshift(j, 1);\n- Array.prototype.splice.apply(targetParts, lines);\n- j += lines.length - 2;\n- }\n- if (mutual) {\n- for (var k = 0, len = splits.points.length; k < len; ++k) {\n- point = splits.points[k];\n- if (!point.equals(vert1)) {\n- points.push(point);\n- sourceParts.push(new OpenLayers.Geometry.LineString(points));\n- if (point.equals(vert2)) {\n- points = [];\n- } else {\n- points = [point.clone()];\n- }\n- }\n- }\n- }\n- }\n- }\n- }\n- if (mutual && sourceParts.length > 0 && points.length > 0) {\n- points.push(vert2.clone());\n- sourceParts.push(new OpenLayers.Geometry.LineString(points));\n- }\n- } else {\n- results = target.splitWith(this, options);\n- }\n- if (targetParts && targetParts.length > 1) {\n- targetSplit = true;\n- } else {\n- targetParts = [];\n- }\n- if (sourceParts && sourceParts.length > 1) {\n- sourceSplit = true;\n- } else {\n- sourceParts = [];\n- }\n- if (targetSplit || sourceSplit) {\n- if (mutual) {\n- results = [sourceParts, targetParts];\n- } else {\n- results = targetParts;\n- }\n- }\n- return results;\n+ element: function(event) {\n+ return event.target || event.srcElement;\n },\n \n /**\n- * Method: splitWith\n- * Split this geometry (the target) with the given geometry (the source).\n+ * Method: isSingleTouch\n+ * Determine whether event was caused by a single touch\n *\n * Parameters:\n- * geometry - {} A geometry used to split this\n- * geometry (the source).\n- * options - {Object} Properties of this object will be used to determine\n- * how the split is conducted.\n+ * event - {Event}\n *\n- * Valid options:\n- * mutual - {Boolean} Split the source geometry in addition to the target\n- * geometry. Default is false.\n- * edge - {Boolean} Allow splitting when only edges intersect. Default is\n- * true. If false, a vertex on the source must be within the tolerance\n- * distance of the intersection to be considered a split.\n- * tolerance - {Number} If a non-null value is provided, intersections\n- * within the tolerance distance of an existing vertex on the source\n- * will be assumed to occur at the vertex.\n- * \n * Returns:\n- * {Array} A list of geometries (of this same type as the target) that\n- * result from splitting the target with the source geometry. The\n- * source and target geometry will remain unmodified. If no split\n- * results, null will be returned. If mutual is true and a split\n- * results, return will be an array of two arrays - the first will be\n- * all geometries that result from splitting the source geometry and\n- * the second will be all geometries that result from splitting the\n- * target geometry.\n+ * {Boolean}\n */\n- splitWith: function(geometry, options) {\n- return geometry.split(this, options);\n-\n+ isSingleTouch: function(event) {\n+ return event.touches && event.touches.length == 1;\n },\n \n /**\n- * APIMethod: getVertices\n- * Return a list of all points in this geometry.\n+ * Method: isMultiTouch\n+ * Determine whether event was caused by a multi touch\n *\n * Parameters:\n- * nodes - {Boolean} For lines, only return vertices that are\n- * endpoints. If false, for lines, only vertices that are not\n- * endpoints will be returned. If not provided, all vertices will\n- * be returned.\n+ * event - {Event}\n *\n * Returns:\n- * {Array} A list of all vertices in the geometry.\n+ * {Boolean}\n */\n- getVertices: function(nodes) {\n- var vertices;\n- if (nodes === true) {\n- vertices = [\n- this.components[0],\n- this.components[this.components.length - 1]\n- ];\n- } else if (nodes === false) {\n- vertices = this.components.slice(1, this.components.length - 1);\n- } else {\n- vertices = this.components.slice();\n- }\n- return vertices;\n+ isMultiTouch: function(event) {\n+ return event.touches && event.touches.length > 1;\n },\n \n /**\n- * APIMethod: distanceTo\n- * Calculate the closest distance between two geometries (on the x-y plane).\n+ * Method: isLeftClick\n+ * Determine whether event was caused by a left click. \n *\n * Parameters:\n- * geometry - {} The target geometry.\n- * options - {Object} Optional properties for configuring the distance\n- * calculation.\n- *\n- * Valid options:\n- * details - {Boolean} Return details from the distance calculation.\n- * Default is false.\n- * edge - {Boolean} Calculate the distance from this geometry to the\n- * nearest edge of the target geometry. Default is true. If true,\n- * calling distanceTo from a geometry that is wholly contained within\n- * the target will result in a non-zero distance. If false, whenever\n- * geometries intersect, calling distanceTo will return 0. If false,\n- * details cannot be returned.\n+ * event - {Event} \n+ * \n+ * Returns:\n+ * {Boolean}\n+ */\n+ isLeftClick: function(event) {\n+ return (((event.which) && (event.which == 1)) ||\n+ ((event.button) && (event.button == 1)));\n+ },\n+\n+ /**\n+ * Method: isRightClick\n+ * Determine whether event was caused by a right mouse click. \n *\n+ * Parameters:\n+ * event - {Event} \n+ * \n * Returns:\n- * {Number | Object} The distance between this geometry and the target.\n- * If details is true, the return will be an object with distance,\n- * x0, y0, x1, and x2 properties. The x0 and y0 properties represent\n- * the coordinates of the closest point on this geometry. The x1 and y1\n- * properties represent the coordinates of the closest point on the\n- * target geometry.\n+ * {Boolean}\n */\n- distanceTo: function(geometry, options) {\n- var edge = !(options && options.edge === false);\n- var details = edge && options && options.details;\n- var result, best = {};\n- var min = Number.POSITIVE_INFINITY;\n- if (geometry instanceof OpenLayers.Geometry.Point) {\n- var segs = this.getSortedSegments();\n- var x = geometry.x;\n- var y = geometry.y;\n- var seg;\n- for (var i = 0, len = segs.length; i < len; ++i) {\n- seg = segs[i];\n- result = OpenLayers.Geometry.distanceToSegment(geometry, seg);\n- if (result.distance < min) {\n- min = result.distance;\n- best = result;\n- if (min === 0) {\n- break;\n- }\n- } else {\n- // if distance increases and we cross y0 to the right of x0, no need to keep looking.\n- if (seg.x2 > x && ((y > seg.y1 && y < seg.y2) || (y < seg.y1 && y > seg.y2))) {\n- break;\n- }\n- }\n- }\n- if (details) {\n- best = {\n- distance: best.distance,\n- x0: best.x,\n- y0: best.y,\n- x1: x,\n- y1: y\n- };\n- } else {\n- best = best.distance;\n- }\n- } else if (geometry instanceof OpenLayers.Geometry.LineString) {\n- var segs0 = this.getSortedSegments();\n- var segs1 = geometry.getSortedSegments();\n- var seg0, seg1, intersection, x0, y0;\n- var len1 = segs1.length;\n- var interOptions = {\n- point: true\n- };\n- outer: for (var i = 0, len = segs0.length; i < len; ++i) {\n- seg0 = segs0[i];\n- x0 = seg0.x1;\n- y0 = seg0.y1;\n- for (var j = 0; j < len1; ++j) {\n- seg1 = segs1[j];\n- intersection = OpenLayers.Geometry.segmentsIntersect(seg0, seg1, interOptions);\n- if (intersection) {\n- min = 0;\n- best = {\n- distance: 0,\n- x0: intersection.x,\n- y0: intersection.y,\n- x1: intersection.x,\n- y1: intersection.y\n- };\n- break outer;\n- } else {\n- result = OpenLayers.Geometry.distanceToSegment({\n- x: x0,\n- y: y0\n- }, seg1);\n- if (result.distance < min) {\n- min = result.distance;\n- best = {\n- distance: min,\n- x0: x0,\n- y0: y0,\n- x1: result.x,\n- y1: result.y\n- };\n- }\n- }\n- }\n- }\n- if (!details) {\n- best = best.distance;\n- }\n- if (min !== 0) {\n- // check the final vertex in this line's sorted segments\n- if (seg0) {\n- result = geometry.distanceTo(\n- new OpenLayers.Geometry.Point(seg0.x2, seg0.y2),\n- options\n- );\n- var dist = details ? result.distance : result;\n- if (dist < min) {\n- if (details) {\n- best = {\n- distance: min,\n- x0: result.x1,\n- y0: result.y1,\n- x1: result.x0,\n- y1: result.y0\n- };\n- } else {\n- best = dist;\n- }\n- }\n- }\n- }\n+ isRightClick: function(event) {\n+ return (((event.which) && (event.which == 3)) ||\n+ ((event.button) && (event.button == 2)));\n+ },\n+\n+ /**\n+ * Method: stop\n+ * Stops an event from propagating. \n+ *\n+ * Parameters: \n+ * event - {Event} \n+ * allowDefault - {Boolean} If true, we stop the event chain but \n+ * still allow the default browser behaviour (text selection,\n+ * radio-button clicking, etc). Default is false.\n+ */\n+ stop: function(event, allowDefault) {\n+\n+ if (!allowDefault) {\n+ OpenLayers.Event.preventDefault(event);\n+ }\n+\n+ if (event.stopPropagation) {\n+ event.stopPropagation();\n } else {\n- best = geometry.distanceTo(this, options);\n- // swap since target comes from this line\n- if (details) {\n- best = {\n- distance: best.distance,\n- x0: best.x1,\n- y0: best.y1,\n- x1: best.x0,\n- y1: best.y0\n- };\n- }\n+ event.cancelBubble = true;\n }\n- return best;\n },\n \n /**\n- * APIMethod: simplify\n- * This function will return a simplified LineString.\n- * Simplification is based on the Douglas-Peucker algorithm.\n- *\n+ * Method: preventDefault\n+ * Cancels the event if it is cancelable, without stopping further\n+ * propagation of the event.\n *\n * Parameters:\n- * tolerance - {number} threshhold for simplification in map units\n- *\n+ * event - {Event}\n+ */\n+ preventDefault: function(event) {\n+ if (event.preventDefault) {\n+ event.preventDefault();\n+ } else {\n+ event.returnValue = false;\n+ }\n+ },\n+\n+ /** \n+ * Method: findElement\n+ * \n+ * Parameters:\n+ * event - {Event} \n+ * tagName - {String} \n+ * \n * Returns:\n- * {OpenLayers.Geometry.LineString} the simplified LineString\n+ * {DOMElement} The first node with the given tagName, starting from the\n+ * node the event was triggered on and traversing the DOM upwards\n */\n- simplify: function(tolerance) {\n- if (this && this !== null) {\n- var points = this.getVertices();\n- if (points.length < 3) {\n- return this;\n+ findElement: function(event, tagName) {\n+ var element = OpenLayers.Event.element(event);\n+ while (element.parentNode && (!element.tagName ||\n+ (element.tagName.toUpperCase() != tagName.toUpperCase()))) {\n+ element = element.parentNode;\n+ }\n+ return element;\n+ },\n+\n+ /** \n+ * Method: observe\n+ * \n+ * Parameters:\n+ * elementParam - {DOMElement || String} \n+ * name - {String} \n+ * observer - {function} \n+ * useCapture - {Boolean} \n+ */\n+ observe: function(elementParam, name, observer, useCapture) {\n+ var element = OpenLayers.Util.getElement(elementParam);\n+ useCapture = useCapture || false;\n+\n+ if (name == 'keypress' &&\n+ (navigator.appVersion.match(/Konqueror|Safari|KHTML/) ||\n+ element.attachEvent)) {\n+ name = 'keydown';\n+ }\n+\n+ //if observers cache has not yet been created, create it\n+ if (!this.observers) {\n+ this.observers = {};\n+ }\n+\n+ //if not already assigned, make a new unique cache ID\n+ if (!element._eventCacheID) {\n+ var idPrefix = \"eventCacheID_\";\n+ if (element.id) {\n+ idPrefix = element.id + \"_\" + idPrefix;\n }\n+ element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix);\n+ }\n \n- var compareNumbers = function(a, b) {\n- return (a - b);\n- };\n+ var cacheID = element._eventCacheID;\n \n- /**\n- * Private function doing the Douglas-Peucker reduction\n- */\n- var douglasPeuckerReduction = function(points, firstPoint, lastPoint, tolerance) {\n- var maxDistance = 0;\n- var indexFarthest = 0;\n+ //if there is not yet a hash entry for this element, add one\n+ if (!this.observers[cacheID]) {\n+ this.observers[cacheID] = [];\n+ }\n \n- for (var index = firstPoint, distance; index < lastPoint; index++) {\n- distance = perpendicularDistance(points[firstPoint], points[lastPoint], points[index]);\n- if (distance > maxDistance) {\n- maxDistance = distance;\n- indexFarthest = index;\n- }\n- }\n+ //add a new observer to this element's list\n+ this.observers[cacheID].push({\n+ 'element': element,\n+ 'name': name,\n+ 'observer': observer,\n+ 'useCapture': useCapture\n+ });\n \n- if (maxDistance > tolerance && indexFarthest != firstPoint) {\n- //Add the largest point that exceeds the tolerance\n- pointIndexsToKeep.push(indexFarthest);\n- douglasPeuckerReduction(points, firstPoint, indexFarthest, tolerance);\n- douglasPeuckerReduction(points, indexFarthest, lastPoint, tolerance);\n- }\n- };\n+ //add the actual browser event listener\n+ if (element.addEventListener) {\n+ element.addEventListener(name, observer, useCapture);\n+ } else if (element.attachEvent) {\n+ element.attachEvent('on' + name, observer);\n+ }\n+ },\n \n- /**\n- * Private function calculating the perpendicular distance\n- * TODO: check whether OpenLayers.Geometry.LineString::distanceTo() is faster or slower\n- */\n- var perpendicularDistance = function(point1, point2, point) {\n- //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)| *Area of triangle\n- //Base = v((x1-x2)\u00b2+(x1-x2)\u00b2) *Base of Triangle*\n- //Area = .5*Base*H *Solve for height\n- //Height = Area/.5/Base\n+ /** \n+ * Method: stopObservingElement\n+ * Given the id of an element to stop observing, cycle through the \n+ * element's cached observers, calling stopObserving on each one, \n+ * skipping those entries which can no longer be removed.\n+ * \n+ * parameters:\n+ * elementParam - {DOMElement || String} \n+ */\n+ stopObservingElement: function(elementParam) {\n+ var element = OpenLayers.Util.getElement(elementParam);\n+ var cacheID = element._eventCacheID;\n \n- var area = Math.abs(0.5 * (point1.x * point2.y + point2.x * point.y + point.x * point1.y - point2.x * point1.y - point.x * point2.y - point1.x * point.y));\n- var bottom = Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2));\n- var height = area / bottom * 2;\n+ this._removeElementObservers(OpenLayers.Event.observers[cacheID]);\n+ },\n \n- return height;\n- };\n+ /**\n+ * Method: _removeElementObservers\n+ *\n+ * Parameters:\n+ * elementObservers - {Array(Object)} Array of (element, name, \n+ * observer, usecapture) objects, \n+ * taken directly from hashtable\n+ */\n+ _removeElementObservers: function(elementObservers) {\n+ if (elementObservers) {\n+ for (var i = elementObservers.length - 1; i >= 0; i--) {\n+ var entry = elementObservers[i];\n+ OpenLayers.Event.stopObserving.apply(this, [\n+ entry.element, entry.name, entry.observer, entry.useCapture\n+ ]);\n+ }\n+ }\n+ },\n \n- var firstPoint = 0;\n- var lastPoint = points.length - 1;\n- var pointIndexsToKeep = [];\n+ /**\n+ * Method: stopObserving\n+ * \n+ * Parameters:\n+ * elementParam - {DOMElement || String} \n+ * name - {String} \n+ * observer - {function} \n+ * useCapture - {Boolean} \n+ * \n+ * Returns:\n+ * {Boolean} Whether or not the event observer was removed\n+ */\n+ stopObserving: function(elementParam, name, observer, useCapture) {\n+ useCapture = useCapture || false;\n \n- //Add the first and last index to the keepers\n- pointIndexsToKeep.push(firstPoint);\n- pointIndexsToKeep.push(lastPoint);\n+ var element = OpenLayers.Util.getElement(elementParam);\n+ var cacheID = element._eventCacheID;\n \n- //The first and the last point cannot be the same\n- while (points[firstPoint].equals(points[lastPoint])) {\n- lastPoint--;\n- //Addition: the first point not equal to first point in the LineString is kept as well\n- pointIndexsToKeep.push(lastPoint);\n+ if (name == 'keypress') {\n+ if (navigator.appVersion.match(/Konqueror|Safari|KHTML/) ||\n+ element.detachEvent) {\n+ name = 'keydown';\n }\n+ }\n \n- douglasPeuckerReduction(points, firstPoint, lastPoint, tolerance);\n- var returnPoints = [];\n- pointIndexsToKeep.sort(compareNumbers);\n- for (var index = 0; index < pointIndexsToKeep.length; index++) {\n- returnPoints.push(points[pointIndexsToKeep[index]]);\n+ // find element's entry in this.observers cache and remove it\n+ var foundEntry = false;\n+ var elementObservers = OpenLayers.Event.observers[cacheID];\n+ if (elementObservers) {\n+\n+ // find the specific event type in the element's list\n+ var i = 0;\n+ while (!foundEntry && i < elementObservers.length) {\n+ var cacheEntry = elementObservers[i];\n+\n+ if ((cacheEntry.name == name) &&\n+ (cacheEntry.observer == observer) &&\n+ (cacheEntry.useCapture == useCapture)) {\n+\n+ elementObservers.splice(i, 1);\n+ if (elementObservers.length == 0) {\n+ delete OpenLayers.Event.observers[cacheID];\n+ }\n+ foundEntry = true;\n+ break;\n+ }\n+ i++;\n }\n- return new OpenLayers.Geometry.LineString(returnPoints);\n+ }\n \n- } else {\n- return this;\n+ //actually remove the event listener from browser\n+ if (foundEntry) {\n+ if (element.removeEventListener) {\n+ element.removeEventListener(name, observer, useCapture);\n+ } else if (element && element.detachEvent) {\n+ element.detachEvent('on' + name, observer);\n+ }\n }\n+ return foundEntry;\n },\n \n- CLASS_NAME: \"OpenLayers.Geometry.LineString\"\n-});\n-/* ======================================================================\n- OpenLayers/Geometry/MultiLineString.js\n- ====================================================================== */\n+ /** \n+ * Method: unloadCache\n+ * Cycle through all the element entries in the events cache and call\n+ * stopObservingElement on each. \n+ */\n+ unloadCache: function() {\n+ // check for OpenLayers.Event before checking for observers, because\n+ // OpenLayers.Event may be undefined in IE if no map instance was\n+ // created\n+ if (OpenLayers.Event && OpenLayers.Event.observers) {\n+ for (var cacheID in OpenLayers.Event.observers) {\n+ var elementObservers = OpenLayers.Event.observers[cacheID];\n+ OpenLayers.Event._removeElementObservers.apply(this,\n+ [elementObservers]);\n+ }\n+ OpenLayers.Event.observers = false;\n+ }\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+ CLASS_NAME: \"OpenLayers.Event\"\n+};\n \n-/**\n- * @requires OpenLayers/Geometry/Collection.js\n- * @requires OpenLayers/Geometry/LineString.js\n- */\n+/* prevent memory leaks in IE */\n+OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false);\n \n /**\n- * Class: OpenLayers.Geometry.MultiLineString\n- * A MultiLineString is a geometry with multiple \n- * components.\n- * \n- * Inherits from:\n- * - \n- * - \n+ * Class: OpenLayers.Events\n */\n-OpenLayers.Geometry.MultiLineString = OpenLayers.Class(\n- OpenLayers.Geometry.Collection, {\n-\n- /**\n- * Property: componentTypes\n- * {Array(String)} An array of class names representing the types of\n- * components that the collection can include. A null value means the\n- * component types are not restricted.\n- */\n- componentTypes: [\"OpenLayers.Geometry.LineString\"],\n+OpenLayers.Events = OpenLayers.Class({\n \n- /**\n- * Constructor: OpenLayers.Geometry.MultiLineString\n- * Constructor for a MultiLineString Geometry.\n- *\n- * Parameters: \n- * components - {Array()} \n- *\n- */\n-\n- /**\n- * Method: split\n- * Use this geometry (the source) to attempt to split a target geometry.\n- * \n- * Parameters:\n- * geometry - {} The target geometry.\n- * options - {Object} Properties of this object will be used to determine\n- * how the split is conducted.\n- *\n- * Valid options:\n- * mutual - {Boolean} Split the source geometry in addition to the target\n- * geometry. Default is false.\n- * edge - {Boolean} Allow splitting when only edges intersect. Default is\n- * true. If false, a vertex on the source must be within the tolerance\n- * distance of the intersection to be considered a split.\n- * tolerance - {Number} If a non-null value is provided, intersections\n- * within the tolerance distance of an existing vertex on the source\n- * will be assumed to occur at the vertex.\n- * \n- * Returns:\n- * {Array} A list of geometries (of this same type as the target) that\n- * result from splitting the target with the source geometry. The\n- * source and target geometry will remain unmodified. If no split\n- * results, null will be returned. If mutual is true and a split\n- * results, return will be an array of two arrays - the first will be\n- * all geometries that result from splitting the source geometry and\n- * the second will be all geometries that result from splitting the\n- * target geometry.\n- */\n- split: function(geometry, options) {\n- var results = null;\n- var mutual = options && options.mutual;\n- var splits, sourceLine, sourceLines, sourceSplit, targetSplit;\n- var sourceParts = [];\n- var targetParts = [geometry];\n- for (var i = 0, len = this.components.length; i < len; ++i) {\n- sourceLine = this.components[i];\n- sourceSplit = false;\n- for (var j = 0; j < targetParts.length; ++j) {\n- splits = sourceLine.split(targetParts[j], options);\n- if (splits) {\n- if (mutual) {\n- sourceLines = splits[0];\n- for (var k = 0, klen = sourceLines.length; k < klen; ++k) {\n- if (k === 0 && sourceParts.length) {\n- sourceParts[sourceParts.length - 1].addComponent(\n- sourceLines[k]\n- );\n- } else {\n- sourceParts.push(\n- new OpenLayers.Geometry.MultiLineString([\n- sourceLines[k]\n- ])\n- );\n- }\n- }\n- sourceSplit = true;\n- splits = splits[1];\n- }\n- if (splits.length) {\n- // splice in new target parts\n- splits.unshift(j, 1);\n- Array.prototype.splice.apply(targetParts, splits);\n- break;\n- }\n- }\n- }\n- if (!sourceSplit) {\n- // source line was not hit\n- if (sourceParts.length) {\n- // add line to existing multi\n- sourceParts[sourceParts.length - 1].addComponent(\n- sourceLine.clone()\n- );\n- } else {\n- // create a fresh multi\n- sourceParts = [\n- new OpenLayers.Geometry.MultiLineString(\n- sourceLine.clone()\n- )\n- ];\n- }\n- }\n- }\n- if (sourceParts && sourceParts.length > 1) {\n- sourceSplit = true;\n- } else {\n- sourceParts = [];\n- }\n- if (targetParts && targetParts.length > 1) {\n- targetSplit = true;\n- } else {\n- targetParts = [];\n- }\n- if (sourceSplit || targetSplit) {\n- if (mutual) {\n- results = [sourceParts, targetParts];\n- } else {\n- results = targetParts;\n- }\n- }\n- return results;\n- },\n-\n- /**\n- * Method: splitWith\n- * Split this geometry (the target) with the given geometry (the source).\n- *\n- * Parameters:\n- * geometry - {} A geometry used to split this\n- * geometry (the source).\n- * options - {Object} Properties of this object will be used to determine\n- * how the split is conducted.\n- *\n- * Valid options:\n- * mutual - {Boolean} Split the source geometry in addition to the target\n- * geometry. Default is false.\n- * edge - {Boolean} Allow splitting when only edges intersect. Default is\n- * true. If false, a vertex on the source must be within the tolerance\n- * distance of the intersection to be considered a split.\n- * tolerance - {Number} If a non-null value is provided, intersections\n- * within the tolerance distance of an existing vertex on the source\n- * will be assumed to occur at the vertex.\n- * \n- * Returns:\n- * {Array} A list of geometries (of this same type as the target) that\n- * result from splitting the target with the source geometry. The\n- * source and target geometry will remain unmodified. If no split\n- * results, null will be returned. If mutual is true and a split\n- * results, return will be an array of two arrays - the first will be\n- * all geometries that result from splitting the source geometry and\n- * the second will be all geometries that result from splitting the\n- * target geometry.\n- */\n- splitWith: function(geometry, options) {\n- var results = null;\n- var mutual = options && options.mutual;\n- var splits, targetLine, sourceLines, sourceSplit, targetSplit, sourceParts, targetParts;\n- if (geometry instanceof OpenLayers.Geometry.LineString) {\n- targetParts = [];\n- sourceParts = [geometry];\n- for (var i = 0, len = this.components.length; i < len; ++i) {\n- targetSplit = false;\n- targetLine = this.components[i];\n- for (var j = 0; j < sourceParts.length; ++j) {\n- splits = sourceParts[j].split(targetLine, options);\n- if (splits) {\n- if (mutual) {\n- sourceLines = splits[0];\n- if (sourceLines.length) {\n- // splice in new source parts\n- sourceLines.unshift(j, 1);\n- Array.prototype.splice.apply(sourceParts, sourceLines);\n- j += sourceLines.length - 2;\n- }\n- splits = splits[1];\n- if (splits.length === 0) {\n- splits = [targetLine.clone()];\n- }\n- }\n- for (var k = 0, klen = splits.length; k < klen; ++k) {\n- if (k === 0 && targetParts.length) {\n- targetParts[targetParts.length - 1].addComponent(\n- splits[k]\n- );\n- } else {\n- targetParts.push(\n- new OpenLayers.Geometry.MultiLineString([\n- splits[k]\n- ])\n- );\n- }\n- }\n- targetSplit = true;\n- }\n- }\n- if (!targetSplit) {\n- // target component was not hit\n- if (targetParts.length) {\n- // add it to any existing multi-line\n- targetParts[targetParts.length - 1].addComponent(\n- targetLine.clone()\n- );\n- } else {\n- // or start with a fresh multi-line\n- targetParts = [\n- new OpenLayers.Geometry.MultiLineString([\n- targetLine.clone()\n- ])\n- ];\n- }\n-\n- }\n- }\n- } else {\n- results = geometry.split(this);\n- }\n- if (sourceParts && sourceParts.length > 1) {\n- sourceSplit = true;\n- } else {\n- sourceParts = [];\n- }\n- if (targetParts && targetParts.length > 1) {\n- targetSplit = true;\n- } else {\n- targetParts = [];\n- }\n- if (sourceSplit || targetSplit) {\n- if (mutual) {\n- results = [sourceParts, targetParts];\n- } else {\n- results = targetParts;\n- }\n- }\n- return results;\n- },\n-\n- CLASS_NAME: \"OpenLayers.Geometry.MultiLineString\"\n- });\n-/* ======================================================================\n- OpenLayers/Geometry/LinearRing.js\n- ====================================================================== */\n+ /** \n+ * Constant: BROWSER_EVENTS\n+ * {Array(String)} supported events \n+ */\n+ BROWSER_EVENTS: [\n+ \"mouseover\", \"mouseout\",\n+ \"mousedown\", \"mouseup\", \"mousemove\",\n+ \"click\", \"dblclick\", \"rightclick\", \"dblrightclick\",\n+ \"resize\", \"focus\", \"blur\",\n+ \"touchstart\", \"touchmove\", \"touchend\",\n+ \"keydown\"\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+ * Property: listeners \n+ * {Object} Hashtable of Array(Function): events listener functions \n+ */\n+ listeners: null,\n \n-/**\n- * @requires OpenLayers/Geometry/LineString.js\n- */\n+ /** \n+ * Property: object \n+ * {Object} the code object issuing application events \n+ */\n+ object: null,\n \n-/**\n- * Class: OpenLayers.Geometry.LinearRing\n- * \n- * A Linear Ring is a special LineString which is closed. It closes itself \n- * automatically on every addPoint/removePoint by adding a copy of the first\n- * point as the last point. \n- * \n- * Also, as it is the first in the line family to close itself, a getArea()\n- * function is defined to calculate the enclosed area of the linearRing\n- * \n- * Inherits:\n- * - \n- */\n-OpenLayers.Geometry.LinearRing = OpenLayers.Class(\n- OpenLayers.Geometry.LineString, {\n+ /** \n+ * Property: element \n+ * {DOMElement} the DOM element receiving browser events \n+ */\n+ element: null,\n \n- /**\n- * Property: componentTypes\n- * {Array(String)} An array of class names representing the types of \n- * components that the collection can include. A null \n- * value means the component types are not restricted.\n- */\n- componentTypes: [\"OpenLayers.Geometry.Point\"],\n+ /** \n+ * Property: eventHandler \n+ * {Function} bound event handler attached to elements \n+ */\n+ eventHandler: null,\n \n- /**\n- * Constructor: OpenLayers.Geometry.LinearRing\n- * Linear rings are constructed with an array of points. This array\n- * can represent a closed or open ring. If the ring is open (the last\n- * point does not equal the first point), the constructor will close\n- * the ring. If the ring is already closed (the last point does equal\n- * the first point), it will be left closed.\n- * \n- * Parameters:\n- * points - {Array()} points\n- */\n+ /** \n+ * APIProperty: fallThrough \n+ * {Boolean} \n+ */\n+ fallThrough: null,\n \n- /**\n- * APIMethod: addComponent\n- * Adds a point to geometry components. If the point is to be added to\n- * the end of the components array and it is the same as the last point\n- * already in that array, the duplicate point is not added. This has \n- * the effect of closing the ring if it is not already closed, and \n- * doing the right thing if it is already closed. This behavior can \n- * be overridden by calling the method with a non-null index as the \n- * second argument.\n- *\n- * Parameters:\n- * point - {}\n- * index - {Integer} Index into the array to insert the component\n- * \n- * Returns:\n- * {Boolean} Was the Point successfully added?\n- */\n- addComponent: function(point, index) {\n- var added = false;\n+ /** \n+ * APIProperty: includeXY\n+ * {Boolean} Should the .xy property automatically be created for browser\n+ * mouse events? In general, this should be false. If it is true, then\n+ * mouse events will automatically generate a '.xy' property on the \n+ * event object that is passed. (Prior to OpenLayers 2.7, this was true\n+ * by default.) Otherwise, you can call the getMousePosition on the\n+ * relevant events handler on the object available via the 'evt.object'\n+ * property of the evt object. So, for most events, you can call:\n+ * function named(evt) { \n+ * this.xy = this.object.events.getMousePosition(evt) \n+ * } \n+ *\n+ * This option typically defaults to false for performance reasons:\n+ * when creating an events object whose primary purpose is to manage\n+ * relatively positioned mouse events within a div, it may make\n+ * sense to set it to true.\n+ *\n+ * This option is also used to control whether the events object caches\n+ * offsets. If this is false, it will not: the reason for this is that\n+ * it is only expected to be called many times if the includeXY property\n+ * is set to true. If you set this to true, you are expected to clear \n+ * the offset cache manually (using this.clearMouseCache()) if:\n+ * the border of the element changes\n+ * the location of the element in the page changes\n+ */\n+ includeXY: false,\n \n- //remove last point\n- var lastPoint = this.components.pop();\n+ /**\n+ * APIProperty: extensions\n+ * {Object} Event extensions registered with this instance. Keys are\n+ * event types, values are {OpenLayers.Events.*} extension instances or\n+ * {Boolean} for events that an instantiated extension provides in\n+ * addition to the one it was created for.\n+ *\n+ * Extensions create an event in addition to browser events, which usually\n+ * fires when a sequence of browser events is completed. Extensions are\n+ * automatically instantiated when a listener is registered for an event\n+ * provided by an extension.\n+ *\n+ * Extensions are created in the namespace using\n+ * , and named after the event they provide.\n+ * The constructor receives the target instance as\n+ * argument. Extensions that need to capture browser events before they\n+ * propagate can register their listeners events using , with\n+ * {extension: true} as 4th argument.\n+ *\n+ * If an extension creates more than one event, an alias for each event\n+ * type should be created and reference the same class. The constructor\n+ * should set a reference in the target's extensions registry to itself.\n+ *\n+ * Below is a minimal extension that provides the \"foostart\" and \"fooend\"\n+ * event types, which replace the native \"click\" event type if clicked on\n+ * an element with the css class \"foo\":\n+ *\n+ * (code)\n+ * OpenLayers.Events.foostart = OpenLayers.Class({\n+ * initialize: function(target) {\n+ * this.target = target;\n+ * this.target.register(\"click\", this, this.doStuff, {extension: true});\n+ * // only required if extension provides more than one event type\n+ * this.target.extensions[\"foostart\"] = true;\n+ * this.target.extensions[\"fooend\"] = true;\n+ * },\n+ * destroy: function() {\n+ * var target = this.target;\n+ * target.unregister(\"click\", this, this.doStuff);\n+ * delete this.target;\n+ * // only required if extension provides more than one event type\n+ * delete target.extensions[\"foostart\"];\n+ * delete target.extensions[\"fooend\"];\n+ * },\n+ * doStuff: function(evt) {\n+ * var propagate = true;\n+ * if (OpenLayers.Event.element(evt).className === \"foo\") {\n+ * propagate = false;\n+ * var target = this.target;\n+ * target.triggerEvent(\"foostart\");\n+ * window.setTimeout(function() {\n+ * target.triggerEvent(\"fooend\");\n+ * }, 1000);\n+ * }\n+ * return propagate;\n+ * }\n+ * });\n+ * // only required if extension provides more than one event type\n+ * OpenLayers.Events.fooend = OpenLayers.Events.foostart;\n+ * (end)\n+ * \n+ */\n+ extensions: null,\n \n- // given an index, add the point\n- // without an index only add non-duplicate points\n- if (index != null || !point.equals(lastPoint)) {\n- added = OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,\n- arguments);\n- }\n+ /**\n+ * Property: extensionCount\n+ * {Object} Keys are event types (like in ), values are the\n+ * number of extension listeners for each event type.\n+ */\n+ extensionCount: null,\n \n- //append copy of first point\n- var firstPoint = this.components[0];\n- OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,\n- [firstPoint]);\n+ /**\n+ * Method: clearMouseListener\n+ * A version of that is bound to this instance so that\n+ * it can be used with and\n+ * .\n+ */\n+ clearMouseListener: null,\n \n- return added;\n- },\n+ /**\n+ * Constructor: OpenLayers.Events\n+ * Construct an OpenLayers.Events object.\n+ *\n+ * Parameters:\n+ * object - {Object} The js object to which this Events object is being added\n+ * element - {DOMElement} A dom element to respond to browser events\n+ * eventTypes - {Array(String)} Deprecated. Array of custom application\n+ * events. A listener may be registered for any named event, regardless\n+ * of the values provided here.\n+ * fallThrough - {Boolean} Allow events to fall through after these have\n+ * been handled?\n+ * options - {Object} Options for the events object.\n+ */\n+ initialize: function(object, element, eventTypes, fallThrough, options) {\n+ OpenLayers.Util.extend(this, options);\n+ this.object = object;\n+ this.fallThrough = fallThrough;\n+ this.listeners = {};\n+ this.extensions = {};\n+ this.extensionCount = {};\n+ this._msTouches = [];\n \n- /**\n- * APIMethod: removeComponent\n- * Removes a point from geometry components.\n- *\n- * Parameters:\n- * point - {}\n- *\n- * Returns: \n- * {Boolean} The component was removed.\n- */\n- removeComponent: function(point) {\n- var removed = this.components && (this.components.length > 3);\n- if (removed) {\n- //remove last point\n- this.components.pop();\n+ // if a dom element is specified, add a listeners list \n+ // for browser events on the element and register them\n+ if (element != null) {\n+ this.attachToElement(element);\n+ }\n+ },\n \n- //remove our point\n- OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,\n- arguments);\n- //append copy of first point\n- var firstPoint = this.components[0];\n- OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,\n- [firstPoint]);\n+ /**\n+ * APIMethod: destroy\n+ */\n+ destroy: function() {\n+ for (var e in this.extensions) {\n+ if (typeof this.extensions[e] !== \"boolean\") {\n+ this.extensions[e].destroy();\n }\n- return removed;\n- },\n-\n- /**\n- * APIMethod: move\n- * Moves a geometry by the given displacement along positive x and y axes.\n- * This modifies the position of the geometry and clears the cached\n- * bounds.\n- *\n- * Parameters:\n- * x - {Float} Distance to move geometry in positive x direction. \n- * y - {Float} Distance to move geometry in positive y direction.\n- */\n- move: function(x, y) {\n- for (var i = 0, len = this.components.length; i < len - 1; i++) {\n- this.components[i].move(x, y);\n+ }\n+ this.extensions = null;\n+ if (this.element) {\n+ OpenLayers.Event.stopObservingElement(this.element);\n+ if (this.element.hasScrollEvent) {\n+ OpenLayers.Event.stopObserving(\n+ window, \"scroll\", this.clearMouseListener\n+ );\n }\n- },\n+ }\n+ this.element = null;\n \n- /**\n- * APIMethod: rotate\n- * Rotate a geometry around some origin\n- *\n- * Parameters:\n- * angle - {Float} Rotation angle in degrees (measured counterclockwise\n- * from the positive x-axis)\n- * origin - {} Center point for the rotation\n- */\n- rotate: function(angle, origin) {\n- for (var i = 0, len = this.components.length; i < len - 1; ++i) {\n- this.components[i].rotate(angle, origin);\n- }\n- },\n+ this.listeners = null;\n+ this.object = null;\n+ this.fallThrough = null;\n+ this.eventHandler = null;\n+ },\n \n- /**\n- * APIMethod: resize\n- * Resize a geometry relative to some origin. Use this method to apply\n- * a uniform scaling to a geometry.\n- *\n- * Parameters:\n- * scale - {Float} Factor by which to scale the geometry. A scale of 2\n- * doubles the size of the geometry in each dimension\n- * (lines, for example, will be twice as long, and polygons\n- * will have four times the area).\n- * origin - {} Point of origin for resizing\n- * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1.\n- * \n- * Returns:\n- * {} - The current geometry. \n- */\n- resize: function(scale, origin, ratio) {\n- for (var i = 0, len = this.components.length; i < len - 1; ++i) {\n- this.components[i].resize(scale, origin, ratio);\n- }\n- return this;\n- },\n+ /**\n+ * APIMethod: addEventType\n+ * Deprecated. Any event can be triggered without adding it first.\n+ * \n+ * Parameters:\n+ * eventName - {String}\n+ */\n+ addEventType: function(eventName) {},\n \n- /**\n- * APIMethod: transform\n- * Reproject the components geometry from source to dest.\n- *\n- * Parameters:\n- * source - {}\n- * dest - {}\n- * \n- * Returns:\n- * {} \n- */\n- transform: function(source, dest) {\n- if (source && dest) {\n- for (var i = 0, len = this.components.length; i < len - 1; i++) {\n- var component = this.components[i];\n- component.transform(source, dest);\n- }\n- this.bounds = null;\n- }\n- return this;\n- },\n+ /**\n+ * Method: attachToElement\n+ *\n+ * Parameters:\n+ * element - {HTMLDOMElement} a DOM element to attach browser events to\n+ */\n+ attachToElement: function(element) {\n+ if (this.element) {\n+ OpenLayers.Event.stopObservingElement(this.element);\n+ } else {\n+ // keep a bound copy of handleBrowserEvent() so that we can\n+ // pass the same function to both Event.observe() and .stopObserving()\n+ this.eventHandler = OpenLayers.Function.bindAsEventListener(\n+ this.handleBrowserEvent, this\n+ );\n \n- /**\n- * APIMethod: getCentroid\n- *\n- * Returns:\n- * {} The centroid of the collection\n- */\n- getCentroid: function() {\n- if (this.components) {\n- var len = this.components.length;\n- if (len > 0 && len <= 2) {\n- return this.components[0].clone();\n- } else if (len > 2) {\n- var sumX = 0.0;\n- var sumY = 0.0;\n- var x0 = this.components[0].x;\n- var y0 = this.components[0].y;\n- var area = -1 * this.getArea();\n- if (area != 0) {\n- for (var i = 0; i < len - 1; i++) {\n- var b = this.components[i];\n- var c = this.components[i + 1];\n- sumX += (b.x + c.x - 2 * x0) * ((b.x - x0) * (c.y - y0) - (c.x - x0) * (b.y - y0));\n- sumY += (b.y + c.y - 2 * y0) * ((b.x - x0) * (c.y - y0) - (c.x - x0) * (b.y - y0));\n- }\n- var x = x0 + sumX / (6 * area);\n- var y = y0 + sumY / (6 * area);\n- } else {\n- for (var i = 0; i < len - 1; i++) {\n- sumX += this.components[i].x;\n- sumY += this.components[i].y;\n- }\n- var x = sumX / (len - 1);\n- var y = sumY / (len - 1);\n- }\n- return new OpenLayers.Geometry.Point(x, y);\n- } else {\n- return null;\n- }\n+ // to be used with observe and stopObserving\n+ this.clearMouseListener = OpenLayers.Function.bind(\n+ this.clearMouseCache, this\n+ );\n+ }\n+ this.element = element;\n+ var msTouch = !!window.navigator.msMaxTouchPoints;\n+ var type;\n+ for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) {\n+ type = this.BROWSER_EVENTS[i];\n+ // register the event cross-browser\n+ OpenLayers.Event.observe(element, type, this.eventHandler);\n+ if (msTouch && type.indexOf('touch') === 0) {\n+ this.addMsTouchListener(element, type, this.eventHandler);\n }\n- },\n+ }\n+ // disable dragstart in IE so that mousedown/move/up works normally\n+ OpenLayers.Event.observe(element, \"dragstart\", OpenLayers.Event.stop);\n+ },\n \n- /**\n- * APIMethod: getArea\n- * Note - The area is positive if the ring is oriented CW, otherwise\n- * it will be negative.\n- * \n- * Returns:\n- * {Float} The signed area for a ring.\n- */\n- getArea: function() {\n- var area = 0.0;\n- if (this.components && (this.components.length > 2)) {\n- var sum = 0.0;\n- for (var i = 0, len = this.components.length; i < len - 1; i++) {\n- var b = this.components[i];\n- var c = this.components[i + 1];\n- sum += (b.x + c.x) * (c.y - b.y);\n- }\n- area = -sum / 2.0;\n+ /**\n+ * APIMethod: on\n+ * Convenience method for registering listeners with a common scope.\n+ * Internally, this method calls as shown in the examples\n+ * below.\n+ *\n+ * Example use:\n+ * (code)\n+ * // register a single listener for the \"loadstart\" event\n+ * events.on({\"loadstart\": loadStartListener});\n+ *\n+ * // this is equivalent to the following\n+ * events.register(\"loadstart\", undefined, loadStartListener);\n+ *\n+ * // register multiple listeners to be called with the same `this` object\n+ * events.on({\n+ * \"loadstart\": loadStartListener,\n+ * \"loadend\": loadEndListener,\n+ * scope: object\n+ * });\n+ *\n+ * // this is equivalent to the following\n+ * events.register(\"loadstart\", object, loadStartListener);\n+ * events.register(\"loadend\", object, loadEndListener);\n+ * (end)\n+ *\n+ * Parameters:\n+ * object - {Object} \n+ */\n+ on: function(object) {\n+ for (var type in object) {\n+ if (type != \"scope\" && object.hasOwnProperty(type)) {\n+ this.register(type, object.scope, object[type]);\n }\n- return area;\n- },\n+ }\n+ },\n \n- /**\n- * APIMethod: getGeodesicArea\n- * Calculate the approximate area of the polygon were it projected onto\n- * the earth. Note that this area will be positive if ring is oriented\n- * clockwise, otherwise it will be negative.\n- *\n- * Parameters:\n- * projection - {} The spatial reference system\n- * for the geometry coordinates. If not provided, Geographic/WGS84 is\n- * assumed.\n- * \n- * Reference:\n- * Robert. G. Chamberlain and William H. Duquette, \"Some Algorithms for\n- * Polygons on a Sphere\", JPL Publication 07-03, Jet Propulsion\n- * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409\n- *\n- * Returns:\n- * {float} The approximate signed geodesic area of the polygon in square\n- * meters.\n- */\n- getGeodesicArea: function(projection) {\n- var ring = this; // so we can work with a clone if needed\n- if (projection) {\n- var gg = new OpenLayers.Projection(\"EPSG:4326\");\n- if (!gg.equals(projection)) {\n- ring = this.clone().transform(projection, gg);\n- }\n- }\n- var area = 0.0;\n- var len = ring.components && ring.components.length;\n- if (len > 2) {\n- var p1, p2;\n- for (var i = 0; i < len - 1; i++) {\n- p1 = ring.components[i];\n- p2 = ring.components[i + 1];\n- area += OpenLayers.Util.rad(p2.x - p1.x) *\n- (2 + Math.sin(OpenLayers.Util.rad(p1.y)) +\n- Math.sin(OpenLayers.Util.rad(p2.y)));\n- }\n- area = area * 6378137.0 * 6378137.0 / 2.0;\n+ /**\n+ * APIMethod: register\n+ * Register an event on the events object.\n+ *\n+ * When the event is triggered, the 'func' function will be called, in the\n+ * context of 'obj'. Imagine we were to register an event, specifying an \n+ * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the \n+ * context in the callback function will be our Bounds object. This means\n+ * that within our callback function, we can access the properties and \n+ * methods of the Bounds object through the \"this\" variable. So our \n+ * callback could execute something like: \n+ * : leftStr = \"Left: \" + this.left;\n+ * \n+ * or\n+ * \n+ * : centerStr = \"Center: \" + this.getCenterLonLat();\n+ *\n+ * Parameters:\n+ * type - {String} Name of the event to register\n+ * obj - {Object} The object to bind the context to for the callback#.\n+ * If no object is specified, default is the Events's 'object' property.\n+ * func - {Function} The callback function. If no callback is \n+ * specified, this function does nothing.\n+ * priority - {Boolean|Object} If true, adds the new listener to the\n+ * *front* of the events queue instead of to the end.\n+ *\n+ * Valid options for priority:\n+ * extension - {Boolean} If true, then the event will be registered as\n+ * extension event. Extension events are handled before all other\n+ * events.\n+ */\n+ register: function(type, obj, func, priority) {\n+ if (type in OpenLayers.Events && !this.extensions[type]) {\n+ this.extensions[type] = new OpenLayers.Events[type](this);\n+ }\n+ if (func != null) {\n+ if (obj == null) {\n+ obj = this.object;\n }\n- return area;\n- },\n-\n- /**\n- * Method: containsPoint\n- * Test if a point is inside a linear ring. For the case where a point\n- * is coincident with a linear ring edge, returns 1. Otherwise,\n- * returns boolean.\n- *\n- * Parameters:\n- * point - {}\n- *\n- * Returns:\n- * {Boolean | Number} The point is inside the linear ring. Returns 1 if\n- * the point is coincident with an edge. Returns boolean otherwise.\n- */\n- containsPoint: function(point) {\n- var approx = OpenLayers.Number.limitSigDigs;\n- var digs = 14;\n- var px = approx(point.x, digs);\n- var py = approx(point.y, digs);\n-\n- function getX(y, x1, y1, x2, y2) {\n- return (y - y2) * ((x2 - x1) / (y2 - y1)) + x2;\n+ var listeners = this.listeners[type];\n+ if (!listeners) {\n+ listeners = [];\n+ this.listeners[type] = listeners;\n+ this.extensionCount[type] = 0;\n }\n- var numSeg = this.components.length - 1;\n- var start, end, x1, y1, x2, y2, cx, cy;\n- var crosses = 0;\n- for (var i = 0; i < numSeg; ++i) {\n- start = this.components[i];\n- x1 = approx(start.x, digs);\n- y1 = approx(start.y, digs);\n- end = this.components[i + 1];\n- x2 = approx(end.x, digs);\n- y2 = approx(end.y, digs);\n-\n- /**\n- * The following conditions enforce five edge-crossing rules:\n- * 1. points coincident with edges are considered contained;\n- * 2. an upward edge includes its starting endpoint, and\n- * excludes its final endpoint;\n- * 3. a downward edge excludes its starting endpoint, and\n- * includes its final endpoint;\n- * 4. horizontal edges are excluded; and\n- * 5. the edge-ray intersection point must be strictly right\n- * of the point P.\n- */\n- if (y1 == y2) {\n- // horizontal edge\n- if (py == y1) {\n- // point on horizontal line\n- if (x1 <= x2 && (px >= x1 && px <= x2) || // right or vert\n- x1 >= x2 && (px <= x1 && px >= x2)) { // left or vert\n- // point on edge\n- crosses = -1;\n- break;\n- }\n- }\n- // ignore other horizontal edges\n- continue;\n- }\n- cx = approx(getX(py, x1, y1, x2, y2), digs);\n- if (cx == px) {\n- // point on line\n- if (y1 < y2 && (py >= y1 && py <= y2) || // upward\n- y1 > y2 && (py <= y1 && py >= y2)) { // downward\n- // point on edge\n- crosses = -1;\n- break;\n- }\n- }\n- if (cx <= px) {\n- // no crossing to the right\n- continue;\n- }\n- if (x1 != x2 && (cx < Math.min(x1, x2) || cx > Math.max(x1, x2))) {\n- // no crossing\n- continue;\n- }\n- if (y1 < y2 && (py >= y1 && py < y2) || // upward\n- y1 > y2 && (py < y1 && py >= y2)) { // downward\n- ++crosses;\n+ var listener = {\n+ obj: obj,\n+ func: func\n+ };\n+ if (priority) {\n+ listeners.splice(this.extensionCount[type], 0, listener);\n+ if (typeof priority === \"object\" && priority.extension) {\n+ this.extensionCount[type]++;\n }\n- }\n- var contained = (crosses == -1) ?\n- // on edge\n- 1 :\n- // even (out) or odd (in)\n- !!(crosses & 1);\n-\n- return contained;\n- },\n-\n- /**\n- * APIMethod: intersects\n- * Determine if the input geometry intersects this one.\n- *\n- * Parameters:\n- * geometry - {} Any type of geometry.\n- *\n- * Returns:\n- * {Boolean} The input geometry intersects this one.\n- */\n- intersects: function(geometry) {\n- var intersect = false;\n- if (geometry.CLASS_NAME == \"OpenLayers.Geometry.Point\") {\n- intersect = this.containsPoint(geometry);\n- } else if (geometry.CLASS_NAME == \"OpenLayers.Geometry.LineString\") {\n- intersect = geometry.intersects(this);\n- } else if (geometry.CLASS_NAME == \"OpenLayers.Geometry.LinearRing\") {\n- intersect = OpenLayers.Geometry.LineString.prototype.intersects.apply(\n- this, [geometry]\n- );\n } else {\n- // check for component intersections\n- for (var i = 0, len = geometry.components.length; i < len; ++i) {\n- intersect = geometry.components[i].intersects(this);\n- if (intersect) {\n- break;\n- }\n- }\n- }\n- return intersect;\n- },\n-\n- /**\n- * APIMethod: getVertices\n- * Return a list of all points in this geometry.\n- *\n- * Parameters:\n- * nodes - {Boolean} For lines, only return vertices that are\n- * endpoints. If false, for lines, only vertices that are not\n- * endpoints will be returned. If not provided, all vertices will\n- * be returned.\n- *\n- * Returns:\n- * {Array} A list of all vertices in the geometry.\n- */\n- getVertices: function(nodes) {\n- return (nodes === true) ? [] : this.components.slice(0, this.components.length - 1);\n- },\n-\n- CLASS_NAME: \"OpenLayers.Geometry.LinearRing\"\n- });\n-/* ======================================================================\n- OpenLayers/Geometry/Polygon.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/Geometry/Collection.js\n- * @requires OpenLayers/Geometry/LinearRing.js\n- */\n-\n-/**\n- * Class: OpenLayers.Geometry.Polygon \n- * Polygon is a collection of Geometry.LinearRings. \n- * \n- * Inherits from:\n- * - \n- * - \n- */\n-OpenLayers.Geometry.Polygon = OpenLayers.Class(\n- OpenLayers.Geometry.Collection, {\n-\n- /**\n- * Property: componentTypes\n- * {Array(String)} An array of class names representing the types of\n- * components that the collection can include. A null value means the\n- * component types are not restricted.\n- */\n- componentTypes: [\"OpenLayers.Geometry.LinearRing\"],\n-\n- /**\n- * Constructor: OpenLayers.Geometry.Polygon\n- * Constructor for a Polygon geometry. \n- * The first ring (this.component[0])is the outer bounds of the polygon and \n- * all subsequent rings (this.component[1-n]) are internal holes.\n- *\n- *\n- * Parameters:\n- * components - {Array()} \n- */\n-\n- /** \n- * APIMethod: getArea\n- * Calculated by subtracting the areas of the internal holes from the \n- * area of the outer hole.\n- * \n- * Returns:\n- * {float} The area of the geometry\n- */\n- getArea: function() {\n- var area = 0.0;\n- if (this.components && (this.components.length > 0)) {\n- area += Math.abs(this.components[0].getArea());\n- for (var i = 1, len = this.components.length; i < len; i++) {\n- area -= Math.abs(this.components[i].getArea());\n- }\n+ listeners.push(listener);\n }\n- return area;\n- },\n+ }\n+ },\n \n- /** \n- * APIMethod: getGeodesicArea\n- * Calculate the approximate area of the polygon were it projected onto\n- * the earth.\n- *\n- * Parameters:\n- * projection - {} The spatial reference system\n- * for the geometry coordinates. If not provided, Geographic/WGS84 is\n- * assumed.\n- * \n- * Reference:\n- * Robert. G. Chamberlain and William H. Duquette, \"Some Algorithms for\n- * Polygons on a Sphere\", JPL Publication 07-03, Jet Propulsion\n- * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409\n- *\n- * Returns:\n- * {float} The approximate geodesic area of the polygon in square meters.\n- */\n- getGeodesicArea: function(projection) {\n- var area = 0.0;\n- if (this.components && (this.components.length > 0)) {\n- area += Math.abs(this.components[0].getGeodesicArea(projection));\n- for (var i = 1, len = this.components.length; i < len; i++) {\n- area -= Math.abs(this.components[i].getGeodesicArea(projection));\n- }\n- }\n- return area;\n- },\n+ /**\n+ * APIMethod: registerPriority\n+ * Same as register() but adds the new listener to the *front* of the\n+ * events queue instead of to the end.\n+ * \n+ * TODO: get rid of this in 3.0 - Decide whether listeners should be \n+ * called in the order they were registered or in reverse order.\n+ *\n+ *\n+ * Parameters:\n+ * type - {String} Name of the event to register\n+ * obj - {Object} The object to bind the context to for the callback#.\n+ * If no object is specified, default is the Events's \n+ * 'object' property.\n+ * func - {Function} The callback function. If no callback is \n+ * specified, this function does nothing.\n+ */\n+ registerPriority: function(type, obj, func) {\n+ this.register(type, obj, func, true);\n+ },\n \n- /**\n- * Method: containsPoint\n- * Test if a point is inside a polygon. Points on a polygon edge are\n- * considered inside.\n- *\n- * Parameters:\n- * point - {}\n- *\n- * Returns:\n- * {Boolean | Number} The point is inside the polygon. Returns 1 if the\n- * point is on an edge. Returns boolean otherwise.\n- */\n- containsPoint: function(point) {\n- var numRings = this.components.length;\n- var contained = false;\n- if (numRings > 0) {\n- // check exterior ring - 1 means on edge, boolean otherwise\n- contained = this.components[0].containsPoint(point);\n- if (contained !== 1) {\n- if (contained && numRings > 1) {\n- // check interior rings\n- var hole;\n- for (var i = 1; i < numRings; ++i) {\n- hole = this.components[i].containsPoint(point);\n- if (hole) {\n- if (hole === 1) {\n- // on edge\n- contained = 1;\n- } else {\n- // in hole\n- contained = false;\n- }\n- break;\n- }\n- }\n- }\n- }\n+ /**\n+ * APIMethod: un\n+ * Convenience method for unregistering listeners with a common scope.\n+ * Internally, this method calls as shown in the examples\n+ * below.\n+ *\n+ * Example use:\n+ * (code)\n+ * // unregister a single listener for the \"loadstart\" event\n+ * events.un({\"loadstart\": loadStartListener});\n+ *\n+ * // this is equivalent to the following\n+ * events.unregister(\"loadstart\", undefined, loadStartListener);\n+ *\n+ * // unregister multiple listeners with the same `this` object\n+ * events.un({\n+ * \"loadstart\": loadStartListener,\n+ * \"loadend\": loadEndListener,\n+ * scope: object\n+ * });\n+ *\n+ * // this is equivalent to the following\n+ * events.unregister(\"loadstart\", object, loadStartListener);\n+ * events.unregister(\"loadend\", object, loadEndListener);\n+ * (end)\n+ */\n+ un: function(object) {\n+ for (var type in object) {\n+ if (type != \"scope\" && object.hasOwnProperty(type)) {\n+ this.unregister(type, object.scope, object[type]);\n }\n- return contained;\n- },\n+ }\n+ },\n \n- /**\n- * APIMethod: intersects\n- * Determine if the input geometry intersects this one.\n- *\n- * Parameters:\n- * geometry - {} Any type of geometry.\n- *\n- * Returns:\n- * {Boolean} The input geometry intersects this one.\n- */\n- intersects: function(geometry) {\n- var intersect = false;\n- var i, len;\n- if (geometry.CLASS_NAME == \"OpenLayers.Geometry.Point\") {\n- intersect = this.containsPoint(geometry);\n- } else if (geometry.CLASS_NAME == \"OpenLayers.Geometry.LineString\" ||\n- geometry.CLASS_NAME == \"OpenLayers.Geometry.LinearRing\") {\n- // check if rings/linestrings intersect\n- for (i = 0, len = this.components.length; i < len; ++i) {\n- intersect = geometry.intersects(this.components[i]);\n- if (intersect) {\n- break;\n- }\n- }\n- if (!intersect) {\n- // check if this poly contains points of the ring/linestring\n- for (i = 0, len = geometry.components.length; i < len; ++i) {\n- intersect = this.containsPoint(geometry.components[i]);\n- if (intersect) {\n- break;\n- }\n- }\n- }\n- } else {\n- for (i = 0, len = geometry.components.length; i < len; ++i) {\n- intersect = this.intersects(geometry.components[i]);\n- if (intersect) {\n- break;\n- }\n- }\n- }\n- // check case where this poly is wholly contained by another\n- if (!intersect && geometry.CLASS_NAME == \"OpenLayers.Geometry.Polygon\") {\n- // exterior ring points will be contained in the other geometry\n- var ring = this.components[0];\n- for (i = 0, len = ring.components.length; i < len; ++i) {\n- intersect = geometry.containsPoint(ring.components[i]);\n- if (intersect) {\n- break;\n- }\n+ /**\n+ * APIMethod: unregister\n+ *\n+ * Parameters:\n+ * type - {String} \n+ * obj - {Object} If none specified, defaults to this.object\n+ * func - {Function} \n+ */\n+ unregister: function(type, obj, func) {\n+ if (obj == null) {\n+ obj = this.object;\n+ }\n+ var listeners = this.listeners[type];\n+ if (listeners != null) {\n+ for (var i = 0, len = listeners.length; i < len; i++) {\n+ if (listeners[i].obj == obj && listeners[i].func == func) {\n+ listeners.splice(i, 1);\n+ break;\n }\n }\n- return intersect;\n- },\n-\n- /**\n- * APIMethod: distanceTo\n- * Calculate the closest distance between two geometries (on the x-y plane).\n- *\n- * Parameters:\n- * geometry - {} The target geometry.\n- * options - {Object} Optional properties for configuring the distance\n- * calculation.\n- *\n- * Valid options:\n- * details - {Boolean} Return details from the distance calculation.\n- * Default is false.\n- * edge - {Boolean} Calculate the distance from this geometry to the\n- * nearest edge of the target geometry. Default is true. If true,\n- * calling distanceTo from a geometry that is wholly contained within\n- * the target will result in a non-zero distance. If false, whenever\n- * geometries intersect, calling distanceTo will return 0. If false,\n- * details cannot be returned.\n- *\n- * Returns:\n- * {Number | Object} The distance between this geometry and the target.\n- * If details is true, the return will be an object with distance,\n- * x0, y0, x1, and y1 properties. The x0 and y0 properties represent\n- * the coordinates of the closest point on this geometry. The x1 and y1\n- * properties represent the coordinates of the closest point on the\n- * target geometry.\n- */\n- distanceTo: function(geometry, options) {\n- var edge = !(options && options.edge === false);\n- var result;\n- // this is the case where we might not be looking for distance to edge\n- if (!edge && this.intersects(geometry)) {\n- result = 0;\n- } else {\n- result = OpenLayers.Geometry.Collection.prototype.distanceTo.apply(\n- this, [geometry, options]\n- );\n- }\n- return result;\n- },\n-\n- CLASS_NAME: \"OpenLayers.Geometry.Polygon\"\n- });\n-\n-/**\n- * APIMethod: createRegularPolygon\n- * Create a regular polygon around a radius. Useful for creating circles \n- * and the like.\n- *\n- * Parameters:\n- * origin - {} center of polygon.\n- * radius - {Float} distance to vertex, in map units.\n- * sides - {Integer} Number of sides. 20 approximates a circle.\n- * rotation - {Float} original angle of rotation, in degrees.\n- */\n-OpenLayers.Geometry.Polygon.createRegularPolygon = function(origin, radius, sides, rotation) {\n- var angle = Math.PI * ((1 / sides) - (1 / 2));\n- if (rotation) {\n- angle += (rotation / 180) * Math.PI;\n- }\n- var rotatedAngle, x, y;\n- var points = [];\n- for (var i = 0; i < sides; ++i) {\n- rotatedAngle = angle + (i * 2 * Math.PI / sides);\n- x = origin.x + (radius * Math.cos(rotatedAngle));\n- y = origin.y + (radius * Math.sin(rotatedAngle));\n- points.push(new OpenLayers.Geometry.Point(x, y));\n- }\n- var ring = new OpenLayers.Geometry.LinearRing(points);\n- return new OpenLayers.Geometry.Polygon([ring]);\n-};\n-/* ======================================================================\n- OpenLayers/Geometry/MultiPolygon.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/Geometry/Collection.js\n- * @requires OpenLayers/Geometry/Polygon.js\n- */\n-\n-/**\n- * Class: OpenLayers.Geometry.MultiPolygon\n- * MultiPolygon is a geometry with multiple \n- * components. Create a new instance with the \n- * constructor.\n- * \n- * Inherits from:\n- * - \n- */\n-OpenLayers.Geometry.MultiPolygon = OpenLayers.Class(\n- OpenLayers.Geometry.Collection, {\n+ }\n+ },\n \n- /**\n- * Property: componentTypes\n- * {Array(String)} An array of class names representing the types of\n- * components that the collection can include. A null value means the\n- * component types are not restricted.\n- */\n- componentTypes: [\"OpenLayers.Geometry.Polygon\"],\n+ /** \n+ * Method: remove\n+ * Remove all listeners for a given event type. If type is not registered,\n+ * does nothing.\n+ *\n+ * Parameters:\n+ * type - {String} \n+ */\n+ remove: function(type) {\n+ if (this.listeners[type] != null) {\n+ this.listeners[type] = [];\n+ }\n+ },\n \n- /**\n- * Constructor: OpenLayers.Geometry.MultiPolygon\n- * Create a new MultiPolygon geometry\n- *\n- * Parameters:\n- * components - {Array()} An array of polygons\n- * used to generate the MultiPolygon\n- *\n- */\n+ /**\n+ * APIMethod: triggerEvent\n+ * Trigger a specified registered event. \n+ * \n+ * Parameters:\n+ * type - {String} \n+ * evt - {Event || Object} will be passed to the listeners.\n+ *\n+ * Returns:\n+ * {Boolean} The last listener return. If a listener returns false, the\n+ * chain of listeners will stop getting called.\n+ */\n+ triggerEvent: function(type, evt) {\n+ var listeners = this.listeners[type];\n \n- CLASS_NAME: \"OpenLayers.Geometry.MultiPolygon\"\n- });\n-/* ======================================================================\n- OpenLayers/Format/WKT.js\n- ====================================================================== */\n+ // fast path\n+ if (!listeners || listeners.length == 0) {\n+ return undefined;\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+ // prep evt object with object & div references\n+ if (evt == null) {\n+ evt = {};\n+ }\n+ evt.object = this.object;\n+ evt.element = this.element;\n+ if (!evt.type) {\n+ evt.type = type;\n+ }\n \n-/**\n- * @requires OpenLayers/Format.js\n- * @requires OpenLayers/Feature/Vector.js\n- * @requires OpenLayers/Geometry/Point.js\n- * @requires OpenLayers/Geometry/MultiPoint.js\n- * @requires OpenLayers/Geometry/LineString.js\n- * @requires OpenLayers/Geometry/MultiLineString.js\n- * @requires OpenLayers/Geometry/Polygon.js\n- * @requires OpenLayers/Geometry/MultiPolygon.js\n- */\n+ // execute all callbacks registered for specified type\n+ // get a clone of the listeners array to\n+ // allow for splicing during callbacks\n+ listeners = listeners.slice();\n+ var continueChain;\n+ for (var i = 0, len = listeners.length; i < len; i++) {\n+ var callback = listeners[i];\n+ // bind the context to callback.obj\n+ continueChain = callback.func.apply(callback.obj, [evt]);\n \n-/**\n- * Class: OpenLayers.Format.WKT\n- * Class for reading and writing Well-Known Text. Create a new instance\n- * with the constructor.\n- * \n- * Inherits from:\n- * - \n- */\n-OpenLayers.Format.WKT = OpenLayers.Class(OpenLayers.Format, {\n+ if ((continueChain != undefined) && (continueChain == false)) {\n+ // if callback returns false, execute no more callbacks.\n+ break;\n+ }\n+ }\n+ // don't fall through to other DOM elements\n+ if (!this.fallThrough) {\n+ OpenLayers.Event.stop(evt, true);\n+ }\n+ return continueChain;\n+ },\n \n /**\n- * Constructor: OpenLayers.Format.WKT\n- * Create a new parser for WKT\n+ * Method: handleBrowserEvent\n+ * Basically just a wrapper to the triggerEvent() function, but takes \n+ * care to set a property 'xy' on the event with the current mouse \n+ * position.\n *\n * Parameters:\n- * options - {Object} An optional object whose properties will be set on\n- * this instance\n- *\n- * Returns:\n- * {} A new WKT parser.\n+ * evt - {Event} \n */\n- initialize: function(options) {\n- this.regExes = {\n- 'typeStr': /^\\s*(\\w+)\\s*\\(\\s*(.*)\\s*\\)\\s*$/,\n- 'spaces': /\\s+/,\n- 'parenComma': /\\)\\s*,\\s*\\(/,\n- 'doubleParenComma': /\\)\\s*\\)\\s*,\\s*\\(\\s*\\(/, // can't use {2} here\n- 'trimParens': /^\\s*\\(?(.*?)\\)?\\s*$/\n- };\n- OpenLayers.Format.prototype.initialize.apply(this, [options]);\n+ handleBrowserEvent: function(evt) {\n+ var type = evt.type,\n+ listeners = this.listeners[type];\n+ if (!listeners || listeners.length == 0) {\n+ // noone's listening, bail out\n+ return;\n+ }\n+ // add clientX & clientY to all events - corresponds to average x, y\n+ var touches = evt.touches;\n+ if (touches && touches[0]) {\n+ var x = 0;\n+ var y = 0;\n+ var num = touches.length;\n+ var touch;\n+ for (var i = 0; i < num; ++i) {\n+ touch = this.getTouchClientXY(touches[i]);\n+ x += touch.clientX;\n+ y += touch.clientY;\n+ }\n+ evt.clientX = x / num;\n+ evt.clientY = y / num;\n+ }\n+ if (this.includeXY) {\n+ evt.xy = this.getMousePosition(evt);\n+ }\n+ this.triggerEvent(type, evt);\n },\n \n /**\n- * APIMethod: read\n- * Deserialize a WKT string and return a vector feature or an\n- * array of vector features. Supports WKT for POINT, MULTIPOINT,\n- * LINESTRING, MULTILINESTRING, POLYGON, MULTIPOLYGON, and\n- * GEOMETRYCOLLECTION.\n+ * Method: getTouchClientXY\n+ * WebKit has a few bugs for clientX/clientY. This method detects them\n+ * and calculate the correct values.\n *\n * Parameters:\n- * wkt - {String} A WKT string\n- *\n+ * evt - {Touch} a Touch object from a TouchEvent\n+ * \n * Returns:\n- * {|Array} A feature or array of features for\n- * GEOMETRYCOLLECTION WKT.\n+ * {Object} An object with only clientX and clientY properties with the\n+ * calculated values.\n */\n- read: function(wkt) {\n- var features, type, str;\n- wkt = wkt.replace(/[\\n\\r]/g, \" \");\n- var matches = this.regExes.typeStr.exec(wkt);\n- if (matches) {\n- type = matches[1].toLowerCase();\n- str = matches[2];\n- if (this.parse[type]) {\n- features = this.parse[type].apply(this, [str]);\n- }\n- if (this.internalProjection && this.externalProjection) {\n- if (features &&\n- features.CLASS_NAME == \"OpenLayers.Feature.Vector\") {\n- features.geometry.transform(this.externalProjection,\n- this.internalProjection);\n- } else if (features &&\n- type != \"geometrycollection\" &&\n- typeof features == \"object\") {\n- for (var i = 0, len = features.length; i < len; i++) {\n- var component = features[i];\n- component.geometry.transform(this.externalProjection,\n- this.internalProjection);\n- }\n- }\n- }\n+ getTouchClientXY: function(evt) {\n+ // olMochWin is to override window, used for testing\n+ var win = window.olMockWin || window,\n+ winPageX = win.pageXOffset,\n+ winPageY = win.pageYOffset,\n+ x = evt.clientX,\n+ y = evt.clientY;\n+\n+ if (evt.pageY === 0 && Math.floor(y) > Math.floor(evt.pageY) ||\n+ evt.pageX === 0 && Math.floor(x) > Math.floor(evt.pageX)) {\n+ // iOS4 include scroll offset in clientX/Y\n+ x = x - winPageX;\n+ y = y - winPageY;\n+ } else if (y < (evt.pageY - winPageY) || x < (evt.pageX - winPageX)) {\n+ // Some Android browsers have totally bogus values for clientX/Y\n+ // when scrolling/zooming a page\n+ x = evt.pageX - winPageX;\n+ y = evt.pageY - winPageY;\n }\n- return features;\n+\n+ evt.olClientX = x;\n+ evt.olClientY = y;\n+\n+ return {\n+ clientX: x,\n+ clientY: y\n+ };\n },\n \n /**\n- * APIMethod: write\n- * Serialize a feature or array of features into a WKT string.\n- *\n+ * APIMethod: clearMouseCache\n+ * Clear cached data about the mouse position. This should be called any \n+ * time the element that events are registered on changes position \n+ * within the page.\n+ */\n+ clearMouseCache: function() {\n+ this.element.scrolls = null;\n+ this.element.lefttop = null;\n+ this.element.offsets = null;\n+ },\n+\n+ /**\n+ * Method: getMousePosition\n+ * \n * Parameters:\n- * features - {|Array} A feature or array of\n- * features\n- *\n+ * evt - {Event} \n+ * \n * Returns:\n- * {String} The WKT string representation of the input geometries\n+ * {} The current xy coordinate of the mouse, adjusted\n+ * for offsets\n */\n- write: function(features) {\n- var collection, geometry, isCollection;\n- if (features.constructor == Array) {\n- collection = features;\n- isCollection = true;\n- } else {\n- collection = [features];\n- isCollection = false;\n+ getMousePosition: function(evt) {\n+ if (!this.includeXY) {\n+ this.clearMouseCache();\n+ } else if (!this.element.hasScrollEvent) {\n+ OpenLayers.Event.observe(window, \"scroll\", this.clearMouseListener);\n+ this.element.hasScrollEvent = true;\n }\n- var pieces = [];\n- if (isCollection) {\n- pieces.push('GEOMETRYCOLLECTION(');\n+\n+ if (!this.element.scrolls) {\n+ var viewportElement = OpenLayers.Util.getViewportElement();\n+ this.element.scrolls = [\n+ window.pageXOffset || viewportElement.scrollLeft,\n+ window.pageYOffset || viewportElement.scrollTop\n+ ];\n }\n- for (var i = 0, len = collection.length; i < len; ++i) {\n- if (isCollection && i > 0) {\n- pieces.push(',');\n- }\n- geometry = collection[i].geometry;\n- pieces.push(this.extractGeometry(geometry));\n+\n+ if (!this.element.lefttop) {\n+ this.element.lefttop = [\n+ (document.documentElement.clientLeft || 0),\n+ (document.documentElement.clientTop || 0)\n+ ];\n }\n- if (isCollection) {\n- pieces.push(')');\n+\n+ if (!this.element.offsets) {\n+ this.element.offsets = OpenLayers.Util.pagePosition(this.element);\n }\n- return pieces.join('');\n+\n+ return new OpenLayers.Pixel(\n+ (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0] -\n+ this.element.lefttop[0],\n+ (evt.clientY + this.element.scrolls[1]) - this.element.offsets[1] -\n+ this.element.lefttop[1]\n+ );\n },\n \n /**\n- * Method: extractGeometry\n- * Entry point to construct the WKT for a single Geometry object.\n+ * Method: addMsTouchListener\n *\n * Parameters:\n- * geometry - {}\n- *\n- * Returns:\n- * {String} A WKT string of representing the geometry\n+ * element - {DOMElement} The DOM element to register the listener on\n+ * type - {String} The event type\n+ * handler - {Function} the handler\n */\n- extractGeometry: function(geometry) {\n- var type = geometry.CLASS_NAME.split('.')[2].toLowerCase();\n- if (!this.extract[type]) {\n- return null;\n+ addMsTouchListener: function(element, type, handler) {\n+ var eventHandler = this.eventHandler;\n+ var touches = this._msTouches;\n+\n+ function msHandler(evt) {\n+ handler(OpenLayers.Util.applyDefaults({\n+ stopPropagation: function() {\n+ for (var i = touches.length - 1; i >= 0; --i) {\n+ touches[i].stopPropagation();\n+ }\n+ },\n+ preventDefault: function() {\n+ for (var i = touches.length - 1; i >= 0; --i) {\n+ touches[i].preventDefault();\n+ }\n+ },\n+ type: type\n+ }, evt));\n }\n- if (this.internalProjection && this.externalProjection) {\n- geometry = geometry.clone();\n- geometry.transform(this.internalProjection, this.externalProjection);\n+\n+ switch (type) {\n+ case 'touchstart':\n+ return this.addMsTouchListenerStart(element, type, msHandler);\n+ case 'touchend':\n+ return this.addMsTouchListenerEnd(element, type, msHandler);\n+ case 'touchmove':\n+ return this.addMsTouchListenerMove(element, type, msHandler);\n+ default:\n+ throw 'Unknown touch event type';\n }\n- var wktType = type == 'collection' ? 'GEOMETRYCOLLECTION' : type.toUpperCase();\n- var data = wktType + '(' + this.extract[type].apply(this, [geometry]) + ')';\n- return data;\n },\n \n /**\n- * Object with properties corresponding to the geometry types.\n- * Property values are functions that do the actual data extraction.\n+ * Method: addMsTouchListenerStart\n+ *\n+ * Parameters:\n+ * element - {DOMElement} The DOM element to register the listener on\n+ * type - {String} The event type\n+ * handler - {Function} the handler\n */\n- extract: {\n- /**\n- * Return a space delimited string of point coordinates.\n- * @param {OpenLayers.Geometry.Point} point\n- * @returns {String} A string of coordinates representing the point\n- */\n- 'point': function(point) {\n- return point.x + ' ' + point.y;\n- },\n+ addMsTouchListenerStart: function(element, type, handler) {\n+ var touches = this._msTouches;\n \n- /**\n- * Return a comma delimited string of point coordinates from a multipoint.\n- * @param {OpenLayers.Geometry.MultiPoint} multipoint\n- * @returns {String} A string of point coordinate strings representing\n- * the multipoint\n- */\n- 'multipoint': function(multipoint) {\n- var array = [];\n- for (var i = 0, len = multipoint.components.length; i < len; ++i) {\n- array.push('(' +\n- this.extract.point.apply(this, [multipoint.components[i]]) +\n- ')');\n- }\n- return array.join(',');\n- },\n+ var cb = function(e) {\n \n- /**\n- * Return a comma delimited string of point coordinates from a line.\n- * @param {OpenLayers.Geometry.LineString} linestring\n- * @returns {String} A string of point coordinate strings representing\n- * the linestring\n- */\n- 'linestring': function(linestring) {\n- var array = [];\n- for (var i = 0, len = linestring.components.length; i < len; ++i) {\n- array.push(this.extract.point.apply(this, [linestring.components[i]]));\n+ var alreadyInArray = false;\n+ for (var i = 0, ii = touches.length; i < ii; ++i) {\n+ if (touches[i].pointerId == e.pointerId) {\n+ alreadyInArray = true;\n+ break;\n+ }\n }\n- return array.join(',');\n- },\n-\n- /**\n- * Return a comma delimited string of linestring strings from a multilinestring.\n- * @param {OpenLayers.Geometry.MultiLineString} multilinestring\n- * @returns {String} A string of of linestring strings representing\n- * the multilinestring\n- */\n- 'multilinestring': function(multilinestring) {\n- var array = [];\n- for (var i = 0, len = multilinestring.components.length; i < len; ++i) {\n- array.push('(' +\n- this.extract.linestring.apply(this, [multilinestring.components[i]]) +\n- ')');\n+ if (!alreadyInArray) {\n+ touches.push(e);\n }\n- return array.join(',');\n- },\n \n- /**\n- * Return a comma delimited string of linear ring arrays from a polygon.\n- * @param {OpenLayers.Geometry.Polygon} polygon\n- * @returns {String} An array of linear ring arrays representing the polygon\n- */\n- 'polygon': function(polygon) {\n- var array = [];\n- for (var i = 0, len = polygon.components.length; i < len; ++i) {\n- array.push('(' +\n- this.extract.linestring.apply(this, [polygon.components[i]]) +\n- ')');\n- }\n- return array.join(',');\n- },\n+ e.touches = touches.slice();\n+ handler(e);\n+ };\n \n- /**\n- * Return an array of polygon arrays from a multipolygon.\n- * @param {OpenLayers.Geometry.MultiPolygon} multipolygon\n- * @returns {String} An array of polygon arrays representing\n- * the multipolygon\n- */\n- 'multipolygon': function(multipolygon) {\n- var array = [];\n- for (var i = 0, len = multipolygon.components.length; i < len; ++i) {\n- array.push('(' +\n- this.extract.polygon.apply(this, [multipolygon.components[i]]) +\n- ')');\n- }\n- return array.join(',');\n- },\n+ OpenLayers.Event.observe(element, 'MSPointerDown', cb);\n \n- /**\n- * Return the WKT portion between 'GEOMETRYCOLLECTION(' and ')' for an \n- * @param {OpenLayers.Geometry.Collection} collection\n- * @returns {String} internal WKT representation of the collection\n- */\n- 'collection': function(collection) {\n- var array = [];\n- for (var i = 0, len = collection.components.length; i < len; ++i) {\n- array.push(this.extractGeometry.apply(this, [collection.components[i]]));\n+ // Need to also listen for end events to keep the _msTouches list\n+ // accurate\n+ var internalCb = function(e) {\n+ for (var i = 0, ii = touches.length; i < ii; ++i) {\n+ if (touches[i].pointerId == e.pointerId) {\n+ touches.splice(i, 1);\n+ break;\n+ }\n }\n- return array.join(',');\n- }\n-\n+ };\n+ OpenLayers.Event.observe(element, 'MSPointerUp', internalCb);\n },\n \n /**\n- * Object with properties corresponding to the geometry types.\n- * Property values are functions that do the actual parsing.\n+ * Method: addMsTouchListenerMove\n+ *\n+ * Parameters:\n+ * element - {DOMElement} The DOM element to register the listener on\n+ * type - {String} The event type\n+ * handler - {Function} the handler\n */\n- parse: {\n- /**\n- * Return point feature given a point WKT fragment.\n- * @param {String} str A WKT fragment representing the point\n- * @returns {OpenLayers.Feature.Vector} A point feature\n- * @private\n- */\n- 'point': function(str) {\n- var coords = OpenLayers.String.trim(str).split(this.regExes.spaces);\n- return new OpenLayers.Feature.Vector(\n- new OpenLayers.Geometry.Point(coords[0], coords[1])\n- );\n- },\n+ addMsTouchListenerMove: function(element, type, handler) {\n+ var touches = this._msTouches;\n+ var cb = function(e) {\n \n- /**\n- * Return a multipoint feature given a multipoint WKT fragment.\n- * @param {String} str A WKT fragment representing the multipoint\n- * @returns {OpenLayers.Feature.Vector} A multipoint feature\n- * @private\n- */\n- 'multipoint': function(str) {\n- var point;\n- var points = OpenLayers.String.trim(str).split(',');\n- var components = [];\n- for (var i = 0, len = points.length; i < len; ++i) {\n- point = points[i].replace(this.regExes.trimParens, '$1');\n- components.push(this.parse.point.apply(this, [point]).geometry);\n+ //Don't fire touch moves when mouse isn't down\n+ if (e.pointerType == e.MSPOINTER_TYPE_MOUSE && e.buttons == 0) {\n+ return;\n }\n- return new OpenLayers.Feature.Vector(\n- new OpenLayers.Geometry.MultiPoint(components)\n- );\n- },\n \n- /**\n- * Return a linestring feature given a linestring WKT fragment.\n- * @param {String} str A WKT fragment representing the linestring\n- * @returns {OpenLayers.Feature.Vector} A linestring feature\n- * @private\n- */\n- 'linestring': function(str) {\n- var points = OpenLayers.String.trim(str).split(',');\n- var components = [];\n- for (var i = 0, len = points.length; i < len; ++i) {\n- components.push(this.parse.point.apply(this, [points[i]]).geometry);\n+ if (touches.length == 1 && touches[0].pageX == e.pageX &&\n+ touches[0].pageY == e.pageY) {\n+ // don't trigger event when pointer has not moved\n+ return;\n }\n- return new OpenLayers.Feature.Vector(\n- new OpenLayers.Geometry.LineString(components)\n- );\n- },\n-\n- /**\n- * Return a multilinestring feature given a multilinestring WKT fragment.\n- * @param {String} str A WKT fragment representing the multilinestring\n- * @returns {OpenLayers.Feature.Vector} A multilinestring feature\n- * @private\n- */\n- 'multilinestring': function(str) {\n- var line;\n- var lines = OpenLayers.String.trim(str).split(this.regExes.parenComma);\n- var components = [];\n- for (var i = 0, len = lines.length; i < len; ++i) {\n- line = lines[i].replace(this.regExes.trimParens, '$1');\n- components.push(this.parse.linestring.apply(this, [line]).geometry);\n+ for (var i = 0, ii = touches.length; i < ii; ++i) {\n+ if (touches[i].pointerId == e.pointerId) {\n+ touches[i] = e;\n+ break;\n+ }\n }\n- return new OpenLayers.Feature.Vector(\n- new OpenLayers.Geometry.MultiLineString(components)\n- );\n- },\n \n- /**\n- * Return a polygon feature given a polygon WKT fragment.\n- * @param {String} str A WKT fragment representing the polygon\n- * @returns {OpenLayers.Feature.Vector} A polygon feature\n- * @private\n- */\n- 'polygon': function(str) {\n- var ring, linestring, linearring;\n- var rings = OpenLayers.String.trim(str).split(this.regExes.parenComma);\n- var components = [];\n- for (var i = 0, len = rings.length; i < len; ++i) {\n- ring = rings[i].replace(this.regExes.trimParens, '$1');\n- linestring = this.parse.linestring.apply(this, [ring]).geometry;\n- linearring = new OpenLayers.Geometry.LinearRing(linestring.components);\n- components.push(linearring);\n- }\n- return new OpenLayers.Feature.Vector(\n- new OpenLayers.Geometry.Polygon(components)\n- );\n- },\n+ e.touches = touches.slice();\n+ handler(e);\n+ };\n \n- /**\n- * Return a multipolygon feature given a multipolygon WKT fragment.\n- * @param {String} str A WKT fragment representing the multipolygon\n- * @returns {OpenLayers.Feature.Vector} A multipolygon feature\n- * @private\n- */\n- 'multipolygon': function(str) {\n- var polygon;\n- var polygons = OpenLayers.String.trim(str).split(this.regExes.doubleParenComma);\n- var components = [];\n- for (var i = 0, len = polygons.length; i < len; ++i) {\n- polygon = polygons[i].replace(this.regExes.trimParens, '$1');\n- components.push(this.parse.polygon.apply(this, [polygon]).geometry);\n- }\n- return new OpenLayers.Feature.Vector(\n- new OpenLayers.Geometry.MultiPolygon(components)\n- );\n- },\n+ OpenLayers.Event.observe(element, 'MSPointerMove', cb);\n+ },\n \n- /**\n- * Return an array of features given a geometrycollection WKT fragment.\n- * @param {String} str A WKT fragment representing the geometrycollection\n- * @returns {Array} An array of OpenLayers.Feature.Vector\n- * @private\n- */\n- 'geometrycollection': function(str) {\n- // separate components of the collection with |\n- str = str.replace(/,\\s*([A-Za-z])/g, '|$1');\n- var wktArray = OpenLayers.String.trim(str).split('|');\n- var components = [];\n- for (var i = 0, len = wktArray.length; i < len; ++i) {\n- components.push(OpenLayers.Format.WKT.prototype.read.apply(this, [wktArray[i]]));\n+ /**\n+ * Method: addMsTouchListenerEnd\n+ *\n+ * Parameters:\n+ * element - {DOMElement} The DOM element to register the listener on\n+ * type - {String} The event type\n+ * handler - {Function} the handler\n+ */\n+ addMsTouchListenerEnd: function(element, type, handler) {\n+ var touches = this._msTouches;\n+\n+ var cb = function(e) {\n+\n+ for (var i = 0, ii = touches.length; i < ii; ++i) {\n+ if (touches[i].pointerId == e.pointerId) {\n+ touches.splice(i, 1);\n+ break;\n+ }\n }\n- return components;\n- }\n \n+ e.touches = touches.slice();\n+ handler(e);\n+ };\n+\n+ OpenLayers.Event.observe(element, 'MSPointerUp', cb);\n },\n \n- CLASS_NAME: \"OpenLayers.Format.WKT\"\n+ CLASS_NAME: \"OpenLayers.Events\"\n });\n /* ======================================================================\n- OpenLayers/Format/JSON.js\n+ OpenLayers/Projection.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- * Note:\n- * This work draws heavily from the public domain JSON serializer/deserializer\n- * at http://www.json.org/json.js. Rewritten so that it doesn't modify\n- * basic data prototypes.\n- */\n-\n-/**\n- * @requires OpenLayers/Format.js\n+ * @requires OpenLayers/BaseTypes/Class.js\n+ * @requires OpenLayers/Util.js\n */\n \n /**\n- * Class: OpenLayers.Format.JSON\n- * A parser to read/write JSON safely. Create a new instance with the\n- * constructor.\n+ * Namespace: OpenLayers.Projection\n+ * Methods for coordinate transforms between coordinate systems. By default,\n+ * OpenLayers ships with the ability to transform coordinates between\n+ * geographic (EPSG:4326) and web or spherical mercator (EPSG:900913 et al.)\n+ * coordinate reference systems. See the method for details\n+ * on usage.\n *\n- * Inherits from:\n- * - \n+ * Additional transforms may be added by using the \n+ * library. If the proj4js library is included, the method \n+ * will work between any two coordinate reference systems with proj4js \n+ * definitions.\n+ *\n+ * If the proj4js library is not included, or if you wish to allow transforms\n+ * between arbitrary coordinate reference systems, use the \n+ * method to register a custom transform method.\n */\n-OpenLayers.Format.JSON = OpenLayers.Class(OpenLayers.Format, {\n-\n- /**\n- * APIProperty: indent\n- * {String} For \"pretty\" printing, the indent string will be used once for\n- * each indentation level.\n- */\n- indent: \" \",\n-\n- /**\n- * APIProperty: space\n- * {String} For \"pretty\" printing, the space string will be used after\n- * the \":\" separating a name/value pair.\n- */\n- space: \" \",\n-\n- /**\n- * APIProperty: newline\n- * {String} For \"pretty\" printing, the newline string will be used at the\n- * end of each name/value pair or array item.\n- */\n- newline: \"\\n\",\n+OpenLayers.Projection = OpenLayers.Class({\n \n /**\n- * Property: level\n- * {Integer} For \"pretty\" printing, this is incremented/decremented during\n- * serialization.\n+ * Property: proj\n+ * {Object} Proj4js.Proj instance.\n */\n- level: 0,\n+ proj: null,\n \n /**\n- * Property: pretty\n- * {Boolean} Serialize with extra whitespace for structure. This is set\n- * by the method.\n+ * Property: projCode\n+ * {String}\n */\n- pretty: false,\n+ projCode: null,\n \n /**\n- * Property: nativeJSON\n- * {Boolean} Does the browser support native json?\n+ * Property: titleRegEx\n+ * {RegExp} regular expression to strip the title from a proj4js definition\n */\n- nativeJSON: (function() {\n- return !!(window.JSON && typeof JSON.parse == \"function\" && typeof JSON.stringify == \"function\");\n- })(),\n+ titleRegEx: /\\+title=[^\\+]*/,\n \n /**\n- * Constructor: OpenLayers.Format.JSON\n- * Create a new parser for JSON.\n+ * Constructor: OpenLayers.Projection\n+ * This class offers several methods for interacting with a wrapped \n+ * pro4js projection object. \n *\n * Parameters:\n- * options - {Object} An optional object whose properties will be set on\n- * this instance.\n- */\n-\n- /**\n- * APIMethod: read\n- * Deserialize a json string.\n+ * projCode - {String} A string identifying the Well Known Identifier for\n+ * the projection.\n+ * options - {Object} An optional object to set additional properties\n+ * on the projection.\n *\n- * Parameters:\n- * json - {String} A JSON string\n- * filter - {Function} A function which will be called for every key and\n- * value at every level of the final result. Each value will be\n- * replaced by the result of the filter function. This can be used to\n- * reform generic objects into instances of classes, or to transform\n- * date strings into Date objects.\n- * \n * Returns:\n- * {Object} An object, array, string, or number .\n+ * {} A projection object.\n */\n- read: function(json, filter) {\n- var object;\n- if (this.nativeJSON) {\n- object = JSON.parse(json, filter);\n- } else try {\n- /**\n- * Parsing happens in three stages. In the first stage, we run the\n- * text against a regular expression which looks for non-JSON\n- * characters. We are especially concerned with '()' and 'new'\n- * because they can cause invocation, and '=' because it can\n- * cause mutation. But just to be safe, we will reject all\n- * unexpected characters.\n- */\n- if (/^[\\],:{}\\s]*$/.test(json.replace(/\\\\[\"\\\\\\/bfnrtu]/g, '@').replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']').replace(/(?:^|:|,)(?:\\s*\\[)+/g, ''))) {\n-\n- /**\n- * In the second stage we use the eval function to compile the\n- * text into a JavaScript structure. The '{' operator is\n- * subject to a syntactic ambiguity in JavaScript - it can\n- * begin a block or an object literal. We wrap the text in\n- * parens to eliminate the ambiguity.\n- */\n- object = eval('(' + json + ')');\n-\n- /**\n- * In the optional third stage, we recursively walk the new\n- * structure, passing each name/value pair to a filter\n- * function for possible transformation.\n- */\n- if (typeof filter === 'function') {\n- function walk(k, v) {\n- if (v && typeof v === 'object') {\n- for (var i in v) {\n- if (v.hasOwnProperty(i)) {\n- v[i] = walk(i, v[i]);\n- }\n- }\n- }\n- return filter(k, v);\n- }\n- object = walk('', object);\n- }\n- }\n- } catch (e) {\n- // Fall through if the regexp test fails.\n- }\n-\n- if (this.keepData) {\n- this.data = object;\n+ initialize: function(projCode, options) {\n+ OpenLayers.Util.extend(this, options);\n+ this.projCode = projCode;\n+ if (typeof Proj4js == \"object\") {\n+ this.proj = new Proj4js.Proj(projCode);\n }\n-\n- return object;\n },\n \n /**\n- * APIMethod: write\n- * Serialize an object into a JSON string.\n- *\n- * Parameters:\n- * value - {String} The object, array, string, number, boolean or date\n- * to be serialized.\n- * pretty - {Boolean} Structure the output with newlines and indentation.\n- * Default is false.\n+ * APIMethod: getCode\n+ * Get the string SRS code.\n *\n * Returns:\n- * {String} The JSON string representation of the input value.\n+ * {String} The SRS code.\n */\n- write: function(value, pretty) {\n- this.pretty = !!pretty;\n- var json = null;\n- var type = typeof value;\n- if (this.serialize[type]) {\n- try {\n- json = (!this.pretty && this.nativeJSON) ?\n- JSON.stringify(value) :\n- this.serialize[type].apply(this, [value]);\n- } catch (err) {\n- OpenLayers.Console.error(\"Trouble serializing: \" + err);\n- }\n- }\n- return json;\n+ getCode: function() {\n+ return this.proj ? this.proj.srsCode : this.projCode;\n },\n \n /**\n- * Method: writeIndent\n- * Output an indentation string depending on the indentation level.\n+ * APIMethod: getUnits\n+ * Get the units string for the projection -- returns null if \n+ * proj4js is not available.\n *\n * Returns:\n- * {String} An appropriate indentation string.\n+ * {String} The units abbreviation.\n */\n- writeIndent: function() {\n- var pieces = [];\n- if (this.pretty) {\n- for (var i = 0; i < this.level; ++i) {\n- pieces.push(this.indent);\n- }\n- }\n- return pieces.join('');\n+ getUnits: function() {\n+ return this.proj ? this.proj.units : null;\n },\n \n /**\n- * Method: writeNewline\n- * Output a string representing a newline if in pretty printing mode.\n+ * Method: toString\n+ * Convert projection to string (getCode wrapper).\n *\n * Returns:\n- * {String} A string representing a new line.\n+ * {String} The projection code.\n */\n- writeNewline: function() {\n- return (this.pretty) ? this.newline : '';\n+ toString: function() {\n+ return this.getCode();\n },\n \n /**\n- * Method: writeSpace\n- * Output a string representing a space if in pretty printing mode.\n+ * Method: equals\n+ * Test equality of two projection instances. Determines equality based\n+ * soley on the projection code.\n *\n * Returns:\n- * {String} A space.\n+ * {Boolean} The two projections are equivalent.\n */\n- writeSpace: function() {\n- return (this.pretty) ? this.space : '';\n+ equals: function(projection) {\n+ var p = projection,\n+ equals = false;\n+ if (p) {\n+ if (!(p instanceof OpenLayers.Projection)) {\n+ p = new OpenLayers.Projection(p);\n+ }\n+ if ((typeof Proj4js == \"object\") && this.proj.defData && p.proj.defData) {\n+ equals = this.proj.defData.replace(this.titleRegEx, \"\") ==\n+ p.proj.defData.replace(this.titleRegEx, \"\");\n+ } else if (p.getCode) {\n+ var source = this.getCode(),\n+ target = p.getCode();\n+ equals = source == target ||\n+ !!OpenLayers.Projection.transforms[source] &&\n+ OpenLayers.Projection.transforms[source][target] ===\n+ OpenLayers.Projection.nullTransform;\n+ }\n+ }\n+ return equals;\n },\n \n- /**\n- * Property: serialize\n- * Object with properties corresponding to the serializable data types.\n- * Property values are functions that do the actual serializing.\n+ /* Method: destroy\n+ * Destroy projection object.\n */\n- serialize: {\n- /**\n- * Method: serialize.object\n- * Transform an object into a JSON string.\n- *\n- * Parameters:\n- * object - {Object} The object to be serialized.\n- * \n- * Returns:\n- * {String} A JSON string representing the object.\n- */\n- 'object': function(object) {\n- // three special objects that we want to treat differently\n- if (object == null) {\n- return \"null\";\n- }\n- if (object.constructor == Date) {\n- return this.serialize.date.apply(this, [object]);\n- }\n- if (object.constructor == Array) {\n- return this.serialize.array.apply(this, [object]);\n- }\n- var pieces = ['{'];\n- this.level += 1;\n- var key, keyJSON, valueJSON;\n+ destroy: function() {\n+ delete this.proj;\n+ delete this.projCode;\n+ },\n \n- var addComma = false;\n- for (key in object) {\n- if (object.hasOwnProperty(key)) {\n- // recursive calls need to allow for sub-classing\n- keyJSON = OpenLayers.Format.JSON.prototype.write.apply(this,\n- [key, this.pretty]);\n- valueJSON = OpenLayers.Format.JSON.prototype.write.apply(this,\n- [object[key], this.pretty]);\n- if (keyJSON != null && valueJSON != null) {\n- if (addComma) {\n- pieces.push(',');\n- }\n- pieces.push(this.writeNewline(), this.writeIndent(),\n- keyJSON, ':', this.writeSpace(), valueJSON);\n- addComma = true;\n- }\n- }\n- }\n+ CLASS_NAME: \"OpenLayers.Projection\"\n+});\n \n- this.level -= 1;\n- pieces.push(this.writeNewline(), this.writeIndent(), '}');\n- return pieces.join('');\n- },\n+/**\n+ * Property: transforms\n+ * {Object} Transforms is an object, with from properties, each of which may\n+ * have a to property. This allows you to define projections without \n+ * requiring support for proj4js to be included.\n+ *\n+ * This object has keys which correspond to a 'source' projection object. The\n+ * keys should be strings, corresponding to the projection.getCode() value.\n+ * Each source projection object should have a set of destination projection\n+ * keys included in the object. \n+ * \n+ * Each value in the destination object should be a transformation function,\n+ * where the function is expected to be passed an object with a .x and a .y\n+ * property. The function should return the object, with the .x and .y\n+ * transformed according to the transformation function.\n+ *\n+ * Note - Properties on this object should not be set directly. To add a\n+ * transform method to this object, use the method. For an\n+ * example of usage, see the OpenLayers.Layer.SphericalMercator file.\n+ */\n+OpenLayers.Projection.transforms = {};\n \n- /**\n- * Method: serialize.array\n- * Transform an array into a JSON string.\n- *\n- * Parameters:\n- * array - {Array} The array to be serialized\n- * \n- * Returns:\n- * {String} A JSON string representing the array.\n- */\n- 'array': function(array) {\n- var json;\n- var pieces = ['['];\n- this.level += 1;\n+/**\n+ * APIProperty: defaults\n+ * {Object} Defaults for the SRS codes known to OpenLayers (currently\n+ * EPSG:4326, CRS:84, urn:ogc:def:crs:EPSG:6.6:4326, EPSG:900913, EPSG:3857,\n+ * EPSG:102113 and EPSG:102100). Keys are the SRS code, values are units,\n+ * maxExtent (the validity extent for the SRS) and yx (true if this SRS is\n+ * known to have a reverse axis order).\n+ */\n+OpenLayers.Projection.defaults = {\n+ \"EPSG:4326\": {\n+ units: \"degrees\",\n+ maxExtent: [-180, -90, 180, 90],\n+ yx: true\n+ },\n+ \"CRS:84\": {\n+ units: \"degrees\",\n+ maxExtent: [-180, -90, 180, 90]\n+ },\n+ \"EPSG:900913\": {\n+ units: \"m\",\n+ maxExtent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34]\n+ }\n+};\n \n- for (var i = 0, len = array.length; i < len; ++i) {\n- // recursive calls need to allow for sub-classing\n- json = OpenLayers.Format.JSON.prototype.write.apply(this,\n- [array[i], this.pretty]);\n- if (json != null) {\n- if (i > 0) {\n- pieces.push(',');\n- }\n- pieces.push(this.writeNewline(), this.writeIndent(), json);\n- }\n+/**\n+ * APIMethod: addTransform\n+ * Set a custom transform method between two projections. Use this method in\n+ * cases where the proj4js lib is not available or where custom projections\n+ * need to be handled.\n+ *\n+ * Parameters:\n+ * from - {String} The code for the source projection\n+ * to - {String} the code for the destination projection\n+ * method - {Function} A function that takes a point as an argument and\n+ * transforms that point from the source to the destination projection\n+ * in place. The original point should be modified.\n+ */\n+OpenLayers.Projection.addTransform = function(from, to, method) {\n+ if (method === OpenLayers.Projection.nullTransform) {\n+ var defaults = OpenLayers.Projection.defaults[from];\n+ if (defaults && !OpenLayers.Projection.defaults[to]) {\n+ OpenLayers.Projection.defaults[to] = defaults;\n+ }\n+ }\n+ if (!OpenLayers.Projection.transforms[from]) {\n+ OpenLayers.Projection.transforms[from] = {};\n+ }\n+ OpenLayers.Projection.transforms[from][to] = method;\n+};\n+\n+/**\n+ * APIMethod: transform\n+ * Transform a point coordinate from one projection to another. Note that\n+ * the input point is transformed in place.\n+ * \n+ * Parameters:\n+ * point - { | Object} An object with x and y\n+ * properties representing coordinates in those dimensions.\n+ * source - {OpenLayers.Projection} Source map coordinate system\n+ * dest - {OpenLayers.Projection} Destination map coordinate system\n+ *\n+ * Returns:\n+ * point - {object} A transformed coordinate. The original point is modified.\n+ */\n+OpenLayers.Projection.transform = function(point, source, dest) {\n+ if (source && dest) {\n+ if (!(source instanceof OpenLayers.Projection)) {\n+ source = new OpenLayers.Projection(source);\n+ }\n+ if (!(dest instanceof OpenLayers.Projection)) {\n+ dest = new OpenLayers.Projection(dest);\n+ }\n+ if (source.proj && dest.proj) {\n+ point = Proj4js.transform(source.proj, dest.proj, point);\n+ } else {\n+ var sourceCode = source.getCode();\n+ var destCode = dest.getCode();\n+ var transforms = OpenLayers.Projection.transforms;\n+ if (transforms[sourceCode] && transforms[sourceCode][destCode]) {\n+ transforms[sourceCode][destCode](point);\n }\n+ }\n+ }\n+ return point;\n+};\n \n- this.level -= 1;\n- pieces.push(this.writeNewline(), this.writeIndent(), ']');\n- return pieces.join('');\n- },\n+/**\n+ * APIFunction: nullTransform\n+ * A null transformation - useful for defining projection aliases when\n+ * proj4js is not available:\n+ *\n+ * (code)\n+ * OpenLayers.Projection.addTransform(\"EPSG:3857\", \"EPSG:900913\",\n+ * OpenLayers.Projection.nullTransform);\n+ * OpenLayers.Projection.addTransform(\"EPSG:900913\", \"EPSG:3857\",\n+ * OpenLayers.Projection.nullTransform);\n+ * (end)\n+ */\n+OpenLayers.Projection.nullTransform = function(point) {\n+ return point;\n+};\n \n- /**\n- * Method: serialize.string\n- * Transform a string into a JSON string.\n- *\n- * Parameters:\n- * string - {String} The string to be serialized\n- * \n- * Returns:\n- * {String} A JSON string representing the string.\n- */\n- 'string': function(string) {\n- // If the string contains no control characters, no quote characters, and no\n- // backslash characters, then we can simply slap some quotes around it.\n- // Otherwise we must also replace the offending characters with safe\n- // sequences. \n- var m = {\n- '\\b': '\\\\b',\n- '\\t': '\\\\t',\n- '\\n': '\\\\n',\n- '\\f': '\\\\f',\n- '\\r': '\\\\r',\n- '\"': '\\\\\"',\n- '\\\\': '\\\\\\\\'\n- };\n- if (/[\"\\\\\\x00-\\x1f]/.test(string)) {\n- return '\"' + string.replace(/([\\x00-\\x1f\\\\\"])/g, function(a, b) {\n- var c = m[b];\n- if (c) {\n- return c;\n- }\n- c = b.charCodeAt();\n- return '\\\\u00' +\n- Math.floor(c / 16).toString(16) +\n- (c % 16).toString(16);\n- }) + '\"';\n- }\n- return '\"' + string + '\"';\n- },\n+/**\n+ * Note: Transforms for web mercator <-> geographic\n+ * OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113 and EPSG:102100.\n+ * OpenLayers originally started referring to EPSG:900913 as web mercator.\n+ * The EPSG has declared EPSG:3857 to be web mercator.\n+ * ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as\n+ * equivalent. See http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2009/11/20/ArcGIS-Online-moving-to-Google-_2F00_-Bing-tiling-scheme_3A00_-What-does-this-mean-for-you_3F00_.aspx#12084.\n+ * For geographic, OpenLayers recognizes EPSG:4326, CRS:84 and\n+ * urn:ogc:def:crs:EPSG:6.6:4326. OpenLayers also knows about the reverse axis\n+ * order for EPSG:4326. \n+ */\n+(function() {\n \n- /**\n- * Method: serialize.number\n- * Transform a number into a JSON string.\n- *\n- * Parameters:\n- * number - {Number} The number to be serialized.\n- *\n- * Returns:\n- * {String} A JSON string representing the number.\n- */\n- 'number': function(number) {\n- return isFinite(number) ? String(number) : \"null\";\n- },\n+ var pole = 20037508.34;\n \n- /**\n- * Method: serialize.boolean\n- * Transform a boolean into a JSON string.\n- *\n- * Parameters:\n- * bool - {Boolean} The boolean to be serialized.\n- * \n- * Returns:\n- * {String} A JSON string representing the boolean.\n- */\n- 'boolean': function(bool) {\n- return String(bool);\n- },\n+ function inverseMercator(xy) {\n+ xy.x = 180 * xy.x / pole;\n+ xy.y = 180 / Math.PI * (2 * Math.atan(Math.exp((xy.y / pole) * Math.PI)) - Math.PI / 2);\n+ return xy;\n+ }\n \n- /**\n- * Method: serialize.object\n- * Transform a date into a JSON string.\n- *\n- * Parameters:\n- * date - {Date} The date to be serialized.\n- * \n- * Returns:\n- * {String} A JSON string representing the date.\n- */\n- 'date': function(date) {\n- function format(number) {\n- // Format integers to have at least two digits.\n- return (number < 10) ? '0' + number : number;\n+ function forwardMercator(xy) {\n+ xy.x = xy.x * pole / 180;\n+ var y = Math.log(Math.tan((90 + xy.y) * Math.PI / 360)) / Math.PI * pole;\n+ xy.y = Math.max(-20037508.34, Math.min(y, 20037508.34));\n+ return xy;\n+ }\n+\n+ function map(base, codes) {\n+ var add = OpenLayers.Projection.addTransform;\n+ var same = OpenLayers.Projection.nullTransform;\n+ var i, len, code, other, j;\n+ for (i = 0, len = codes.length; i < len; ++i) {\n+ code = codes[i];\n+ add(base, code, forwardMercator);\n+ add(code, base, inverseMercator);\n+ for (j = i + 1; j < len; ++j) {\n+ other = codes[j];\n+ add(code, other, same);\n+ add(other, code, same);\n }\n- return '\"' + date.getFullYear() + '-' +\n- format(date.getMonth() + 1) + '-' +\n- format(date.getDate()) + 'T' +\n- format(date.getHours()) + ':' +\n- format(date.getMinutes()) + ':' +\n- format(date.getSeconds()) + '\"';\n }\n- },\n+ }\n \n- CLASS_NAME: \"OpenLayers.Format.JSON\"\n+ // list of equivalent codes for web mercator\n+ var mercator = [\"EPSG:900913\", \"EPSG:3857\", \"EPSG:102113\", \"EPSG:102100\"],\n+ geographic = [\"CRS:84\", \"urn:ogc:def:crs:EPSG:6.6:4326\", \"EPSG:4326\"],\n+ i;\n+ for (i = mercator.length - 1; i >= 0; --i) {\n+ map(mercator[i], geographic);\n+ }\n+ for (i = geographic.length - 1; i >= 0; --i) {\n+ map(geographic[i], mercator);\n+ }\n \n-});\n+})();\n /* ======================================================================\n- OpenLayers/Format/GeoJSON.js\n+ OpenLayers/Map.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/Format/JSON.js\n- * @requires OpenLayers/Feature/Vector.js\n- * @requires OpenLayers/Geometry/Point.js\n- * @requires OpenLayers/Geometry/MultiPoint.js\n- * @requires OpenLayers/Geometry/LineString.js\n- * @requires OpenLayers/Geometry/MultiLineString.js\n- * @requires OpenLayers/Geometry/Polygon.js\n- * @requires OpenLayers/Geometry/MultiPolygon.js\n- * @requires OpenLayers/Console.js\n+ * @requires OpenLayers/BaseTypes/Class.js\n+ * @requires OpenLayers/Util.js\n+ * @requires OpenLayers/Util/vendorPrefix.js\n+ * @requires OpenLayers/Events.js\n+ * @requires OpenLayers/Tween.js\n+ * @requires OpenLayers/Projection.js\n */\n \n /**\n- * Class: OpenLayers.Format.GeoJSON\n- * Read and write GeoJSON. Create a new parser with the\n- * constructor.\n- *\n- * Inherits from:\n- * - \n+ * Class: OpenLayers.Map\n+ * Instances of OpenLayers.Map are interactive maps embedded in a web page.\n+ * Create a new map with the constructor.\n+ * \n+ * On their own maps do not provide much functionality. To extend a map\n+ * it's necessary to add controls () and \n+ * layers () to the map. \n */\n-OpenLayers.Format.GeoJSON = OpenLayers.Class(OpenLayers.Format.JSON, {\n+OpenLayers.Map = OpenLayers.Class({\n \n /**\n- * APIProperty: ignoreExtraDims\n- * {Boolean} Ignore dimensions higher than 2 when reading geometry\n- * coordinates.\n+ * Constant: Z_INDEX_BASE\n+ * {Object} Base z-indexes for different classes of thing \n */\n- ignoreExtraDims: false,\n+ Z_INDEX_BASE: {\n+ BaseLayer: 100,\n+ Overlay: 325,\n+ Feature: 725,\n+ Popup: 750,\n+ Control: 1000\n+ },\n \n /**\n- * Constructor: OpenLayers.Format.GeoJSON\n- * Create a new parser for GeoJSON.\n+ * APIProperty: events\n+ * {}\n *\n- * Parameters:\n- * options - {Object} An optional object whose properties will be set on\n- * this instance.\n- */\n-\n- /**\n- * APIMethod: read\n- * Deserialize a GeoJSON string.\n+ * Register a listener for a particular event with the following syntax:\n+ * (code)\n+ * map.events.register(type, obj, listener);\n+ * (end)\n *\n- * Parameters:\n- * json - {String} A GeoJSON string\n- * type - {String} Optional string that determines the structure of\n- * the output. Supported values are \"Geometry\", \"Feature\", and\n- * \"FeatureCollection\". If absent or null, a default of\n- * \"FeatureCollection\" is assumed.\n- * filter - {Function} A function which will be called for every key and\n- * value at every level of the final result. Each value will be\n- * replaced by the result of the filter function. This can be used to\n- * reform generic objects into instances of classes, or to transform\n- * date strings into Date objects.\n+ * Listeners will be called with a reference to an event object. The\n+ * properties of this event depends on exactly what happened.\n *\n- * Returns: \n- * {Object} The return depends on the value of the type argument. If type\n- * is \"FeatureCollection\" (the default), the return will be an array\n- * of . If type is \"Geometry\", the input json\n- * must represent a single geometry, and the return will be an\n- * . If type is \"Feature\", the input json must\n- * represent a single feature, and the return will be an\n- * .\n+ * All event objects have at least the following properties:\n+ * object - {Object} A reference to map.events.object.\n+ * element - {DOMElement} A reference to map.events.element.\n+ *\n+ * Browser events have the following additional properties:\n+ * xy - {} The pixel location of the event (relative\n+ * to the the map viewport).\n+ *\n+ * Supported map event types:\n+ * preaddlayer - triggered before a layer has been added. The event\n+ * object will include a *layer* property that references the layer \n+ * to be added. When a listener returns \"false\" the adding will be \n+ * aborted.\n+ * addlayer - triggered after a layer has been added. The event object\n+ * will include a *layer* property that references the added layer.\n+ * preremovelayer - triggered before a layer has been removed. The event\n+ * object will include a *layer* property that references the layer \n+ * to be removed. When a listener returns \"false\" the removal will be \n+ * aborted.\n+ * removelayer - triggered after a layer has been removed. The event\n+ * object will include a *layer* property that references the removed\n+ * layer.\n+ * changelayer - triggered after a layer name change, order change,\n+ * opacity change, params change, visibility change (actual visibility,\n+ * not the layer's visibility property) or attribution change (due to\n+ * extent change). Listeners will receive an event object with *layer*\n+ * and *property* properties. The *layer* property will be a reference\n+ * to the changed layer. The *property* property will be a key to the\n+ * changed property (name, order, opacity, params, visibility or\n+ * attribution).\n+ * movestart - triggered after the start of a drag, pan, or zoom. The event\n+ * object may include a *zoomChanged* property that tells whether the\n+ * zoom has changed.\n+ * move - triggered after each drag, pan, or zoom\n+ * moveend - triggered after a drag, pan, or zoom completes\n+ * zoomend - triggered after a zoom completes\n+ * mouseover - triggered after mouseover the map\n+ * mouseout - triggered after mouseout the map\n+ * mousemove - triggered after mousemove the map\n+ * changebaselayer - triggered after the base layer changes\n+ * updatesize - triggered after the method was executed\n */\n- read: function(json, type, filter) {\n- type = (type) ? type : \"FeatureCollection\";\n- var results = null;\n- var obj = null;\n- if (typeof json == \"string\") {\n- obj = OpenLayers.Format.JSON.prototype.read.apply(this,\n- [json, filter]);\n- } else {\n- obj = json;\n- }\n- if (!obj) {\n- OpenLayers.Console.error(\"Bad JSON: \" + json);\n- } else if (typeof(obj.type) != \"string\") {\n- OpenLayers.Console.error(\"Bad GeoJSON - no type: \" + json);\n- } else if (this.isValidType(obj, type)) {\n- switch (type) {\n- case \"Geometry\":\n- try {\n- results = this.parseGeometry(obj);\n- } catch (err) {\n- OpenLayers.Console.error(err);\n- }\n- break;\n- case \"Feature\":\n- try {\n- results = this.parseFeature(obj);\n- results.type = \"Feature\";\n- } catch (err) {\n- OpenLayers.Console.error(err);\n- }\n- break;\n- case \"FeatureCollection\":\n- // for type FeatureCollection, we allow input to be any type\n- results = [];\n- switch (obj.type) {\n- case \"Feature\":\n- try {\n- results.push(this.parseFeature(obj));\n- } catch (err) {\n- results = null;\n- OpenLayers.Console.error(err);\n- }\n- break;\n- case \"FeatureCollection\":\n- for (var i = 0, len = obj.features.length; i < len; ++i) {\n- try {\n- results.push(this.parseFeature(obj.features[i]));\n- } catch (err) {\n- results = null;\n- OpenLayers.Console.error(err);\n- }\n- }\n- break;\n- default:\n- try {\n- var geom = this.parseGeometry(obj);\n- results.push(new OpenLayers.Feature.Vector(geom));\n- } catch (err) {\n- results = null;\n- OpenLayers.Console.error(err);\n- }\n- }\n- break;\n- }\n- }\n- return results;\n- },\n \n /**\n- * Method: isValidType\n- * Check if a GeoJSON object is a valid representative of the given type.\n- *\n- * Returns:\n- * {Boolean} The object is valid GeoJSON object of the given type.\n+ * Property: id\n+ * {String} Unique identifier for the map\n */\n- isValidType: function(obj, type) {\n- var valid = false;\n- switch (type) {\n- case \"Geometry\":\n- if (OpenLayers.Util.indexOf(\n- [\"Point\", \"MultiPoint\", \"LineString\", \"MultiLineString\",\n- \"Polygon\", \"MultiPolygon\", \"Box\", \"GeometryCollection\"\n- ],\n- obj.type) == -1) {\n- // unsupported geometry type\n- OpenLayers.Console.error(\"Unsupported geometry type: \" +\n- obj.type);\n- } else {\n- valid = true;\n- }\n- break;\n- case \"FeatureCollection\":\n- // allow for any type to be converted to a feature collection\n- valid = true;\n- break;\n- default:\n- // for Feature types must match\n- if (obj.type == type) {\n- valid = true;\n- } else {\n- OpenLayers.Console.error(\"Cannot convert types from \" +\n- obj.type + \" to \" + type);\n- }\n- }\n- return valid;\n- },\n+ id: null,\n \n /**\n- * Method: parseFeature\n- * Convert a feature object from GeoJSON into an\n- * .\n+ * Property: fractionalZoom\n+ * {Boolean} For a base layer that supports it, allow the map resolution\n+ * to be set to a value between one of the values in the resolutions\n+ * array. Default is false.\n *\n- * Parameters:\n- * obj - {Object} An object created from a GeoJSON object\n+ * When fractionalZoom is set to true, it is possible to zoom to\n+ * an arbitrary extent. This requires a base layer from a source\n+ * that supports requests for arbitrary extents (i.e. not cached\n+ * tiles on a regular lattice). This means that fractionalZoom\n+ * will not work with commercial layers (Google, Yahoo, VE), layers\n+ * using TileCache, or any other pre-cached data sources.\n *\n- * Returns:\n- * {} A feature.\n+ * If you are using fractionalZoom, then you should also use\n+ * instead of layer.resolutions[zoom] as the\n+ * former works for non-integer zoom levels.\n */\n- parseFeature: function(obj) {\n- var feature, geometry, attributes, bbox;\n- attributes = (obj.properties) ? obj.properties : {};\n- bbox = (obj.geometry && obj.geometry.bbox) || obj.bbox;\n- try {\n- geometry = this.parseGeometry(obj.geometry);\n- } catch (err) {\n- // deal with bad geometries\n- throw err;\n- }\n- feature = new OpenLayers.Feature.Vector(geometry, attributes);\n- if (bbox) {\n- feature.bounds = OpenLayers.Bounds.fromArray(bbox);\n- }\n- if (obj.id) {\n- feature.fid = obj.id;\n- }\n- return feature;\n- },\n+ fractionalZoom: false,\n \n /**\n- * Method: parseGeometry\n- * Convert a geometry object from GeoJSON into an .\n- *\n- * Parameters:\n- * obj - {Object} An object created from a GeoJSON object\n- *\n- * Returns: \n- * {} A geometry.\n+ * APIProperty: events\n+ * {} An events object that handles all \n+ * events on the map\n */\n- parseGeometry: function(obj) {\n- if (obj == null) {\n- return null;\n- }\n- var geometry, collection = false;\n- if (obj.type == \"GeometryCollection\") {\n- if (!(OpenLayers.Util.isArray(obj.geometries))) {\n- throw \"GeometryCollection must have geometries array: \" + obj;\n- }\n- var numGeom = obj.geometries.length;\n- var components = new Array(numGeom);\n- for (var i = 0; i < numGeom; ++i) {\n- components[i] = this.parseGeometry.apply(\n- this, [obj.geometries[i]]\n- );\n- }\n- geometry = new OpenLayers.Geometry.Collection(components);\n- collection = true;\n- } else {\n- if (!(OpenLayers.Util.isArray(obj.coordinates))) {\n- throw \"Geometry must have coordinates array: \" + obj;\n- }\n- if (!this.parseCoords[obj.type.toLowerCase()]) {\n- throw \"Unsupported geometry type: \" + obj.type;\n- }\n- try {\n- geometry = this.parseCoords[obj.type.toLowerCase()].apply(\n- this, [obj.coordinates]\n- );\n- } catch (err) {\n- // deal with bad coordinates\n- throw err;\n- }\n- }\n- // We don't reproject collections because the children are reprojected\n- // for us when they are created.\n- if (this.internalProjection && this.externalProjection && !collection) {\n- geometry.transform(this.externalProjection,\n- this.internalProjection);\n- }\n- return geometry;\n- },\n+ events: null,\n \n /**\n- * Property: parseCoords\n- * Object with properties corresponding to the GeoJSON geometry types.\n- * Property values are functions that do the actual parsing.\n+ * APIProperty: allOverlays\n+ * {Boolean} Allow the map to function with \"overlays\" only. Defaults to\n+ * false. If true, the lowest layer in the draw order will act as\n+ * the base layer. In addition, if set to true, all layers will\n+ * have isBaseLayer set to false when they are added to the map.\n+ *\n+ * Note:\n+ * If you set map.allOverlays to true, then you *cannot* use\n+ * map.setBaseLayer or layer.setIsBaseLayer. With allOverlays true,\n+ * the lowest layer in the draw layer is the base layer. So, to change\n+ * the base layer, use or to set the layer\n+ * index to 0.\n */\n- parseCoords: {\n- /**\n- * Method: parseCoords.point\n- * Convert a coordinate array from GeoJSON into an\n- * .\n- *\n- * Parameters:\n- * array - {Object} The coordinates array from the GeoJSON fragment.\n- *\n- * Returns:\n- * {} A geometry.\n- */\n- \"point\": function(array) {\n- if (this.ignoreExtraDims == false &&\n- array.length != 2) {\n- throw \"Only 2D points are supported: \" + array;\n- }\n- return new OpenLayers.Geometry.Point(array[0], array[1]);\n- },\n+ allOverlays: false,\n \n- /**\n- * Method: parseCoords.multipoint\n- * Convert a coordinate array from GeoJSON into an\n- * .\n- *\n- * Parameters:\n- * array - {Object} The coordinates array from the GeoJSON fragment.\n- *\n- * Returns:\n- * {} A geometry.\n- */\n- \"multipoint\": function(array) {\n- var points = [];\n- var p = null;\n- for (var i = 0, len = array.length; i < len; ++i) {\n- try {\n- p = this.parseCoords[\"point\"].apply(this, [array[i]]);\n- } catch (err) {\n- throw err;\n- }\n- points.push(p);\n- }\n- return new OpenLayers.Geometry.MultiPoint(points);\n- },\n+ /**\n+ * APIProperty: div\n+ * {DOMElement|String} The element that contains the map (or an id for\n+ * that element). If the constructor is called\n+ * with two arguments, this should be provided as the first argument.\n+ * Alternatively, the map constructor can be called with the options\n+ * object as the only argument. In this case (one argument), a\n+ * div property may or may not be provided. If the div property\n+ * is not provided, the map can be rendered to a container later\n+ * using the method.\n+ * \n+ * Note:\n+ * If you are calling after map construction, do not use\n+ * auto. Instead, divide your by your\n+ * maximum expected dimension.\n+ */\n+ div: null,\n \n- /**\n- * Method: parseCoords.linestring\n- * Convert a coordinate array from GeoJSON into an\n- * .\n- *\n- * Parameters:\n- * array - {Object} The coordinates array from the GeoJSON fragment.\n- *\n- * Returns:\n- * {} A geometry.\n- */\n- \"linestring\": function(array) {\n- var points = [];\n- var p = null;\n- for (var i = 0, len = array.length; i < len; ++i) {\n- try {\n- p = this.parseCoords[\"point\"].apply(this, [array[i]]);\n- } catch (err) {\n- throw err;\n- }\n- points.push(p);\n- }\n- return new OpenLayers.Geometry.LineString(points);\n- },\n+ /**\n+ * Property: dragging\n+ * {Boolean} The map is currently being dragged.\n+ */\n+ dragging: false,\n \n- /**\n- * Method: parseCoords.multilinestring\n- * Convert a coordinate array from GeoJSON into an\n- * .\n- *\n- * Parameters:\n- * array - {Object} The coordinates array from the GeoJSON fragment.\n- *\n- * Returns:\n- * {} A geometry.\n- */\n- \"multilinestring\": function(array) {\n- var lines = [];\n- var l = null;\n- for (var i = 0, len = array.length; i < len; ++i) {\n- try {\n- l = this.parseCoords[\"linestring\"].apply(this, [array[i]]);\n- } catch (err) {\n- throw err;\n- }\n- lines.push(l);\n- }\n- return new OpenLayers.Geometry.MultiLineString(lines);\n- },\n+ /**\n+ * Property: size\n+ * {} Size of the main div (this.div)\n+ */\n+ size: null,\n \n- /**\n- * Method: parseCoords.polygon\n- * Convert a coordinate array from GeoJSON into an\n- * .\n- *\n- * Returns:\n- * {} A geometry.\n- */\n- \"polygon\": function(array) {\n- var rings = [];\n- var r, l;\n- for (var i = 0, len = array.length; i < len; ++i) {\n- try {\n- l = this.parseCoords[\"linestring\"].apply(this, [array[i]]);\n- } catch (err) {\n- throw err;\n- }\n- r = new OpenLayers.Geometry.LinearRing(l.components);\n- rings.push(r);\n- }\n- return new OpenLayers.Geometry.Polygon(rings);\n- },\n+ /**\n+ * Property: viewPortDiv\n+ * {HTMLDivElement} The element that represents the map viewport\n+ */\n+ viewPortDiv: null,\n \n- /**\n- * Method: parseCoords.multipolygon\n- * Convert a coordinate array from GeoJSON into an\n- * .\n- *\n- * Parameters:\n- * array - {Object} The coordinates array from the GeoJSON fragment.\n- *\n- * Returns:\n- * {} A geometry.\n- */\n- \"multipolygon\": function(array) {\n- var polys = [];\n- var p = null;\n- for (var i = 0, len = array.length; i < len; ++i) {\n- try {\n- p = this.parseCoords[\"polygon\"].apply(this, [array[i]]);\n- } catch (err) {\n- throw err;\n- }\n- polys.push(p);\n- }\n- return new OpenLayers.Geometry.MultiPolygon(polys);\n- },\n+ /**\n+ * Property: layerContainerOrigin\n+ * {} The lonlat at which the later container was\n+ * re-initialized (on-zoom)\n+ */\n+ layerContainerOrigin: null,\n \n- /**\n- * Method: parseCoords.box\n- * Convert a coordinate array from GeoJSON into an\n- * .\n- *\n- * Parameters:\n- * array - {Object} The coordinates array from the GeoJSON fragment.\n- *\n- * Returns:\n- * {} A geometry.\n- */\n- \"box\": function(array) {\n- if (array.length != 2) {\n- throw \"GeoJSON box coordinates must have 2 elements\";\n- }\n- return new OpenLayers.Geometry.Polygon([\n- new OpenLayers.Geometry.LinearRing([\n- new OpenLayers.Geometry.Point(array[0][0], array[0][1]),\n- new OpenLayers.Geometry.Point(array[1][0], array[0][1]),\n- new OpenLayers.Geometry.Point(array[1][0], array[1][1]),\n- new OpenLayers.Geometry.Point(array[0][0], array[1][1]),\n- new OpenLayers.Geometry.Point(array[0][0], array[0][1])\n- ])\n- ]);\n- }\n+ /**\n+ * Property: layerContainerDiv\n+ * {HTMLDivElement} The element that contains the layers.\n+ */\n+ layerContainerDiv: null,\n \n- },\n+ /**\n+ * APIProperty: layers\n+ * {Array()} Ordered list of layers in the map\n+ */\n+ layers: null,\n \n /**\n- * APIMethod: write\n- * Serialize a feature, geometry, array of features into a GeoJSON string.\n- *\n- * Parameters:\n- * obj - {Object} An , ,\n- * or an array of features.\n- * pretty - {Boolean} Structure the output with newlines and indentation.\n- * Default is false.\n+ * APIProperty: controls\n+ * {Array()} List of controls associated with the map.\n *\n- * Returns:\n- * {String} The GeoJSON string representation of the input geometry,\n- * features, or array of features.\n+ * If not provided in the map options at construction, the map will\n+ * by default be given the following controls if present in the build:\n+ * - or \n+ * - or \n+ * - \n+ * - \n */\n- write: function(obj, pretty) {\n- var geojson = {\n- \"type\": null\n- };\n- if (OpenLayers.Util.isArray(obj)) {\n- geojson.type = \"FeatureCollection\";\n- var numFeatures = obj.length;\n- geojson.features = new Array(numFeatures);\n- for (var i = 0; i < numFeatures; ++i) {\n- var element = obj[i];\n- if (!element instanceof OpenLayers.Feature.Vector) {\n- var msg = \"FeatureCollection only supports collections \" +\n- \"of features: \" + element;\n- throw msg;\n- }\n- geojson.features[i] = this.extract.feature.apply(\n- this, [element]\n- );\n- }\n- } else if (obj.CLASS_NAME.indexOf(\"OpenLayers.Geometry\") == 0) {\n- geojson = this.extract.geometry.apply(this, [obj]);\n- } else if (obj instanceof OpenLayers.Feature.Vector) {\n- geojson = this.extract.feature.apply(this, [obj]);\n- if (obj.layer && obj.layer.projection) {\n- geojson.crs = this.createCRSObject(obj);\n- }\n- }\n- return OpenLayers.Format.JSON.prototype.write.apply(this,\n- [geojson, pretty]);\n- },\n+ controls: null,\n \n /**\n- * Method: createCRSObject\n- * Create the CRS object for an object.\n- *\n- * Parameters:\n- * object - {} \n- *\n- * Returns:\n- * {Object} An object which can be assigned to the crs property\n- * of a GeoJSON object.\n+ * Property: popups\n+ * {Array()} List of popups associated with the map\n */\n- createCRSObject: function(object) {\n- var proj = object.layer.projection.toString();\n- var crs = {};\n- if (proj.match(/epsg:/i)) {\n- var code = parseInt(proj.substring(proj.indexOf(\":\") + 1));\n- if (code == 4326) {\n- crs = {\n- \"type\": \"name\",\n- \"properties\": {\n- \"name\": \"urn:ogc:def:crs:OGC:1.3:CRS84\"\n- }\n- };\n- } else {\n- crs = {\n- \"type\": \"name\",\n- \"properties\": {\n- \"name\": \"EPSG:\" + code\n- }\n- };\n- }\n- }\n- return crs;\n- },\n+ popups: null,\n \n /**\n- * Property: extract\n- * Object with properties corresponding to the GeoJSON types.\n- * Property values are functions that do the actual value extraction.\n+ * APIProperty: baseLayer\n+ * {} The currently selected base layer. This determines\n+ * min/max zoom level, projection, etc.\n */\n- extract: {\n- /**\n- * Method: extract.feature\n- * Return a partial GeoJSON object representing a single feature.\n- *\n- * Parameters:\n- * feature - {}\n- *\n- * Returns:\n- * {Object} An object representing the point.\n- */\n- 'feature': function(feature) {\n- var geom = this.extract.geometry.apply(this, [feature.geometry]);\n- var json = {\n- \"type\": \"Feature\",\n- \"properties\": feature.attributes,\n- \"geometry\": geom\n- };\n- if (feature.fid != null) {\n- json.id = feature.fid;\n- }\n- return json;\n- },\n+ baseLayer: null,\n \n- /**\n- * Method: extract.geometry\n- * Return a GeoJSON object representing a single geometry.\n- *\n- * Parameters:\n- * geometry - {}\n- *\n- * Returns:\n- * {Object} An object representing the geometry.\n- */\n- 'geometry': function(geometry) {\n- if (geometry == null) {\n- return null;\n- }\n- if (this.internalProjection && this.externalProjection) {\n- geometry = geometry.clone();\n- geometry.transform(this.internalProjection,\n- this.externalProjection);\n- }\n- var geometryType = geometry.CLASS_NAME.split('.')[2];\n- var data = this.extract[geometryType.toLowerCase()].apply(this, [geometry]);\n- var json;\n- if (geometryType == \"Collection\") {\n- json = {\n- \"type\": \"GeometryCollection\",\n- \"geometries\": data\n- };\n- } else {\n- json = {\n- \"type\": geometryType,\n- \"coordinates\": data\n- };\n- }\n+ /**\n+ * Property: center\n+ * {} The current center of the map\n+ */\n+ center: null,\n \n- return json;\n- },\n+ /**\n+ * Property: resolution\n+ * {Float} The resolution of the map.\n+ */\n+ resolution: null,\n \n- /**\n- * Method: extract.point\n- * Return an array of coordinates from a point.\n- *\n- * Parameters:\n- * point - {}\n- *\n- * Returns: \n- * {Array} An array of coordinates representing the point.\n- */\n- 'point': function(point) {\n- return [point.x, point.y];\n- },\n+ /**\n+ * Property: zoom\n+ * {Integer} The current zoom level of the map\n+ */\n+ zoom: 0,\n \n- /**\n- * Method: extract.multipoint\n- * Return an array of point coordinates from a multipoint.\n- *\n- * Parameters:\n- * multipoint - {}\n- *\n- * Returns:\n- * {Array} An array of point coordinate arrays representing\n- * the multipoint.\n- */\n- 'multipoint': function(multipoint) {\n- var array = [];\n- for (var i = 0, len = multipoint.components.length; i < len; ++i) {\n- array.push(this.extract.point.apply(this, [multipoint.components[i]]));\n- }\n- return array;\n- },\n+ /**\n+ * Property: panRatio\n+ * {Float} The ratio of the current extent within\n+ * which panning will tween.\n+ */\n+ panRatio: 1.5,\n \n- /**\n- * Method: extract.linestring\n- * Return an array of coordinate arrays from a linestring.\n- *\n- * Parameters:\n- * linestring - {}\n- *\n- * Returns:\n- * {Array} An array of coordinate arrays representing\n- * the linestring.\n- */\n- 'linestring': function(linestring) {\n- var array = [];\n- for (var i = 0, len = linestring.components.length; i < len; ++i) {\n- array.push(this.extract.point.apply(this, [linestring.components[i]]));\n- }\n- return array;\n- },\n+ /**\n+ * APIProperty: options\n+ * {Object} The options object passed to the class constructor. Read-only.\n+ */\n+ options: null,\n \n- /**\n- * Method: extract.multilinestring\n- * Return an array of linestring arrays from a linestring.\n- * \n- * Parameters:\n- * multilinestring - {}\n- * \n- * Returns:\n- * {Array} An array of linestring arrays representing\n- * the multilinestring.\n- */\n- 'multilinestring': function(multilinestring) {\n- var array = [];\n- for (var i = 0, len = multilinestring.components.length; i < len; ++i) {\n- array.push(this.extract.linestring.apply(this, [multilinestring.components[i]]));\n- }\n- return array;\n- },\n+ // Options\n \n- /**\n- * Method: extract.polygon\n- * Return an array of linear ring arrays from a polygon.\n- *\n- * Parameters:\n- * polygon - {}\n- * \n- * Returns:\n- * {Array} An array of linear ring arrays representing the polygon.\n- */\n- 'polygon': function(polygon) {\n- var array = [];\n- for (var i = 0, len = polygon.components.length; i < len; ++i) {\n- array.push(this.extract.linestring.apply(this, [polygon.components[i]]));\n- }\n- return array;\n- },\n+ /**\n+ * APIProperty: tileSize\n+ * {} Set in the map options to override the default tile\n+ * size for this map.\n+ */\n+ tileSize: null,\n \n- /**\n- * Method: extract.multipolygon\n- * Return an array of polygon arrays from a multipolygon.\n- * \n- * Parameters:\n- * multipolygon - {}\n- * \n- * Returns:\n- * {Array} An array of polygon arrays representing\n- * the multipolygon\n- */\n- 'multipolygon': function(multipolygon) {\n- var array = [];\n- for (var i = 0, len = multipolygon.components.length; i < len; ++i) {\n- array.push(this.extract.polygon.apply(this, [multipolygon.components[i]]));\n- }\n- return array;\n- },\n+ /**\n+ * APIProperty: projection\n+ * {String} Set in the map options to specify the default projection \n+ * for layers added to this map. When using a projection other than EPSG:4326\n+ * (CRS:84, Geographic) or EPSG:3857 (EPSG:900913, Web Mercator),\n+ * also set maxExtent, maxResolution or resolutions. Default is \"EPSG:4326\".\n+ * Note that the projection of the map is usually determined\n+ * by that of the current baseLayer (see and ).\n+ */\n+ projection: \"EPSG:4326\",\n \n- /**\n- * Method: extract.collection\n- * Return an array of geometries from a geometry collection.\n- * \n- * Parameters:\n- * collection - {}\n- * \n- * Returns:\n- * {Array} An array of geometry objects representing the geometry\n- * collection.\n- */\n- 'collection': function(collection) {\n- var len = collection.components.length;\n- var array = new Array(len);\n- for (var i = 0; i < len; ++i) {\n- array[i] = this.extract.geometry.apply(\n- this, [collection.components[i]]\n- );\n- }\n- return array;\n- }\n+ /**\n+ * APIProperty: units\n+ * {String} The map units. Possible values are 'degrees' (or 'dd'), 'm', \n+ * 'ft', 'km', 'mi', 'inches'. Normally taken from the projection.\n+ * Only required if both map and layers do not define a projection,\n+ * or if they define a projection which does not define units\n+ */\n+ units: null,\n \n+ /**\n+ * APIProperty: resolutions\n+ * {Array(Float)} A list of map resolutions (map units per pixel) in \n+ * descending order. If this is not set in the layer constructor, it \n+ * will be set based on other resolution related properties \n+ * (maxExtent, maxResolution, maxScale, etc.).\n+ */\n+ resolutions: null,\n \n- },\n+ /**\n+ * APIProperty: maxResolution\n+ * {Float} Required if you are not displaying the whole world on a tile\n+ * with the size specified in .\n+ */\n+ maxResolution: null,\n \n- CLASS_NAME: \"OpenLayers.Format.GeoJSON\"\n+ /**\n+ * APIProperty: minResolution\n+ * {Float}\n+ */\n+ minResolution: null,\n \n-});\n-/* ======================================================================\n- OpenLayers/Format/XML.js\n- ====================================================================== */\n+ /**\n+ * APIProperty: maxScale\n+ * {Float}\n+ */\n+ maxScale: null,\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+ * APIProperty: minScale\n+ * {Float}\n+ */\n+ minScale: null,\n \n-/**\n- * @requires OpenLayers/Format.js\n- */\n+ /**\n+ * APIProperty: maxExtent\n+ * {|Array} If provided as an array, the array\n+ * should consist of four values (left, bottom, right, top).\n+ * The maximum extent for the map.\n+ * Default depends on projection; if this is one of those defined in OpenLayers.Projection.defaults\n+ * (EPSG:4326 or web mercator), maxExtent will be set to the value defined there;\n+ * else, defaults to null.\n+ * To restrict user panning and zooming of the map, use instead.\n+ * The value for will change calculations for tile URLs.\n+ */\n+ maxExtent: null,\n \n-/**\n- * Class: OpenLayers.Format.XML\n- * Read and write XML. For cross-browser XML generation, use methods on an\n- * instance of the XML format class instead of on document.\n- * The DOM creation and traversing methods exposed here all mimic the\n- * W3C XML DOM methods. Create a new parser with the\n- * constructor.\n- *\n- * Inherits from:\n- * - \n- */\n-OpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, {\n+ /**\n+ * APIProperty: minExtent\n+ * {|Array} If provided as an array, the array\n+ * should consist of four values (left, bottom, right, top).\n+ * The minimum extent for the map. Defaults to null.\n+ */\n+ minExtent: null,\n \n /**\n- * Property: namespaces\n- * {Object} Mapping of namespace aliases to namespace URIs. Properties\n- * of this object should not be set individually. Read-only. All\n- * XML subclasses should have their own namespaces object. Use\n- * to add or set a namespace alias after construction.\n+ * APIProperty: restrictedExtent\n+ * {|Array} If provided as an array, the array\n+ * should consist of four values (left, bottom, right, top).\n+ * Limit map navigation to this extent where possible.\n+ * If a non-null restrictedExtent is set, panning will be restricted\n+ * to the given bounds. In addition, zooming to a resolution that\n+ * displays more than the restricted extent will center the map\n+ * on the restricted extent. If you wish to limit the zoom level\n+ * or resolution, use maxResolution.\n */\n- namespaces: null,\n+ restrictedExtent: null,\n \n /**\n- * Property: namespaceAlias\n- * {Object} Mapping of namespace URI to namespace alias. This object\n- * is read-only. Use