--- /srv/reproducible-results/rbuild-debian/r-b-build.GFeAtFh3/b1/openlayers_2.13.1+ds2-10_i386.changes +++ /srv/reproducible-results/rbuild-debian/r-b-build.GFeAtFh3/b2/openlayers_2.13.1+ds2-10_i386.changes ├── Files │ @@ -1,2 +1,2 @@ │ │ - e10e99197b80e8001ad4aeb43e1d6b32 721476 javascript optional libjs-openlayers_2.13.1+ds2-10_all.deb │ + cb91a6b8575e4068f69c2c211e993efc 724396 javascript optional libjs-openlayers_2.13.1+ds2-10_all.deb ├── libjs-openlayers_2.13.1+ds2-10_all.deb │ ├── file list │ │ @@ -1,3 +1,3 @@ │ │ -rw-r--r-- 0 0 0 4 2023-01-14 13:27:41.000000 debian-binary │ │ --rw-r--r-- 0 0 0 3680 2023-01-14 13:27:41.000000 control.tar.xz │ │ --rw-r--r-- 0 0 0 717604 2023-01-14 13:27:41.000000 data.tar.xz │ │ +-rw-r--r-- 0 0 0 3676 2023-01-14 13:27:41.000000 control.tar.xz │ │ +-rw-r--r-- 0 0 0 720528 2023-01-14 13:27:41.000000 data.tar.xz │ ├── control.tar.xz │ │ ├── control.tar │ │ │ ├── ./md5sums │ │ │ │ ├── ./md5sums │ │ │ │ │┄ Files differ │ ├── data.tar.xz │ │ ├── data.tar │ │ │ ├── ./usr/share/javascript/openlayers/OpenLayers.js │ │ │ │ ├── js-beautify {} │ │ │ │ │ @@ -52,37 +52,14 @@ │ │ │ │ │ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS │ │ │ │ │ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN │ │ │ │ │ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) │ │ │ │ │ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE │ │ │ │ │ * POSSIBILITY OF SUCH DAMAGE. │ │ │ │ │ */ │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - Rico/license.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @license Apache 2 │ │ │ │ │ - * │ │ │ │ │ - * Contains portions of Rico │ │ │ │ │ - * │ │ │ │ │ - * Copyright 2005 Sabre Airline Solutions │ │ │ │ │ - * │ │ │ │ │ - * Licensed under the Apache License, Version 2.0 (the "License"); you │ │ │ │ │ - * may not use this file except in compliance with the License. You │ │ │ │ │ - * may obtain a copy of the License at │ │ │ │ │ - * │ │ │ │ │ - * http://www.apache.org/licenses/LICENSE-2.0 │ │ │ │ │ - * │ │ │ │ │ - * Unless required by applicable law or agreed to in writing, software │ │ │ │ │ - * distributed under the License is distributed on an "AS IS" BASIS, │ │ │ │ │ - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or │ │ │ │ │ - * implied. See the License for the specific language governing │ │ │ │ │ - * permissions and limitations under the License. │ │ │ │ │ - */ │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ OpenLayers/SingleFile.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ @@ -286,268 +263,14 @@ │ │ │ │ │ source.hasOwnProperty && source.hasOwnProperty("toString")) { │ │ │ │ │ destination.toString = source.toString; │ │ │ │ │ } │ │ │ │ │ } │ │ │ │ │ return destination; │ │ │ │ │ }; │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Console.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Namespace: OpenLayers.Console │ │ │ │ │ - * The OpenLayers.Console namespace is used for debugging and error logging. │ │ │ │ │ - * If the Firebug Lite (../Firebug/firebug.js) is included before this script, │ │ │ │ │ - * calls to OpenLayers.Console methods will get redirected to window.console. │ │ │ │ │ - * This makes use of the Firebug extension where available and allows for │ │ │ │ │ - * cross-browser debugging Firebug style. │ │ │ │ │ - * │ │ │ │ │ - * Note: │ │ │ │ │ - * Note that behavior will differ with the Firebug extention and Firebug Lite. │ │ │ │ │ - * Most notably, the Firebug Lite console does not currently allow for │ │ │ │ │ - * hyperlinks to code or for clicking on object to explore their properties. │ │ │ │ │ - * │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Console = { │ │ │ │ │ - /** │ │ │ │ │ - * Create empty functions for all console methods. The real value of these │ │ │ │ │ - * properties will be set if Firebug Lite (../Firebug/firebug.js script) is │ │ │ │ │ - * included. We explicitly require the Firebug Lite script to trigger │ │ │ │ │ - * functionality of the OpenLayers.Console methods. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: log │ │ │ │ │ - * Log an object in the console. The Firebug Lite console logs string │ │ │ │ │ - * representation of objects. Given multiple arguments, they will │ │ │ │ │ - * be cast to strings and logged with a space delimiter. If the first │ │ │ │ │ - * argument is a string with printf-like formatting, subsequent arguments │ │ │ │ │ - * will be used in string substitution. Any additional arguments (beyond │ │ │ │ │ - * the number substituted in a format string) will be appended in a space- │ │ │ │ │ - * delimited line. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} │ │ │ │ │ - */ │ │ │ │ │ - log: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: debug │ │ │ │ │ - * Writes a message to the console, including a hyperlink to the line │ │ │ │ │ - * where it was called. │ │ │ │ │ - * │ │ │ │ │ - * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} │ │ │ │ │ - */ │ │ │ │ │ - debug: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: info │ │ │ │ │ - * Writes a message to the console with the visual "info" icon and color │ │ │ │ │ - * coding and a hyperlink to the line where it was called. │ │ │ │ │ - * │ │ │ │ │ - * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} │ │ │ │ │ - */ │ │ │ │ │ - info: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: warn │ │ │ │ │ - * Writes a message to the console with the visual "warning" icon and │ │ │ │ │ - * color coding and a hyperlink to the line where it was called. │ │ │ │ │ - * │ │ │ │ │ - * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} │ │ │ │ │ - */ │ │ │ │ │ - warn: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: error │ │ │ │ │ - * Writes a message to the console with the visual "error" icon and color │ │ │ │ │ - * coding and a hyperlink to the line where it was called. │ │ │ │ │ - * │ │ │ │ │ - * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} │ │ │ │ │ - */ │ │ │ │ │ - error: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: userError │ │ │ │ │ - * A single interface for showing error messages to the user. The default │ │ │ │ │ - * behavior is a Javascript alert, though this can be overridden by │ │ │ │ │ - * reassigning OpenLayers.Console.userError to a different function. │ │ │ │ │ - * │ │ │ │ │ - * Expects a single error message │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * error - {Object} │ │ │ │ │ - */ │ │ │ │ │ - userError: function(error) { │ │ │ │ │ - alert(error); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: assert │ │ │ │ │ - * Tests that an expression is true. If not, it will write a message to │ │ │ │ │ - * the console and throw an exception. │ │ │ │ │ - * │ │ │ │ │ - * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} │ │ │ │ │ - */ │ │ │ │ │ - assert: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: dir │ │ │ │ │ - * Prints an interactive listing of all properties of the object. This │ │ │ │ │ - * looks identical to the view that you would see in the DOM tab. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} │ │ │ │ │ - */ │ │ │ │ │ - dir: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: dirxml │ │ │ │ │ - * Prints the XML source tree of an HTML or XML element. This looks │ │ │ │ │ - * identical to the view that you would see in the HTML tab. You can click │ │ │ │ │ - * on any node to inspect it in the HTML tab. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} │ │ │ │ │ - */ │ │ │ │ │ - dirxml: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: trace │ │ │ │ │ - * Prints an interactive stack trace of JavaScript execution at the point │ │ │ │ │ - * where it is called. The stack trace details the functions on the stack, │ │ │ │ │ - * as well as the values that were passed as arguments to each function. │ │ │ │ │ - * You can click each function to take you to its source in the Script tab, │ │ │ │ │ - * and click each argument value to inspect it in the DOM or HTML tabs. │ │ │ │ │ - * │ │ │ │ │ - */ │ │ │ │ │ - trace: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: group │ │ │ │ │ - * Writes a message to the console and opens a nested block to indent all │ │ │ │ │ - * future messages sent to the console. Call OpenLayers.Console.groupEnd() │ │ │ │ │ - * to close the block. │ │ │ │ │ - * │ │ │ │ │ - * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} │ │ │ │ │ - */ │ │ │ │ │ - group: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: groupEnd │ │ │ │ │ - * Closes the most recently opened block created by a call to │ │ │ │ │ - * OpenLayers.Console.group │ │ │ │ │ - */ │ │ │ │ │ - groupEnd: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: time │ │ │ │ │ - * Creates a new timer under the given name. Call │ │ │ │ │ - * OpenLayers.Console.timeEnd(name) │ │ │ │ │ - * with the same name to stop the timer and print the time elapsed. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * name - {String} │ │ │ │ │ - */ │ │ │ │ │ - time: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: timeEnd │ │ │ │ │ - * Stops a timer created by a call to OpenLayers.Console.time(name) and │ │ │ │ │ - * writes the time elapsed. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * name - {String} │ │ │ │ │ - */ │ │ │ │ │ - timeEnd: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: profile │ │ │ │ │ - * Turns on the JavaScript profiler. The optional argument title would │ │ │ │ │ - * contain the text to be printed in the header of the profile report. │ │ │ │ │ - * │ │ │ │ │ - * This function is not currently implemented in Firebug Lite. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * title - {String} Optional title for the profiler │ │ │ │ │ - */ │ │ │ │ │ - profile: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: profileEnd │ │ │ │ │ - * Turns off the JavaScript profiler and prints its report. │ │ │ │ │ - * │ │ │ │ │ - * This function is not currently implemented in Firebug Lite. │ │ │ │ │ - */ │ │ │ │ │ - profileEnd: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: count │ │ │ │ │ - * Writes the number of times that the line of code where count was called │ │ │ │ │ - * was executed. The optional argument title will print a message in │ │ │ │ │ - * addition to the number of the count. │ │ │ │ │ - * │ │ │ │ │ - * This function is not currently implemented in Firebug Lite. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * title - {String} Optional title to be printed with count │ │ │ │ │ - */ │ │ │ │ │ - count: function() {}, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Console" │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Execute an anonymous function to extend the OpenLayers.Console namespace │ │ │ │ │ - * if the firebug.js script is included. This closure is used so that the │ │ │ │ │ - * "scripts" and "i" variables don't pollute the global namespace. │ │ │ │ │ - */ │ │ │ │ │ -(function() { │ │ │ │ │ - /** │ │ │ │ │ - * If Firebug Lite is included (before this script), re-route all │ │ │ │ │ - * OpenLayers.Console calls to the console object. │ │ │ │ │ - */ │ │ │ │ │ - var scripts = document.getElementsByTagName("script"); │ │ │ │ │ - for (var i = 0, len = scripts.length; i < len; ++i) { │ │ │ │ │ - if (scripts[i].src.indexOf("firebug.js") != -1) { │ │ │ │ │ - if (console) { │ │ │ │ │ - OpenLayers.Util.extend(OpenLayers.Console, console); │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ -})(); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ OpenLayers/BaseTypes.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ @@ -1866,14 +1589,207 @@ │ │ │ │ │ │ │ │ │ │ opp += (quadrant.charAt(0) == 't') ? 'b' : 't'; │ │ │ │ │ opp += (quadrant.charAt(1) == 'l') ? 'r' : 'l'; │ │ │ │ │ │ │ │ │ │ return opp; │ │ │ │ │ }; │ │ │ │ │ /* ====================================================================== │ │ │ │ │ + OpenLayers/BaseTypes/Element.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Util.js │ │ │ │ │ + * @requires OpenLayers/BaseTypes.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Namespace: OpenLayers.Element │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Element = { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: visible │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Is the element visible? │ │ │ │ │ + */ │ │ │ │ │ + visible: function(element) { │ │ │ │ │ + return OpenLayers.Util.getElement(element).style.display != 'none'; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: toggle │ │ │ │ │ + * Toggle the visibility of element(s) passed in │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} Actually user can pass any number of elements │ │ │ │ │ + */ │ │ │ │ │ + toggle: function() { │ │ │ │ │ + for (var i = 0, len = arguments.length; i < len; i++) { │ │ │ │ │ + var element = OpenLayers.Util.getElement(arguments[i]); │ │ │ │ │ + var display = OpenLayers.Element.visible(element) ? 'none' : │ │ │ │ │ + ''; │ │ │ │ │ + element.style.display = display; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: remove │ │ │ │ │ + * Remove the specified element from the DOM. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} │ │ │ │ │ + */ │ │ │ │ │ + remove: function(element) { │ │ │ │ │ + element = OpenLayers.Util.getElement(element); │ │ │ │ │ + element.parentNode.removeChild(element); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: getHeight │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Integer} The offset height of the element passed in │ │ │ │ │ + */ │ │ │ │ │ + getHeight: function(element) { │ │ │ │ │ + element = OpenLayers.Util.getElement(element); │ │ │ │ │ + return element.offsetHeight; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Function: hasClass │ │ │ │ │ + * Tests if an element has the given CSS class name. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} A DOM element node. │ │ │ │ │ + * name - {String} The CSS class name to search for. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The element has the given class name. │ │ │ │ │ + */ │ │ │ │ │ + hasClass: function(element, name) { │ │ │ │ │ + var names = element.className; │ │ │ │ │ + return (!!names && new RegExp("(^|\\s)" + name + "(\\s|$)").test(names)); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Function: addClass │ │ │ │ │ + * Add a CSS class name to an element. Safe where element already has │ │ │ │ │ + * the class name. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} A DOM element node. │ │ │ │ │ + * name - {String} The CSS class name to add. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {DOMElement} The element. │ │ │ │ │ + */ │ │ │ │ │ + addClass: function(element, name) { │ │ │ │ │ + if (!OpenLayers.Element.hasClass(element, name)) { │ │ │ │ │ + element.className += (element.className ? " " : "") + name; │ │ │ │ │ + } │ │ │ │ │ + return element; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Function: removeClass │ │ │ │ │ + * Remove a CSS class name from an element. Safe where element does not │ │ │ │ │ + * have the class name. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} A DOM element node. │ │ │ │ │ + * name - {String} The CSS class name to remove. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {DOMElement} The element. │ │ │ │ │ + */ │ │ │ │ │ + removeClass: function(element, name) { │ │ │ │ │ + var names = element.className; │ │ │ │ │ + if (names) { │ │ │ │ │ + element.className = OpenLayers.String.trim( │ │ │ │ │ + names.replace( │ │ │ │ │ + new RegExp("(^|\\s+)" + name + "(\\s+|$)"), " " │ │ │ │ │ + ) │ │ │ │ │ + ); │ │ │ │ │ + } │ │ │ │ │ + return element; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Function: toggleClass │ │ │ │ │ + * Remove a CSS class name from an element if it exists. Add the class name │ │ │ │ │ + * if it doesn't exist. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} A DOM element node. │ │ │ │ │ + * name - {String} The CSS class name to toggle. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {DOMElement} The element. │ │ │ │ │ + */ │ │ │ │ │ + toggleClass: function(element, name) { │ │ │ │ │ + if (OpenLayers.Element.hasClass(element, name)) { │ │ │ │ │ + OpenLayers.Element.removeClass(element, name); │ │ │ │ │ + } else { │ │ │ │ │ + OpenLayers.Element.addClass(element, name); │ │ │ │ │ + } │ │ │ │ │ + return element; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: getStyle │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} │ │ │ │ │ + * style - {?} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {?} │ │ │ │ │ + */ │ │ │ │ │ + getStyle: function(element, style) { │ │ │ │ │ + element = OpenLayers.Util.getElement(element); │ │ │ │ │ + │ │ │ │ │ + var value = null; │ │ │ │ │ + if (element && element.style) { │ │ │ │ │ + value = element.style[OpenLayers.String.camelize(style)]; │ │ │ │ │ + if (!value) { │ │ │ │ │ + if (document.defaultView && │ │ │ │ │ + document.defaultView.getComputedStyle) { │ │ │ │ │ + │ │ │ │ │ + var css = document.defaultView.getComputedStyle(element, null); │ │ │ │ │ + value = css ? css.getPropertyValue(style) : null; │ │ │ │ │ + } else if (element.currentStyle) { │ │ │ │ │ + value = element.currentStyle[OpenLayers.String.camelize(style)]; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + var positions = ['left', 'top', 'right', 'bottom']; │ │ │ │ │ + if (window.opera && │ │ │ │ │ + (OpenLayers.Util.indexOf(positions, style) != -1) && │ │ │ │ │ + (OpenLayers.Element.getStyle(element, 'position') == 'static')) { │ │ │ │ │ + value = 'auto'; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + return value == 'auto' ? null : value; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ +}; │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ OpenLayers/BaseTypes/LonLat.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ @@ -2327,14 +2243,268 @@ │ │ │ │ │ } │ │ │ │ │ return equals; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ CLASS_NAME: "OpenLayers.Size" │ │ │ │ │ }); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ + OpenLayers/Console.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Namespace: OpenLayers.Console │ │ │ │ │ + * The OpenLayers.Console namespace is used for debugging and error logging. │ │ │ │ │ + * If the Firebug Lite (../Firebug/firebug.js) is included before this script, │ │ │ │ │ + * calls to OpenLayers.Console methods will get redirected to window.console. │ │ │ │ │ + * This makes use of the Firebug extension where available and allows for │ │ │ │ │ + * cross-browser debugging Firebug style. │ │ │ │ │ + * │ │ │ │ │ + * Note: │ │ │ │ │ + * Note that behavior will differ with the Firebug extention and Firebug Lite. │ │ │ │ │ + * Most notably, the Firebug Lite console does not currently allow for │ │ │ │ │ + * hyperlinks to code or for clicking on object to explore their properties. │ │ │ │ │ + * │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Console = { │ │ │ │ │ + /** │ │ │ │ │ + * Create empty functions for all console methods. The real value of these │ │ │ │ │ + * properties will be set if Firebug Lite (../Firebug/firebug.js script) is │ │ │ │ │ + * included. We explicitly require the Firebug Lite script to trigger │ │ │ │ │ + * functionality of the OpenLayers.Console methods. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: log │ │ │ │ │ + * Log an object in the console. The Firebug Lite console logs string │ │ │ │ │ + * representation of objects. Given multiple arguments, they will │ │ │ │ │ + * be cast to strings and logged with a space delimiter. If the first │ │ │ │ │ + * argument is a string with printf-like formatting, subsequent arguments │ │ │ │ │ + * will be used in string substitution. Any additional arguments (beyond │ │ │ │ │ + * the number substituted in a format string) will be appended in a space- │ │ │ │ │ + * delimited line. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} │ │ │ │ │ + */ │ │ │ │ │ + log: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: debug │ │ │ │ │ + * Writes a message to the console, including a hyperlink to the line │ │ │ │ │ + * where it was called. │ │ │ │ │ + * │ │ │ │ │ + * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} │ │ │ │ │ + */ │ │ │ │ │ + debug: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: info │ │ │ │ │ + * Writes a message to the console with the visual "info" icon and color │ │ │ │ │ + * coding and a hyperlink to the line where it was called. │ │ │ │ │ + * │ │ │ │ │ + * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} │ │ │ │ │ + */ │ │ │ │ │ + info: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: warn │ │ │ │ │ + * Writes a message to the console with the visual "warning" icon and │ │ │ │ │ + * color coding and a hyperlink to the line where it was called. │ │ │ │ │ + * │ │ │ │ │ + * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} │ │ │ │ │ + */ │ │ │ │ │ + warn: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: error │ │ │ │ │ + * Writes a message to the console with the visual "error" icon and color │ │ │ │ │ + * coding and a hyperlink to the line where it was called. │ │ │ │ │ + * │ │ │ │ │ + * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} │ │ │ │ │ + */ │ │ │ │ │ + error: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: userError │ │ │ │ │ + * A single interface for showing error messages to the user. The default │ │ │ │ │ + * behavior is a Javascript alert, though this can be overridden by │ │ │ │ │ + * reassigning OpenLayers.Console.userError to a different function. │ │ │ │ │ + * │ │ │ │ │ + * Expects a single error message │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * error - {Object} │ │ │ │ │ + */ │ │ │ │ │ + userError: function(error) { │ │ │ │ │ + alert(error); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: assert │ │ │ │ │ + * Tests that an expression is true. If not, it will write a message to │ │ │ │ │ + * the console and throw an exception. │ │ │ │ │ + * │ │ │ │ │ + * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} │ │ │ │ │ + */ │ │ │ │ │ + assert: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: dir │ │ │ │ │ + * Prints an interactive listing of all properties of the object. This │ │ │ │ │ + * looks identical to the view that you would see in the DOM tab. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} │ │ │ │ │ + */ │ │ │ │ │ + dir: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: dirxml │ │ │ │ │ + * Prints the XML source tree of an HTML or XML element. This looks │ │ │ │ │ + * identical to the view that you would see in the HTML tab. You can click │ │ │ │ │ + * on any node to inspect it in the HTML tab. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} │ │ │ │ │ + */ │ │ │ │ │ + dirxml: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: trace │ │ │ │ │ + * Prints an interactive stack trace of JavaScript execution at the point │ │ │ │ │ + * where it is called. The stack trace details the functions on the stack, │ │ │ │ │ + * as well as the values that were passed as arguments to each function. │ │ │ │ │ + * You can click each function to take you to its source in the Script tab, │ │ │ │ │ + * and click each argument value to inspect it in the DOM or HTML tabs. │ │ │ │ │ + * │ │ │ │ │ + */ │ │ │ │ │ + trace: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: group │ │ │ │ │ + * Writes a message to the console and opens a nested block to indent all │ │ │ │ │ + * future messages sent to the console. Call OpenLayers.Console.groupEnd() │ │ │ │ │ + * to close the block. │ │ │ │ │ + * │ │ │ │ │ + * May be called with multiple arguments as with OpenLayers.Console.log(). │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} │ │ │ │ │ + */ │ │ │ │ │ + group: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: groupEnd │ │ │ │ │ + * Closes the most recently opened block created by a call to │ │ │ │ │ + * OpenLayers.Console.group │ │ │ │ │ + */ │ │ │ │ │ + groupEnd: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: time │ │ │ │ │ + * Creates a new timer under the given name. Call │ │ │ │ │ + * OpenLayers.Console.timeEnd(name) │ │ │ │ │ + * with the same name to stop the timer and print the time elapsed. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * name - {String} │ │ │ │ │ + */ │ │ │ │ │ + time: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: timeEnd │ │ │ │ │ + * Stops a timer created by a call to OpenLayers.Console.time(name) and │ │ │ │ │ + * writes the time elapsed. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * name - {String} │ │ │ │ │ + */ │ │ │ │ │ + timeEnd: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: profile │ │ │ │ │ + * Turns on the JavaScript profiler. The optional argument title would │ │ │ │ │ + * contain the text to be printed in the header of the profile report. │ │ │ │ │ + * │ │ │ │ │ + * This function is not currently implemented in Firebug Lite. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * title - {String} Optional title for the profiler │ │ │ │ │ + */ │ │ │ │ │ + profile: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: profileEnd │ │ │ │ │ + * Turns off the JavaScript profiler and prints its report. │ │ │ │ │ + * │ │ │ │ │ + * This function is not currently implemented in Firebug Lite. │ │ │ │ │ + */ │ │ │ │ │ + profileEnd: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIFunction: count │ │ │ │ │ + * Writes the number of times that the line of code where count was called │ │ │ │ │ + * was executed. The optional argument title will print a message in │ │ │ │ │ + * addition to the number of the count. │ │ │ │ │ + * │ │ │ │ │ + * This function is not currently implemented in Firebug Lite. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * title - {String} Optional title to be printed with count │ │ │ │ │ + */ │ │ │ │ │ + count: function() {}, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Console" │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Execute an anonymous function to extend the OpenLayers.Console namespace │ │ │ │ │ + * if the firebug.js script is included. This closure is used so that the │ │ │ │ │ + * "scripts" and "i" variables don't pollute the global namespace. │ │ │ │ │ + */ │ │ │ │ │ +(function() { │ │ │ │ │ + /** │ │ │ │ │ + * If Firebug Lite is included (before this script), re-route all │ │ │ │ │ + * OpenLayers.Console calls to the console object. │ │ │ │ │ + */ │ │ │ │ │ + var scripts = document.getElementsByTagName("script"); │ │ │ │ │ + for (var i = 0, len = scripts.length; i < len; ++i) { │ │ │ │ │ + if (scripts[i].src.indexOf("firebug.js") != -1) { │ │ │ │ │ + if (console) { │ │ │ │ │ + OpenLayers.Util.extend(OpenLayers.Console, console); │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ +})(); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ OpenLayers/Lang.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ @@ -4256,1347 +4426,14 @@ │ │ │ │ │ } else { │ │ │ │ │ str += coordinate < 0 ? OpenLayers.i18n("S") : OpenLayers.i18n("N"); │ │ │ │ │ } │ │ │ │ │ return str; │ │ │ │ │ }; │ │ │ │ │ │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/BaseTypes/Element.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Util.js │ │ │ │ │ - * @requires OpenLayers/BaseTypes.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Namespace: OpenLayers.Element │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Element = { │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: visible │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} Is the element visible? │ │ │ │ │ - */ │ │ │ │ │ - visible: function(element) { │ │ │ │ │ - return OpenLayers.Util.getElement(element).style.display != 'none'; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: toggle │ │ │ │ │ - * Toggle the visibility of element(s) passed in │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} Actually user can pass any number of elements │ │ │ │ │ - */ │ │ │ │ │ - toggle: function() { │ │ │ │ │ - for (var i = 0, len = arguments.length; i < len; i++) { │ │ │ │ │ - var element = OpenLayers.Util.getElement(arguments[i]); │ │ │ │ │ - var display = OpenLayers.Element.visible(element) ? 'none' : │ │ │ │ │ - ''; │ │ │ │ │ - element.style.display = display; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: remove │ │ │ │ │ - * Remove the specified element from the DOM. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} │ │ │ │ │ - */ │ │ │ │ │ - remove: function(element) { │ │ │ │ │ - element = OpenLayers.Util.getElement(element); │ │ │ │ │ - element.parentNode.removeChild(element); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: getHeight │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Integer} The offset height of the element passed in │ │ │ │ │ - */ │ │ │ │ │ - getHeight: function(element) { │ │ │ │ │ - element = OpenLayers.Util.getElement(element); │ │ │ │ │ - return element.offsetHeight; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Function: hasClass │ │ │ │ │ - * Tests if an element has the given CSS class name. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} A DOM element node. │ │ │ │ │ - * name - {String} The CSS class name to search for. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} The element has the given class name. │ │ │ │ │ - */ │ │ │ │ │ - hasClass: function(element, name) { │ │ │ │ │ - var names = element.className; │ │ │ │ │ - return (!!names && new RegExp("(^|\\s)" + name + "(\\s|$)").test(names)); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Function: addClass │ │ │ │ │ - * Add a CSS class name to an element. Safe where element already has │ │ │ │ │ - * the class name. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} A DOM element node. │ │ │ │ │ - * name - {String} The CSS class name to add. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {DOMElement} The element. │ │ │ │ │ - */ │ │ │ │ │ - addClass: function(element, name) { │ │ │ │ │ - if (!OpenLayers.Element.hasClass(element, name)) { │ │ │ │ │ - element.className += (element.className ? " " : "") + name; │ │ │ │ │ - } │ │ │ │ │ - return element; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Function: removeClass │ │ │ │ │ - * Remove a CSS class name from an element. Safe where element does not │ │ │ │ │ - * have the class name. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} A DOM element node. │ │ │ │ │ - * name - {String} The CSS class name to remove. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {DOMElement} The element. │ │ │ │ │ - */ │ │ │ │ │ - removeClass: function(element, name) { │ │ │ │ │ - var names = element.className; │ │ │ │ │ - if (names) { │ │ │ │ │ - element.className = OpenLayers.String.trim( │ │ │ │ │ - names.replace( │ │ │ │ │ - new RegExp("(^|\\s+)" + name + "(\\s+|$)"), " " │ │ │ │ │ - ) │ │ │ │ │ - ); │ │ │ │ │ - } │ │ │ │ │ - return element; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Function: toggleClass │ │ │ │ │ - * Remove a CSS class name from an element if it exists. Add the class name │ │ │ │ │ - * if it doesn't exist. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} A DOM element node. │ │ │ │ │ - * name - {String} The CSS class name to toggle. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {DOMElement} The element. │ │ │ │ │ - */ │ │ │ │ │ - toggleClass: function(element, name) { │ │ │ │ │ - if (OpenLayers.Element.hasClass(element, name)) { │ │ │ │ │ - OpenLayers.Element.removeClass(element, name); │ │ │ │ │ - } else { │ │ │ │ │ - OpenLayers.Element.addClass(element, name); │ │ │ │ │ - } │ │ │ │ │ - return element; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIFunction: getStyle │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} │ │ │ │ │ - * style - {?} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {?} │ │ │ │ │ - */ │ │ │ │ │ - getStyle: function(element, style) { │ │ │ │ │ - element = OpenLayers.Util.getElement(element); │ │ │ │ │ - │ │ │ │ │ - var value = null; │ │ │ │ │ - if (element && element.style) { │ │ │ │ │ - value = element.style[OpenLayers.String.camelize(style)]; │ │ │ │ │ - if (!value) { │ │ │ │ │ - if (document.defaultView && │ │ │ │ │ - document.defaultView.getComputedStyle) { │ │ │ │ │ - │ │ │ │ │ - var css = document.defaultView.getComputedStyle(element, null); │ │ │ │ │ - value = css ? css.getPropertyValue(style) : null; │ │ │ │ │ - } else if (element.currentStyle) { │ │ │ │ │ - value = element.currentStyle[OpenLayers.String.camelize(style)]; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - var positions = ['left', 'top', 'right', 'bottom']; │ │ │ │ │ - if (window.opera && │ │ │ │ │ - (OpenLayers.Util.indexOf(positions, style) != -1) && │ │ │ │ │ - (OpenLayers.Element.getStyle(element, 'position') == 'static')) { │ │ │ │ │ - value = 'auto'; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - return value == 'auto' ? null : value; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ -}; │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - Rico/Color.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires Rico/license.js │ │ │ │ │ - * @requires OpenLayers/Console.js │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Element.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ -/* │ │ │ │ │ - * This file has been edited substantially from the Rico-released version by │ │ │ │ │ - * the OpenLayers development team. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Console.warn("OpenLayers.Rico is deprecated"); │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Rico = OpenLayers.Rico || {}; │ │ │ │ │ -OpenLayers.Rico.Color = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - initialize: function(red, green, blue) { │ │ │ │ │ - this.rgb = { │ │ │ │ │ - r: red, │ │ │ │ │ - g: green, │ │ │ │ │ - b: blue │ │ │ │ │ - }; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - setRed: function(r) { │ │ │ │ │ - this.rgb.r = r; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - setGreen: function(g) { │ │ │ │ │ - this.rgb.g = g; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - setBlue: function(b) { │ │ │ │ │ - this.rgb.b = b; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - setHue: function(h) { │ │ │ │ │ - │ │ │ │ │ - // get an HSB model, and set the new hue... │ │ │ │ │ - var hsb = this.asHSB(); │ │ │ │ │ - hsb.h = h; │ │ │ │ │ - │ │ │ │ │ - // convert back to RGB... │ │ │ │ │ - this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - setSaturation: function(s) { │ │ │ │ │ - // get an HSB model, and set the new hue... │ │ │ │ │ - var hsb = this.asHSB(); │ │ │ │ │ - hsb.s = s; │ │ │ │ │ - │ │ │ │ │ - // convert back to RGB and set values... │ │ │ │ │ - this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - setBrightness: function(b) { │ │ │ │ │ - // get an HSB model, and set the new hue... │ │ │ │ │ - var hsb = this.asHSB(); │ │ │ │ │ - hsb.b = b; │ │ │ │ │ - │ │ │ │ │ - // convert back to RGB and set values... │ │ │ │ │ - this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - darken: function(percent) { │ │ │ │ │ - var hsb = this.asHSB(); │ │ │ │ │ - this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent, 0)); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - brighten: function(percent) { │ │ │ │ │ - var hsb = this.asHSB(); │ │ │ │ │ - this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent, 1)); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - blend: function(other) { │ │ │ │ │ - this.rgb.r = Math.floor((this.rgb.r + other.rgb.r) / 2); │ │ │ │ │ - this.rgb.g = Math.floor((this.rgb.g + other.rgb.g) / 2); │ │ │ │ │ - this.rgb.b = Math.floor((this.rgb.b + other.rgb.b) / 2); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - isBright: function() { │ │ │ │ │ - var hsb = this.asHSB(); │ │ │ │ │ - return this.asHSB().b > 0.5; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - isDark: function() { │ │ │ │ │ - return !this.isBright(); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - asRGB: function() { │ │ │ │ │ - return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")"; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - asHex: function() { │ │ │ │ │ - return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart(); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - asHSB: function() { │ │ │ │ │ - return OpenLayers.Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - toString: function() { │ │ │ │ │ - return this.asHex(); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Rico.Color.createFromHex = function(hexCode) { │ │ │ │ │ - if (hexCode.length == 4) { │ │ │ │ │ - var shortHexCode = hexCode; │ │ │ │ │ - var hexCode = '#'; │ │ │ │ │ - for (var i = 1; i < 4; i++) { │ │ │ │ │ - hexCode += (shortHexCode.charAt(i) + │ │ │ │ │ - shortHexCode.charAt(i)); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - if (hexCode.indexOf('#') == 0) { │ │ │ │ │ - hexCode = hexCode.substring(1); │ │ │ │ │ - } │ │ │ │ │ - var red = hexCode.substring(0, 2); │ │ │ │ │ - var green = hexCode.substring(2, 4); │ │ │ │ │ - var blue = hexCode.substring(4, 6); │ │ │ │ │ - return new OpenLayers.Rico.Color(parseInt(red, 16), parseInt(green, 16), parseInt(blue, 16)); │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Factory method for creating a color from the background of │ │ │ │ │ - * an HTML element. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Rico.Color.createColorFromBackground = function(elem) { │ │ │ │ │ - │ │ │ │ │ - var actualColor = │ │ │ │ │ - OpenLayers.Element.getStyle(OpenLayers.Util.getElement(elem), │ │ │ │ │ - "backgroundColor"); │ │ │ │ │ - │ │ │ │ │ - if (actualColor == "transparent" && elem.parentNode) { │ │ │ │ │ - return OpenLayers.Rico.Color.createColorFromBackground(elem.parentNode); │ │ │ │ │ - } │ │ │ │ │ - if (actualColor == null) { │ │ │ │ │ - return new OpenLayers.Rico.Color(255, 255, 255); │ │ │ │ │ - } │ │ │ │ │ - if (actualColor.indexOf("rgb(") == 0) { │ │ │ │ │ - var colors = actualColor.substring(4, actualColor.length - 1); │ │ │ │ │ - var colorArray = colors.split(","); │ │ │ │ │ - return new OpenLayers.Rico.Color(parseInt(colorArray[0]), │ │ │ │ │ - parseInt(colorArray[1]), │ │ │ │ │ - parseInt(colorArray[2])); │ │ │ │ │ - │ │ │ │ │ - } else if (actualColor.indexOf("#") == 0) { │ │ │ │ │ - return OpenLayers.Rico.Color.createFromHex(actualColor); │ │ │ │ │ - } else { │ │ │ │ │ - return new OpenLayers.Rico.Color(255, 255, 255); │ │ │ │ │ - } │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Rico.Color.HSBtoRGB = function(hue, saturation, brightness) { │ │ │ │ │ - │ │ │ │ │ - var red = 0; │ │ │ │ │ - var green = 0; │ │ │ │ │ - var blue = 0; │ │ │ │ │ - │ │ │ │ │ - if (saturation == 0) { │ │ │ │ │ - red = parseInt(brightness * 255.0 + 0.5); │ │ │ │ │ - green = red; │ │ │ │ │ - blue = red; │ │ │ │ │ - } else { │ │ │ │ │ - var h = (hue - Math.floor(hue)) * 6.0; │ │ │ │ │ - var f = h - Math.floor(h); │ │ │ │ │ - var p = brightness * (1.0 - saturation); │ │ │ │ │ - var q = brightness * (1.0 - saturation * f); │ │ │ │ │ - var t = brightness * (1.0 - (saturation * (1.0 - f))); │ │ │ │ │ - │ │ │ │ │ - switch (parseInt(h)) { │ │ │ │ │ - case 0: │ │ │ │ │ - red = (brightness * 255.0 + 0.5); │ │ │ │ │ - green = (t * 255.0 + 0.5); │ │ │ │ │ - blue = (p * 255.0 + 0.5); │ │ │ │ │ - break; │ │ │ │ │ - case 1: │ │ │ │ │ - red = (q * 255.0 + 0.5); │ │ │ │ │ - green = (brightness * 255.0 + 0.5); │ │ │ │ │ - blue = (p * 255.0 + 0.5); │ │ │ │ │ - break; │ │ │ │ │ - case 2: │ │ │ │ │ - red = (p * 255.0 + 0.5); │ │ │ │ │ - green = (brightness * 255.0 + 0.5); │ │ │ │ │ - blue = (t * 255.0 + 0.5); │ │ │ │ │ - break; │ │ │ │ │ - case 3: │ │ │ │ │ - red = (p * 255.0 + 0.5); │ │ │ │ │ - green = (q * 255.0 + 0.5); │ │ │ │ │ - blue = (brightness * 255.0 + 0.5); │ │ │ │ │ - break; │ │ │ │ │ - case 4: │ │ │ │ │ - red = (t * 255.0 + 0.5); │ │ │ │ │ - green = (p * 255.0 + 0.5); │ │ │ │ │ - blue = (brightness * 255.0 + 0.5); │ │ │ │ │ - break; │ │ │ │ │ - case 5: │ │ │ │ │ - red = (brightness * 255.0 + 0.5); │ │ │ │ │ - green = (p * 255.0 + 0.5); │ │ │ │ │ - blue = (q * 255.0 + 0.5); │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - return { │ │ │ │ │ - r: parseInt(red), │ │ │ │ │ - g: parseInt(green), │ │ │ │ │ - b: parseInt(blue) │ │ │ │ │ - }; │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Rico.Color.RGBtoHSB = function(r, g, b) { │ │ │ │ │ - │ │ │ │ │ - var hue; │ │ │ │ │ - var saturation; │ │ │ │ │ - var brightness; │ │ │ │ │ - │ │ │ │ │ - var cmax = (r > g) ? r : g; │ │ │ │ │ - if (b > cmax) { │ │ │ │ │ - cmax = b; │ │ │ │ │ - } │ │ │ │ │ - var cmin = (r < g) ? r : g; │ │ │ │ │ - if (b < cmin) { │ │ │ │ │ - cmin = b; │ │ │ │ │ - } │ │ │ │ │ - brightness = cmax / 255.0; │ │ │ │ │ - if (cmax != 0) { │ │ │ │ │ - saturation = (cmax - cmin) / cmax; │ │ │ │ │ - } else { │ │ │ │ │ - saturation = 0; │ │ │ │ │ - } │ │ │ │ │ - if (saturation == 0) { │ │ │ │ │ - hue = 0; │ │ │ │ │ - } else { │ │ │ │ │ - var redc = (cmax - r) / (cmax - cmin); │ │ │ │ │ - var greenc = (cmax - g) / (cmax - cmin); │ │ │ │ │ - var bluec = (cmax - b) / (cmax - cmin); │ │ │ │ │ - │ │ │ │ │ - if (r == cmax) { │ │ │ │ │ - hue = bluec - greenc; │ │ │ │ │ - } else if (g == cmax) { │ │ │ │ │ - hue = 2.0 + redc - bluec; │ │ │ │ │ - } else { │ │ │ │ │ - hue = 4.0 + greenc - redc; │ │ │ │ │ - } │ │ │ │ │ - hue = hue / 6.0; │ │ │ │ │ - if (hue < 0) { │ │ │ │ │ - hue = hue + 1.0; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - return { │ │ │ │ │ - h: hue, │ │ │ │ │ - s: saturation, │ │ │ │ │ - b: brightness │ │ │ │ │ - }; │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - Rico/Corner.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Console.js │ │ │ │ │ - * @requires Rico/Color.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ -/* │ │ │ │ │ - * This file has been edited substantially from the Rico-released │ │ │ │ │ - * version by the OpenLayers development team. │ │ │ │ │ - * │ │ │ │ │ - * Copyright 2005 Sabre Airline Solutions │ │ │ │ │ - * │ │ │ │ │ - * Licensed under the Apache License, Version 2.0 (the "License"); │ │ │ │ │ - * you may not use this file except in compliance with the │ │ │ │ │ - * License. You may obtain a copy of the License at │ │ │ │ │ - * │ │ │ │ │ - * http://www.apache.org/licenses/LICENSE-2.0 │ │ │ │ │ - * │ │ │ │ │ - * Unless required by applicable law or agreed to in writing, software │ │ │ │ │ - * distributed under the * License is distributed on an "AS IS" BASIS, │ │ │ │ │ - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or │ │ │ │ │ - * implied. See the License for the specific language governing │ │ │ │ │ - * permissions * and limitations under the License. │ │ │ │ │ - * │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Console.warn("OpenLayers.Rico is deprecated"); │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Rico = OpenLayers.Rico || {}; │ │ │ │ │ -OpenLayers.Rico.Corner = { │ │ │ │ │ - │ │ │ │ │ - round: function(e, options) { │ │ │ │ │ - e = OpenLayers.Util.getElement(e); │ │ │ │ │ - this._setOptions(options); │ │ │ │ │ - │ │ │ │ │ - var color = this.options.color; │ │ │ │ │ - if (this.options.color == "fromElement") { │ │ │ │ │ - color = this._background(e); │ │ │ │ │ - } │ │ │ │ │ - var bgColor = this.options.bgColor; │ │ │ │ │ - if (this.options.bgColor == "fromParent") { │ │ │ │ │ - bgColor = this._background(e.offsetParent); │ │ │ │ │ - } │ │ │ │ │ - this._roundCornersImpl(e, color, bgColor); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** This is a helper function to change the background │ │ │ │ │ - * color of
that has had Rico rounded corners added. │ │ │ │ │ - * │ │ │ │ │ - * It seems we cannot just set the background color for the │ │ │ │ │ - * outer
so each element used to create the │ │ │ │ │ - * corners must have its background color set individually. │ │ │ │ │ - * │ │ │ │ │ - * @param {DOM} theDiv - A child of the outer
that was │ │ │ │ │ - * supplied to the `round` method. │ │ │ │ │ - * │ │ │ │ │ - * @param {String} newColor - The new background color to use. │ │ │ │ │ - */ │ │ │ │ │ - changeColor: function(theDiv, newColor) { │ │ │ │ │ - │ │ │ │ │ - theDiv.style.backgroundColor = newColor; │ │ │ │ │ - │ │ │ │ │ - var spanElements = theDiv.parentNode.getElementsByTagName("span"); │ │ │ │ │ - │ │ │ │ │ - for (var currIdx = 0; currIdx < spanElements.length; currIdx++) { │ │ │ │ │ - spanElements[currIdx].style.backgroundColor = newColor; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ - /** This is a helper function to change the background │ │ │ │ │ - * opacity of
that has had Rico rounded corners added. │ │ │ │ │ - * │ │ │ │ │ - * See changeColor (above) for algorithm explanation │ │ │ │ │ - * │ │ │ │ │ - * @param {DOM} theDiv A child of the outer
that was │ │ │ │ │ - * supplied to the `round` method. │ │ │ │ │ - * │ │ │ │ │ - * @param {int} newOpacity The new opacity to use (0-1). │ │ │ │ │ - */ │ │ │ │ │ - changeOpacity: function(theDiv, newOpacity) { │ │ │ │ │ - │ │ │ │ │ - var mozillaOpacity = newOpacity; │ │ │ │ │ - var ieOpacity = 'alpha(opacity=' + newOpacity * 100 + ')'; │ │ │ │ │ - │ │ │ │ │ - theDiv.style.opacity = mozillaOpacity; │ │ │ │ │ - theDiv.style.filter = ieOpacity; │ │ │ │ │ - │ │ │ │ │ - var spanElements = theDiv.parentNode.getElementsByTagName("span"); │ │ │ │ │ - │ │ │ │ │ - for (var currIdx = 0; currIdx < spanElements.length; currIdx++) { │ │ │ │ │ - spanElements[currIdx].style.opacity = mozillaOpacity; │ │ │ │ │ - spanElements[currIdx].style.filter = ieOpacity; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** this function takes care of redoing the rico cornering │ │ │ │ │ - * │ │ │ │ │ - * you can't just call updateRicoCorners() again and pass it a │ │ │ │ │ - * new options string. you have to first remove the divs that │ │ │ │ │ - * rico puts on top and below the content div. │ │ │ │ │ - * │ │ │ │ │ - * @param {DOM} theDiv - A child of the outer
that was │ │ │ │ │ - * supplied to the `round` method. │ │ │ │ │ - * │ │ │ │ │ - * @param {Object} options - list of options │ │ │ │ │ - */ │ │ │ │ │ - reRound: function(theDiv, options) { │ │ │ │ │ - │ │ │ │ │ - var topRico = theDiv.parentNode.childNodes[0]; │ │ │ │ │ - //theDiv would be theDiv.parentNode.childNodes[1] │ │ │ │ │ - var bottomRico = theDiv.parentNode.childNodes[2]; │ │ │ │ │ - │ │ │ │ │ - theDiv.parentNode.removeChild(topRico); │ │ │ │ │ - theDiv.parentNode.removeChild(bottomRico); │ │ │ │ │ - │ │ │ │ │ - this.round(theDiv.parentNode, options); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _roundCornersImpl: function(e, color, bgColor) { │ │ │ │ │ - if (this.options.border) { │ │ │ │ │ - this._renderBorder(e, bgColor); │ │ │ │ │ - } │ │ │ │ │ - if (this._isTopRounded()) { │ │ │ │ │ - this._roundTopCorners(e, color, bgColor); │ │ │ │ │ - } │ │ │ │ │ - if (this._isBottomRounded()) { │ │ │ │ │ - this._roundBottomCorners(e, color, bgColor); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _renderBorder: function(el, bgColor) { │ │ │ │ │ - var borderValue = "1px solid " + this._borderColor(bgColor); │ │ │ │ │ - var borderL = "border-left: " + borderValue; │ │ │ │ │ - var borderR = "border-right: " + borderValue; │ │ │ │ │ - var style = "style='" + borderL + ";" + borderR + "'"; │ │ │ │ │ - el.innerHTML = "
" + el.innerHTML + "
"; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _roundTopCorners: function(el, color, bgColor) { │ │ │ │ │ - var corner = this._createCorner(bgColor); │ │ │ │ │ - for (var i = 0; i < this.options.numSlices; i++) { │ │ │ │ │ - corner.appendChild(this._createCornerSlice(color, bgColor, i, "top")); │ │ │ │ │ - } │ │ │ │ │ - el.style.paddingTop = 0; │ │ │ │ │ - el.insertBefore(corner, el.firstChild); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _roundBottomCorners: function(el, color, bgColor) { │ │ │ │ │ - var corner = this._createCorner(bgColor); │ │ │ │ │ - for (var i = (this.options.numSlices - 1); i >= 0; i--) { │ │ │ │ │ - corner.appendChild(this._createCornerSlice(color, bgColor, i, "bottom")); │ │ │ │ │ - } │ │ │ │ │ - el.style.paddingBottom = 0; │ │ │ │ │ - el.appendChild(corner); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _createCorner: function(bgColor) { │ │ │ │ │ - var corner = document.createElement("div"); │ │ │ │ │ - corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor); │ │ │ │ │ - return corner; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _createCornerSlice: function(color, bgColor, n, position) { │ │ │ │ │ - var slice = document.createElement("span"); │ │ │ │ │ - │ │ │ │ │ - var inStyle = slice.style; │ │ │ │ │ - inStyle.backgroundColor = color; │ │ │ │ │ - inStyle.display = "block"; │ │ │ │ │ - inStyle.height = "1px"; │ │ │ │ │ - inStyle.overflow = "hidden"; │ │ │ │ │ - inStyle.fontSize = "1px"; │ │ │ │ │ - │ │ │ │ │ - var borderColor = this._borderColor(color, bgColor); │ │ │ │ │ - if (this.options.border && n == 0) { │ │ │ │ │ - inStyle.borderTopStyle = "solid"; │ │ │ │ │ - inStyle.borderTopWidth = "1px"; │ │ │ │ │ - inStyle.borderLeftWidth = "0px"; │ │ │ │ │ - inStyle.borderRightWidth = "0px"; │ │ │ │ │ - inStyle.borderBottomWidth = "0px"; │ │ │ │ │ - inStyle.height = "0px"; // assumes css compliant box model │ │ │ │ │ - inStyle.borderColor = borderColor; │ │ │ │ │ - } else if (borderColor) { │ │ │ │ │ - inStyle.borderColor = borderColor; │ │ │ │ │ - inStyle.borderStyle = "solid"; │ │ │ │ │ - inStyle.borderWidth = "0px 1px"; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (!this.options.compact && (n == (this.options.numSlices - 1))) { │ │ │ │ │ - inStyle.height = "2px"; │ │ │ │ │ - } │ │ │ │ │ - this._setMargin(slice, n, position); │ │ │ │ │ - this._setBorder(slice, n, position); │ │ │ │ │ - return slice; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _setOptions: function(options) { │ │ │ │ │ - this.options = { │ │ │ │ │ - corners: "all", │ │ │ │ │ - color: "fromElement", │ │ │ │ │ - bgColor: "fromParent", │ │ │ │ │ - blend: true, │ │ │ │ │ - border: false, │ │ │ │ │ - compact: false │ │ │ │ │ - }; │ │ │ │ │ - OpenLayers.Util.extend(this.options, options || {}); │ │ │ │ │ - │ │ │ │ │ - this.options.numSlices = this.options.compact ? 2 : 4; │ │ │ │ │ - if (this._isTransparent()) { │ │ │ │ │ - this.options.blend = false; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _whichSideTop: function() { │ │ │ │ │ - if (this._hasString(this.options.corners, "all", "top")) { │ │ │ │ │ - return ""; │ │ │ │ │ - } │ │ │ │ │ - if (this.options.corners.indexOf("tl") >= 0 && this.options.corners.indexOf("tr") >= 0) { │ │ │ │ │ - return ""; │ │ │ │ │ - } │ │ │ │ │ - if (this.options.corners.indexOf("tl") >= 0) { │ │ │ │ │ - return "left"; │ │ │ │ │ - } else if (this.options.corners.indexOf("tr") >= 0) { │ │ │ │ │ - return "right"; │ │ │ │ │ - } │ │ │ │ │ - return ""; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _whichSideBottom: function() { │ │ │ │ │ - if (this._hasString(this.options.corners, "all", "bottom")) { │ │ │ │ │ - return ""; │ │ │ │ │ - } │ │ │ │ │ - if (this.options.corners.indexOf("bl") >= 0 && this.options.corners.indexOf("br") >= 0) { │ │ │ │ │ - return ""; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (this.options.corners.indexOf("bl") >= 0) { │ │ │ │ │ - return "left"; │ │ │ │ │ - } else if (this.options.corners.indexOf("br") >= 0) { │ │ │ │ │ - return "right"; │ │ │ │ │ - } │ │ │ │ │ - return ""; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _borderColor: function(color, bgColor) { │ │ │ │ │ - if (color == "transparent") { │ │ │ │ │ - return bgColor; │ │ │ │ │ - } else if (this.options.border) { │ │ │ │ │ - return this.options.border; │ │ │ │ │ - } else if (this.options.blend) { │ │ │ │ │ - return this._blend(bgColor, color); │ │ │ │ │ - } else { │ │ │ │ │ - return ""; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ - _setMargin: function(el, n, corners) { │ │ │ │ │ - var marginSize = this._marginSize(n); │ │ │ │ │ - var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom(); │ │ │ │ │ - │ │ │ │ │ - if (whichSide == "left") { │ │ │ │ │ - el.style.marginLeft = marginSize + "px"; │ │ │ │ │ - el.style.marginRight = "0px"; │ │ │ │ │ - } else if (whichSide == "right") { │ │ │ │ │ - el.style.marginRight = marginSize + "px"; │ │ │ │ │ - el.style.marginLeft = "0px"; │ │ │ │ │ - } else { │ │ │ │ │ - el.style.marginLeft = marginSize + "px"; │ │ │ │ │ - el.style.marginRight = marginSize + "px"; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _setBorder: function(el, n, corners) { │ │ │ │ │ - var borderSize = this._borderSize(n); │ │ │ │ │ - var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom(); │ │ │ │ │ - if (whichSide == "left") { │ │ │ │ │ - el.style.borderLeftWidth = borderSize + "px"; │ │ │ │ │ - el.style.borderRightWidth = "0px"; │ │ │ │ │ - } else if (whichSide == "right") { │ │ │ │ │ - el.style.borderRightWidth = borderSize + "px"; │ │ │ │ │ - el.style.borderLeftWidth = "0px"; │ │ │ │ │ - } else { │ │ │ │ │ - el.style.borderLeftWidth = borderSize + "px"; │ │ │ │ │ - el.style.borderRightWidth = borderSize + "px"; │ │ │ │ │ - } │ │ │ │ │ - if (this.options.border != false) { │ │ │ │ │ - el.style.borderLeftWidth = borderSize + "px"; │ │ │ │ │ - el.style.borderRightWidth = borderSize + "px"; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _marginSize: function(n) { │ │ │ │ │ - if (this._isTransparent()) { │ │ │ │ │ - return 0; │ │ │ │ │ - } │ │ │ │ │ - var marginSizes = [5, 3, 2, 1]; │ │ │ │ │ - var blendedMarginSizes = [3, 2, 1, 0]; │ │ │ │ │ - var compactMarginSizes = [2, 1]; │ │ │ │ │ - var smBlendedMarginSizes = [1, 0]; │ │ │ │ │ - │ │ │ │ │ - if (this.options.compact && this.options.blend) { │ │ │ │ │ - return smBlendedMarginSizes[n]; │ │ │ │ │ - } else if (this.options.compact) { │ │ │ │ │ - return compactMarginSizes[n]; │ │ │ │ │ - } else if (this.options.blend) { │ │ │ │ │ - return blendedMarginSizes[n]; │ │ │ │ │ - } else { │ │ │ │ │ - return marginSizes[n]; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _borderSize: function(n) { │ │ │ │ │ - var transparentBorderSizes = [5, 3, 2, 1]; │ │ │ │ │ - var blendedBorderSizes = [2, 1, 1, 1]; │ │ │ │ │ - var compactBorderSizes = [1, 0]; │ │ │ │ │ - var actualBorderSizes = [0, 2, 0, 0]; │ │ │ │ │ - │ │ │ │ │ - if (this.options.compact && (this.options.blend || this._isTransparent())) { │ │ │ │ │ - return 1; │ │ │ │ │ - } else if (this.options.compact) { │ │ │ │ │ - return compactBorderSizes[n]; │ │ │ │ │ - } else if (this.options.blend) { │ │ │ │ │ - return blendedBorderSizes[n]; │ │ │ │ │ - } else if (this.options.border) { │ │ │ │ │ - return actualBorderSizes[n]; │ │ │ │ │ - } else if (this._isTransparent()) { │ │ │ │ │ - return transparentBorderSizes[n]; │ │ │ │ │ - } │ │ │ │ │ - return 0; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - _hasString: function(str) { │ │ │ │ │ - for (var i = 1; i < arguments.length; i++) │ │ │ │ │ - if (str.indexOf(arguments[i]) >= 0) { │ │ │ │ │ - return true; │ │ │ │ │ - } return false; │ │ │ │ │ - }, │ │ │ │ │ - _blend: function(c1, c2) { │ │ │ │ │ - var cc1 = OpenLayers.Rico.Color.createFromHex(c1); │ │ │ │ │ - cc1.blend(OpenLayers.Rico.Color.createFromHex(c2)); │ │ │ │ │ - return cc1; │ │ │ │ │ - }, │ │ │ │ │ - _background: function(el) { │ │ │ │ │ - try { │ │ │ │ │ - return OpenLayers.Rico.Color.createColorFromBackground(el).asHex(); │ │ │ │ │ - } catch (err) { │ │ │ │ │ - return "#ffffff"; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - _isTransparent: function() { │ │ │ │ │ - return this.options.color == "transparent"; │ │ │ │ │ - }, │ │ │ │ │ - _isTopRounded: function() { │ │ │ │ │ - return this._hasString(this.options.corners, "all", "top", "tl", "tr"); │ │ │ │ │ - }, │ │ │ │ │ - _isBottomRounded: function() { │ │ │ │ │ - return this._hasString(this.options.corners, "all", "bottom", "bl", "br"); │ │ │ │ │ - }, │ │ │ │ │ - _hasSingleTextChild: function(el) { │ │ │ │ │ - return el.childNodes.length == 1 && el.childNodes[0].nodeType == 3; │ │ │ │ │ - } │ │ │ │ │ -}; │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Geometry.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Geometry │ │ │ │ │ - * A Geometry is a description of a geographic object. Create an instance of │ │ │ │ │ - * this class with the constructor. This is a base class, │ │ │ │ │ - * typical geometry types are described by subclasses of this class. │ │ │ │ │ - * │ │ │ │ │ - * Note that if you use the method, you must │ │ │ │ │ - * explicitly include the OpenLayers.Format.WKT in your build. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Geometry = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: id │ │ │ │ │ - * {String} A unique identifier for this geometry. │ │ │ │ │ - */ │ │ │ │ │ - id: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: parent │ │ │ │ │ - * {}This is set when a Geometry is added as component │ │ │ │ │ - * of another geometry │ │ │ │ │ - */ │ │ │ │ │ - parent: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: bounds │ │ │ │ │ - * {} The bounds of this geometry │ │ │ │ │ - */ │ │ │ │ │ - bounds: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Geometry │ │ │ │ │ - * Creates a geometry object. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function() { │ │ │ │ │ - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: destroy │ │ │ │ │ - * Destroy this geometry. │ │ │ │ │ - */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - this.id = null; │ │ │ │ │ - this.bounds = null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: clone │ │ │ │ │ - * Create a clone of this geometry. Does not set any non-standard │ │ │ │ │ - * properties of the cloned geometry. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} An exact clone of this geometry. │ │ │ │ │ - */ │ │ │ │ │ - clone: function() { │ │ │ │ │ - return new OpenLayers.Geometry(); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: setBounds │ │ │ │ │ - * Set the bounds for this Geometry. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * bounds - {} │ │ │ │ │ - */ │ │ │ │ │ - setBounds: function(bounds) { │ │ │ │ │ - if (bounds) { │ │ │ │ │ - this.bounds = bounds.clone(); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: clearBounds │ │ │ │ │ - * Nullify this components bounds and that of its parent as well. │ │ │ │ │ - */ │ │ │ │ │ - clearBounds: function() { │ │ │ │ │ - this.bounds = null; │ │ │ │ │ - if (this.parent) { │ │ │ │ │ - this.parent.clearBounds(); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: extendBounds │ │ │ │ │ - * Extend the existing bounds to include the new bounds. │ │ │ │ │ - * If geometry's bounds is not yet set, then set a new Bounds. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * newBounds - {} │ │ │ │ │ - */ │ │ │ │ │ - extendBounds: function(newBounds) { │ │ │ │ │ - var bounds = this.getBounds(); │ │ │ │ │ - if (!bounds) { │ │ │ │ │ - this.setBounds(newBounds); │ │ │ │ │ - } else { │ │ │ │ │ - this.bounds.extend(newBounds); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: getBounds │ │ │ │ │ - * Get the bounds for this Geometry. If bounds is not set, it │ │ │ │ │ - * is calculated again, this makes queries faster. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} │ │ │ │ │ - */ │ │ │ │ │ - getBounds: function() { │ │ │ │ │ - if (this.bounds == null) { │ │ │ │ │ - this.calculateBounds(); │ │ │ │ │ - } │ │ │ │ │ - return this.bounds; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: calculateBounds │ │ │ │ │ - * Recalculate the bounds for the geometry. │ │ │ │ │ - */ │ │ │ │ │ - calculateBounds: function() { │ │ │ │ │ - // │ │ │ │ │ - // This should be overridden by subclasses. │ │ │ │ │ - // │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: distanceTo │ │ │ │ │ - * Calculate the closest distance between two geometries (on the x-y plane). │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * geometry - {} The target geometry. │ │ │ │ │ - * options - {Object} Optional properties for configuring the distance │ │ │ │ │ - * calculation. │ │ │ │ │ - * │ │ │ │ │ - * Valid options depend on the specific geometry type. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Number | Object} The distance between this geometry and the target. │ │ │ │ │ - * If details is true, the return will be an object with distance, │ │ │ │ │ - * x0, y0, x1, and x2 properties. The x0 and y0 properties represent │ │ │ │ │ - * the coordinates of the closest point on this geometry. The x1 and y1 │ │ │ │ │ - * properties represent the coordinates of the closest point on the │ │ │ │ │ - * target geometry. │ │ │ │ │ - */ │ │ │ │ │ - distanceTo: function(geometry, options) {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: getVertices │ │ │ │ │ - * Return a list of all points in this geometry. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * nodes - {Boolean} For lines, only return vertices that are │ │ │ │ │ - * endpoints. If false, for lines, only vertices that are not │ │ │ │ │ - * endpoints will be returned. If not provided, all vertices will │ │ │ │ │ - * be returned. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Array} A list of all vertices in the geometry. │ │ │ │ │ - */ │ │ │ │ │ - getVertices: function(nodes) {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: atPoint │ │ │ │ │ - * Note - This is only an approximation based on the bounds of the │ │ │ │ │ - * geometry. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * lonlat - {|Object} OpenLayers.LonLat or an │ │ │ │ │ - * object with a 'lon' and 'lat' properties. │ │ │ │ │ - * toleranceLon - {float} Optional tolerance in Geometric Coords │ │ │ │ │ - * toleranceLat - {float} Optional tolerance in Geographic Coords │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} Whether or not the geometry is at the specified location │ │ │ │ │ - */ │ │ │ │ │ - atPoint: function(lonlat, toleranceLon, toleranceLat) { │ │ │ │ │ - var atPoint = false; │ │ │ │ │ - var bounds = this.getBounds(); │ │ │ │ │ - if ((bounds != null) && (lonlat != null)) { │ │ │ │ │ - │ │ │ │ │ - var dX = (toleranceLon != null) ? toleranceLon : 0; │ │ │ │ │ - var dY = (toleranceLat != null) ? toleranceLat : 0; │ │ │ │ │ - │ │ │ │ │ - var toleranceBounds = │ │ │ │ │ - new OpenLayers.Bounds(this.bounds.left - dX, │ │ │ │ │ - this.bounds.bottom - dY, │ │ │ │ │ - this.bounds.right + dX, │ │ │ │ │ - this.bounds.top + dY); │ │ │ │ │ - │ │ │ │ │ - atPoint = toleranceBounds.containsLonLat(lonlat); │ │ │ │ │ - } │ │ │ │ │ - return atPoint; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: getLength │ │ │ │ │ - * Calculate the length of this geometry. This method is defined in │ │ │ │ │ - * subclasses. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Float} The length of the collection by summing its parts │ │ │ │ │ - */ │ │ │ │ │ - getLength: function() { │ │ │ │ │ - //to be overridden by geometries that actually have a length │ │ │ │ │ - // │ │ │ │ │ - return 0.0; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: getArea │ │ │ │ │ - * Calculate the area of this geometry. This method is defined in subclasses. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Float} The area of the collection by summing its parts │ │ │ │ │ - */ │ │ │ │ │ - getArea: function() { │ │ │ │ │ - //to be overridden by geometries that actually have an area │ │ │ │ │ - // │ │ │ │ │ - return 0.0; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: getCentroid │ │ │ │ │ - * Calculate the centroid of this geometry. This method is defined in subclasses. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} The centroid of the collection │ │ │ │ │ - */ │ │ │ │ │ - getCentroid: function() { │ │ │ │ │ - return null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: toString │ │ │ │ │ - * Returns a text representation of the geometry. If the WKT format is │ │ │ │ │ - * included in a build, this will be the Well-Known Text │ │ │ │ │ - * representation. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} String representation of this geometry. │ │ │ │ │ - */ │ │ │ │ │ - toString: function() { │ │ │ │ │ - var string; │ │ │ │ │ - if (OpenLayers.Format && OpenLayers.Format.WKT) { │ │ │ │ │ - string = OpenLayers.Format.WKT.prototype.write( │ │ │ │ │ - new OpenLayers.Feature.Vector(this) │ │ │ │ │ - ); │ │ │ │ │ - } else { │ │ │ │ │ - string = Object.prototype.toString.call(this); │ │ │ │ │ - } │ │ │ │ │ - return string; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Geometry" │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Function: OpenLayers.Geometry.fromWKT │ │ │ │ │ - * Generate a geometry given a Well-Known Text string. For this method to │ │ │ │ │ - * work, you must include the OpenLayers.Format.WKT in your build │ │ │ │ │ - * explicitly. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * wkt - {String} A string representing the geometry in Well-Known Text. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} A geometry of the appropriate class. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Geometry.fromWKT = function(wkt) { │ │ │ │ │ - var geom; │ │ │ │ │ - if (OpenLayers.Format && OpenLayers.Format.WKT) { │ │ │ │ │ - var format = OpenLayers.Geometry.fromWKT.format; │ │ │ │ │ - if (!format) { │ │ │ │ │ - format = new OpenLayers.Format.WKT(); │ │ │ │ │ - OpenLayers.Geometry.fromWKT.format = format; │ │ │ │ │ - } │ │ │ │ │ - var result = format.read(wkt); │ │ │ │ │ - if (result instanceof OpenLayers.Feature.Vector) { │ │ │ │ │ - geom = result.geometry; │ │ │ │ │ - } else if (OpenLayers.Util.isArray(result)) { │ │ │ │ │ - var len = result.length; │ │ │ │ │ - var components = new Array(len); │ │ │ │ │ - for (var i = 0; i < len; ++i) { │ │ │ │ │ - components[i] = result[i].geometry; │ │ │ │ │ - } │ │ │ │ │ - geom = new OpenLayers.Geometry.Collection(components); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return geom; │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Method: OpenLayers.Geometry.segmentsIntersect │ │ │ │ │ - * Determine whether two line segments intersect. Optionally calculates │ │ │ │ │ - * and returns the intersection point. This function is optimized for │ │ │ │ │ - * cases where seg1.x2 >= seg2.x1 || seg2.x2 >= seg1.x1. In those │ │ │ │ │ - * obvious cases where there is no intersection, the function should │ │ │ │ │ - * not be called. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * seg1 - {Object} Object representing a segment with properties x1, y1, x2, │ │ │ │ │ - * and y2. The start point is represented by x1 and y1. The end point │ │ │ │ │ - * is represented by x2 and y2. Start and end are ordered so that x1 < x2. │ │ │ │ │ - * seg2 - {Object} Object representing a segment with properties x1, y1, x2, │ │ │ │ │ - * and y2. The start point is represented by x1 and y1. The end point │ │ │ │ │ - * is represented by x2 and y2. Start and end are ordered so that x1 < x2. │ │ │ │ │ - * options - {Object} Optional properties for calculating the intersection. │ │ │ │ │ - * │ │ │ │ │ - * Valid options: │ │ │ │ │ - * point - {Boolean} Return the intersection point. If false, the actual │ │ │ │ │ - * intersection point will not be calculated. If true and the segments │ │ │ │ │ - * intersect, the intersection point will be returned. If true and │ │ │ │ │ - * the segments do not intersect, false will be returned. If true and │ │ │ │ │ - * the segments are coincident, true will be returned. │ │ │ │ │ - * tolerance - {Number} If a non-null value is provided, if the segments are │ │ │ │ │ - * within the tolerance distance, this will be considered an intersection. │ │ │ │ │ - * In addition, if the point option is true and the calculated intersection │ │ │ │ │ - * is within the tolerance distance of an end point, the endpoint will be │ │ │ │ │ - * returned instead of the calculated intersection. Further, if the │ │ │ │ │ - * intersection is within the tolerance of endpoints on both segments, or │ │ │ │ │ - * if two segment endpoints are within the tolerance distance of eachother │ │ │ │ │ - * (but no intersection is otherwise calculated), an endpoint on the │ │ │ │ │ - * first segment provided will be returned. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean | } The two segments intersect. │ │ │ │ │ - * If the point argument is true, the return will be the intersection │ │ │ │ │ - * point or false if none exists. If point is true and the segments │ │ │ │ │ - * are coincident, return will be true (and the instersection is equal │ │ │ │ │ - * to the shorter segment). │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, options) { │ │ │ │ │ - var point = options && options.point; │ │ │ │ │ - var tolerance = options && options.tolerance; │ │ │ │ │ - var intersection = false; │ │ │ │ │ - var x11_21 = seg1.x1 - seg2.x1; │ │ │ │ │ - var y11_21 = seg1.y1 - seg2.y1; │ │ │ │ │ - var x12_11 = seg1.x2 - seg1.x1; │ │ │ │ │ - var y12_11 = seg1.y2 - seg1.y1; │ │ │ │ │ - var y22_21 = seg2.y2 - seg2.y1; │ │ │ │ │ - var x22_21 = seg2.x2 - seg2.x1; │ │ │ │ │ - var d = (y22_21 * x12_11) - (x22_21 * y12_11); │ │ │ │ │ - var n1 = (x22_21 * y11_21) - (y22_21 * x11_21); │ │ │ │ │ - var n2 = (x12_11 * y11_21) - (y12_11 * x11_21); │ │ │ │ │ - if (d == 0) { │ │ │ │ │ - // parallel │ │ │ │ │ - if (n1 == 0 && n2 == 0) { │ │ │ │ │ - // coincident │ │ │ │ │ - intersection = true; │ │ │ │ │ - } │ │ │ │ │ - } else { │ │ │ │ │ - var along1 = n1 / d; │ │ │ │ │ - var along2 = n2 / d; │ │ │ │ │ - if (along1 >= 0 && along1 <= 1 && along2 >= 0 && along2 <= 1) { │ │ │ │ │ - // intersect │ │ │ │ │ - if (!point) { │ │ │ │ │ - intersection = true; │ │ │ │ │ - } else { │ │ │ │ │ - // calculate the intersection point │ │ │ │ │ - var x = seg1.x1 + (along1 * x12_11); │ │ │ │ │ - var y = seg1.y1 + (along1 * y12_11); │ │ │ │ │ - intersection = new OpenLayers.Geometry.Point(x, y); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - if (tolerance) { │ │ │ │ │ - var dist; │ │ │ │ │ - if (intersection) { │ │ │ │ │ - if (point) { │ │ │ │ │ - var segs = [seg1, seg2]; │ │ │ │ │ - var seg, x, y; │ │ │ │ │ - // check segment endpoints for proximity to intersection │ │ │ │ │ - // set intersection to first endpoint within the tolerance │ │ │ │ │ - outer: for (var i = 0; i < 2; ++i) { │ │ │ │ │ - seg = segs[i]; │ │ │ │ │ - for (var j = 1; j < 3; ++j) { │ │ │ │ │ - x = seg["x" + j]; │ │ │ │ │ - y = seg["y" + j]; │ │ │ │ │ - dist = Math.sqrt( │ │ │ │ │ - Math.pow(x - intersection.x, 2) + │ │ │ │ │ - Math.pow(y - intersection.y, 2) │ │ │ │ │ - ); │ │ │ │ │ - if (dist < tolerance) { │ │ │ │ │ - intersection.x = x; │ │ │ │ │ - intersection.y = y; │ │ │ │ │ - break outer; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - } │ │ │ │ │ - } else { │ │ │ │ │ - // no calculated intersection, but segments could be within │ │ │ │ │ - // the tolerance of one another │ │ │ │ │ - var segs = [seg1, seg2]; │ │ │ │ │ - var source, target, x, y, p, result; │ │ │ │ │ - // check segment endpoints for proximity to intersection │ │ │ │ │ - // set intersection to first endpoint within the tolerance │ │ │ │ │ - outer: for (var i = 0; i < 2; ++i) { │ │ │ │ │ - source = segs[i]; │ │ │ │ │ - target = segs[(i + 1) % 2]; │ │ │ │ │ - for (var j = 1; j < 3; ++j) { │ │ │ │ │ - p = { │ │ │ │ │ - x: source["x" + j], │ │ │ │ │ - y: source["y" + j] │ │ │ │ │ - }; │ │ │ │ │ - result = OpenLayers.Geometry.distanceToSegment(p, target); │ │ │ │ │ - if (result.distance < tolerance) { │ │ │ │ │ - if (point) { │ │ │ │ │ - intersection = new OpenLayers.Geometry.Point(p.x, p.y); │ │ │ │ │ - } else { │ │ │ │ │ - intersection = true; │ │ │ │ │ - } │ │ │ │ │ - break outer; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return intersection; │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Function: OpenLayers.Geometry.distanceToSegment │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * point - {Object} An object with x and y properties representing the │ │ │ │ │ - * point coordinates. │ │ │ │ │ - * segment - {Object} An object with x1, y1, x2, and y2 properties │ │ │ │ │ - * representing endpoint coordinates. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} An object with distance, along, x, and y properties. The distance │ │ │ │ │ - * will be the shortest distance between the input point and segment. │ │ │ │ │ - * The x and y properties represent the coordinates along the segment │ │ │ │ │ - * where the shortest distance meets the segment. The along attribute │ │ │ │ │ - * describes how far between the two segment points the given point is. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Geometry.distanceToSegment = function(point, segment) { │ │ │ │ │ - var result = OpenLayers.Geometry.distanceSquaredToSegment(point, segment); │ │ │ │ │ - result.distance = Math.sqrt(result.distance); │ │ │ │ │ - return result; │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Function: OpenLayers.Geometry.distanceSquaredToSegment │ │ │ │ │ - * │ │ │ │ │ - * Usually the distanceToSegment function should be used. This variant however │ │ │ │ │ - * can be used for comparisons where the exact distance is not important. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * point - {Object} An object with x and y properties representing the │ │ │ │ │ - * point coordinates. │ │ │ │ │ - * segment - {Object} An object with x1, y1, x2, and y2 properties │ │ │ │ │ - * representing endpoint coordinates. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} An object with squared distance, along, x, and y properties. │ │ │ │ │ - * The distance will be the shortest distance between the input point and │ │ │ │ │ - * segment. The x and y properties represent the coordinates along the │ │ │ │ │ - * segment where the shortest distance meets the segment. The along │ │ │ │ │ - * attribute describes how far between the two segment points the given │ │ │ │ │ - * point is. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Geometry.distanceSquaredToSegment = function(point, segment) { │ │ │ │ │ - var x0 = point.x; │ │ │ │ │ - var y0 = point.y; │ │ │ │ │ - var x1 = segment.x1; │ │ │ │ │ - var y1 = segment.y1; │ │ │ │ │ - var x2 = segment.x2; │ │ │ │ │ - var y2 = segment.y2; │ │ │ │ │ - var dx = x2 - x1; │ │ │ │ │ - var dy = y2 - y1; │ │ │ │ │ - var along = ((dx * (x0 - x1)) + (dy * (y0 - y1))) / │ │ │ │ │ - (Math.pow(dx, 2) + Math.pow(dy, 2)); │ │ │ │ │ - var x, y; │ │ │ │ │ - if (along <= 0.0) { │ │ │ │ │ - x = x1; │ │ │ │ │ - y = y1; │ │ │ │ │ - } else if (along >= 1.0) { │ │ │ │ │ - x = x2; │ │ │ │ │ - y = y2; │ │ │ │ │ - } else { │ │ │ │ │ - x = x1 + along * dx; │ │ │ │ │ - y = y1 + along * dy; │ │ │ │ │ - } │ │ │ │ │ - return { │ │ │ │ │ - distance: Math.pow(x - x0, 2) + Math.pow(y - y0, 2), │ │ │ │ │ - x: x, │ │ │ │ │ - y: y, │ │ │ │ │ - along: along │ │ │ │ │ - }; │ │ │ │ │ -}; │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ OpenLayers/Feature.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ @@ -6332,1348 +5169,5592 @@ │ │ │ │ │ │ │ │ │ │ }, │ │ │ │ │ 'delete': { │ │ │ │ │ display: "none" │ │ │ │ │ } │ │ │ │ │ }; │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Format.js │ │ │ │ │ + OpenLayers/Style.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ + │ │ │ │ │ /** │ │ │ │ │ * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ * @requires OpenLayers/Util.js │ │ │ │ │ + * @requires OpenLayers/Feature/Vector.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Format │ │ │ │ │ - * Base class for format reading/writing a variety of formats. Subclasses │ │ │ │ │ - * of OpenLayers.Format are expected to have read and write methods. │ │ │ │ │ + * Class: OpenLayers.Style │ │ │ │ │ + * This class represents a UserStyle obtained │ │ │ │ │ + * from a SLD, containing styling rules. │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Format = OpenLayers.Class({ │ │ │ │ │ +OpenLayers.Style = OpenLayers.Class({ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: options │ │ │ │ │ - * {Object} A reference to options passed to the constructor. │ │ │ │ │ + * Property: id │ │ │ │ │ + * {String} A unique id for this session. │ │ │ │ │ */ │ │ │ │ │ - options: null, │ │ │ │ │ + id: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: externalProjection │ │ │ │ │ - * {} When passed a externalProjection and │ │ │ │ │ - * internalProjection, the format will reproject the geometries it │ │ │ │ │ - * reads or writes. The externalProjection is the projection used by │ │ │ │ │ - * the content which is passed into read or which comes out of write. │ │ │ │ │ - * In order to reproject, a projection transformation function for the │ │ │ │ │ - * specified projections must be available. This support may be │ │ │ │ │ - * provided via proj4js or via a custom transformation function. See │ │ │ │ │ - * {} for more information on │ │ │ │ │ - * custom transformations. │ │ │ │ │ + * APIProperty: name │ │ │ │ │ + * {String} │ │ │ │ │ */ │ │ │ │ │ - externalProjection: null, │ │ │ │ │ + name: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: internalProjection │ │ │ │ │ - * {} When passed a externalProjection and │ │ │ │ │ - * internalProjection, the format will reproject the geometries it │ │ │ │ │ - * reads or writes. The internalProjection is the projection used by │ │ │ │ │ - * the geometries which are returned by read or which are passed into │ │ │ │ │ - * write. In order to reproject, a projection transformation function │ │ │ │ │ - * for the specified projections must be available. This support may be │ │ │ │ │ - * provided via proj4js or via a custom transformation function. See │ │ │ │ │ - * {} for more information on │ │ │ │ │ - * custom transformations. │ │ │ │ │ + * Property: title │ │ │ │ │ + * {String} Title of this style (set if included in SLD) │ │ │ │ │ */ │ │ │ │ │ - internalProjection: null, │ │ │ │ │ + title: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: data │ │ │ │ │ - * {Object} When is true, this is the parsed string sent to │ │ │ │ │ - * . │ │ │ │ │ + * Property: description │ │ │ │ │ + * {String} Description of this style (set if abstract is included in SLD) │ │ │ │ │ */ │ │ │ │ │ - data: null, │ │ │ │ │ + description: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: keepData │ │ │ │ │ - * {Object} Maintain a reference () to the most recently read data. │ │ │ │ │ - * Default is false. │ │ │ │ │ + * APIProperty: layerName │ │ │ │ │ + * {} name of the layer that this style belongs to, usually │ │ │ │ │ + * according to the NamedLayer attribute of an SLD document. │ │ │ │ │ */ │ │ │ │ │ - keepData: false, │ │ │ │ │ + layerName: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Format │ │ │ │ │ - * Instances of this class are not useful. See one of the subclasses. │ │ │ │ │ + * APIProperty: isDefault │ │ │ │ │ + * {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + isDefault: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: rules │ │ │ │ │ + * {Array()} │ │ │ │ │ + */ │ │ │ │ │ + rules: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: context │ │ │ │ │ + * {Object} An optional object with properties that symbolizers' property │ │ │ │ │ + * values should be evaluated against. If no context is specified, │ │ │ │ │ + * feature.attributes will be used │ │ │ │ │ + */ │ │ │ │ │ + context: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: defaultStyle │ │ │ │ │ + * {Object} hash of style properties to use as default for merging │ │ │ │ │ + * rule-based style symbolizers onto. If no rules are defined, │ │ │ │ │ + * createSymbolizer will return this style. If is set to │ │ │ │ │ + * true, the defaultStyle will only be taken into account if there are │ │ │ │ │ + * rules defined. │ │ │ │ │ + */ │ │ │ │ │ + defaultStyle: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: defaultsPerSymbolizer │ │ │ │ │ + * {Boolean} If set to true, the will extend the symbolizer │ │ │ │ │ + * of every rule. Properties of the will also be used to set │ │ │ │ │ + * missing symbolizer properties if the symbolizer has stroke, fill or │ │ │ │ │ + * graphic set to true. Default is false. │ │ │ │ │ + */ │ │ │ │ │ + defaultsPerSymbolizer: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: propertyStyles │ │ │ │ │ + * {Hash of Boolean} cache of style properties that need to be parsed for │ │ │ │ │ + * propertyNames. Property names are keys, values won't be used. │ │ │ │ │ + */ │ │ │ │ │ + propertyStyles: null, │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Style │ │ │ │ │ + * Creates a UserStyle. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ + * style - {Object} Optional hash of style properties that will be │ │ │ │ │ + * used as default style for this style object. This style │ │ │ │ │ + * applies if no rules are specified. Symbolizers defined in │ │ │ │ │ + * rules will extend this default style. │ │ │ │ │ * options - {Object} An optional object with properties to set on the │ │ │ │ │ - * format │ │ │ │ │ + * style. │ │ │ │ │ * │ │ │ │ │ * Valid options: │ │ │ │ │ - * keepData - {Boolean} If true, upon , the data property will be │ │ │ │ │ - * set to the parsed object (e.g. the json or xml object). │ │ │ │ │ - * │ │ │ │ │ + * rules - {Array()} List of rules to be added to the │ │ │ │ │ + * style. │ │ │ │ │ + * │ │ │ │ │ * Returns: │ │ │ │ │ - * An instance of OpenLayers.Format │ │ │ │ │ + * {} │ │ │ │ │ */ │ │ │ │ │ - initialize: function(options) { │ │ │ │ │ + initialize: function(style, options) { │ │ │ │ │ + │ │ │ │ │ OpenLayers.Util.extend(this, options); │ │ │ │ │ - this.options = options; │ │ │ │ │ + this.rules = []; │ │ │ │ │ + if (options && options.rules) { │ │ │ │ │ + this.addRules(options.rules); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // use the default style from OpenLayers.Feature.Vector if no style │ │ │ │ │ + // was given in the constructor │ │ │ │ │ + this.setDefaultStyle(style || │ │ │ │ │ + OpenLayers.Feature.Vector.style["default"]); │ │ │ │ │ + │ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ + /** │ │ │ │ │ * APIMethod: destroy │ │ │ │ │ - * Clean up. │ │ │ │ │ + * nullify references to prevent circular references and memory leaks │ │ │ │ │ */ │ │ │ │ │ - destroy: function() {}, │ │ │ │ │ + destroy: function() { │ │ │ │ │ + for (var i = 0, len = this.rules.length; i < len; i++) { │ │ │ │ │ + this.rules[i].destroy(); │ │ │ │ │ + this.rules[i] = null; │ │ │ │ │ + } │ │ │ │ │ + this.rules = null; │ │ │ │ │ + this.defaultStyle = null; │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: read │ │ │ │ │ - * Read data from a string, and return an object whose type depends on the │ │ │ │ │ - * subclass. │ │ │ │ │ + * Method: createSymbolizer │ │ │ │ │ + * creates a style by applying all feature-dependent rules to the base │ │ │ │ │ + * style. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * data - {string} Data to read/parse. │ │ │ │ │ - * │ │ │ │ │ + * feature - {} feature to evaluate rules for │ │ │ │ │ + * │ │ │ │ │ * Returns: │ │ │ │ │ - * Depends on the subclass │ │ │ │ │ + * {Object} symbolizer hash │ │ │ │ │ */ │ │ │ │ │ - read: function(data) { │ │ │ │ │ - throw new Error('Read not implemented.'); │ │ │ │ │ + createSymbolizer: function(feature) { │ │ │ │ │ + var style = this.defaultsPerSymbolizer ? {} : this.createLiterals( │ │ │ │ │ + OpenLayers.Util.extend({}, this.defaultStyle), feature); │ │ │ │ │ + │ │ │ │ │ + var rules = this.rules; │ │ │ │ │ + │ │ │ │ │ + var rule, context; │ │ │ │ │ + var elseRules = []; │ │ │ │ │ + var appliedRules = false; │ │ │ │ │ + for (var i = 0, len = rules.length; i < len; i++) { │ │ │ │ │ + rule = rules[i]; │ │ │ │ │ + // does the rule apply? │ │ │ │ │ + var applies = rule.evaluate(feature); │ │ │ │ │ + │ │ │ │ │ + if (applies) { │ │ │ │ │ + if (rule instanceof OpenLayers.Rule && rule.elseFilter) { │ │ │ │ │ + elseRules.push(rule); │ │ │ │ │ + } else { │ │ │ │ │ + appliedRules = true; │ │ │ │ │ + this.applySymbolizer(rule, style, feature); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // if no other rules apply, apply the rules with else filters │ │ │ │ │ + if (appliedRules == false && elseRules.length > 0) { │ │ │ │ │ + appliedRules = true; │ │ │ │ │ + for (var i = 0, len = elseRules.length; i < len; i++) { │ │ │ │ │ + this.applySymbolizer(elseRules[i], style, feature); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // don't display if there were rules but none applied │ │ │ │ │ + if (rules.length > 0 && appliedRules == false) { │ │ │ │ │ + style.display = "none"; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + if (style.label != null && typeof style.label !== "string") { │ │ │ │ │ + style.label = String(style.label); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + return style; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: write │ │ │ │ │ - * Accept an object, and return a string. │ │ │ │ │ + * Method: applySymbolizer │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * object - {Object} Object to be serialized │ │ │ │ │ + * rule - {} │ │ │ │ │ + * style - {Object} │ │ │ │ │ + * feature - {} │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {String} A string representation of the object. │ │ │ │ │ + * {Object} A style with new symbolizer applied. │ │ │ │ │ */ │ │ │ │ │ - write: function(object) { │ │ │ │ │ - throw new Error('Write not implemented.'); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Format" │ │ │ │ │ -}); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Geometry/Point.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ + applySymbolizer: function(rule, style, feature) { │ │ │ │ │ + var symbolizerPrefix = feature.geometry ? │ │ │ │ │ + this.getSymbolizerPrefix(feature.geometry) : │ │ │ │ │ + OpenLayers.Style.SYMBOLIZER_PREFIXES[0]; │ │ │ │ │ │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ + var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer; │ │ │ │ │ │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Geometry.js │ │ │ │ │ - */ │ │ │ │ │ + if (this.defaultsPerSymbolizer === true) { │ │ │ │ │ + var defaults = this.defaultStyle; │ │ │ │ │ + OpenLayers.Util.applyDefaults(symbolizer, { │ │ │ │ │ + pointRadius: defaults.pointRadius │ │ │ │ │ + }); │ │ │ │ │ + if (symbolizer.stroke === true || symbolizer.graphic === true) { │ │ │ │ │ + OpenLayers.Util.applyDefaults(symbolizer, { │ │ │ │ │ + strokeWidth: defaults.strokeWidth, │ │ │ │ │ + strokeColor: defaults.strokeColor, │ │ │ │ │ + strokeOpacity: defaults.strokeOpacity, │ │ │ │ │ + strokeDashstyle: defaults.strokeDashstyle, │ │ │ │ │ + strokeLinecap: defaults.strokeLinecap │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + if (symbolizer.fill === true || symbolizer.graphic === true) { │ │ │ │ │ + OpenLayers.Util.applyDefaults(symbolizer, { │ │ │ │ │ + fillColor: defaults.fillColor, │ │ │ │ │ + fillOpacity: defaults.fillOpacity │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + if (symbolizer.graphic === true) { │ │ │ │ │ + OpenLayers.Util.applyDefaults(symbolizer, { │ │ │ │ │ + pointRadius: this.defaultStyle.pointRadius, │ │ │ │ │ + externalGraphic: this.defaultStyle.externalGraphic, │ │ │ │ │ + graphicName: this.defaultStyle.graphicName, │ │ │ │ │ + graphicOpacity: this.defaultStyle.graphicOpacity, │ │ │ │ │ + graphicWidth: this.defaultStyle.graphicWidth, │ │ │ │ │ + graphicHeight: this.defaultStyle.graphicHeight, │ │ │ │ │ + graphicXOffset: this.defaultStyle.graphicXOffset, │ │ │ │ │ + graphicYOffset: this.defaultStyle.graphicYOffset │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Geometry.Point │ │ │ │ │ - * Point geometry class. │ │ │ │ │ - * │ │ │ │ │ - * Inherits from: │ │ │ │ │ - * - │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Geometry.Point = OpenLayers.Class(OpenLayers.Geometry, { │ │ │ │ │ + // merge the style with the current style │ │ │ │ │ + return this.createLiterals( │ │ │ │ │ + OpenLayers.Util.extend(style, symbolizer), feature); │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: x │ │ │ │ │ - * {float} │ │ │ │ │ + /** │ │ │ │ │ + * Method: createLiterals │ │ │ │ │ + * creates literals for all style properties that have an entry in │ │ │ │ │ + * . │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * style - {Object} style to create literals for. Will be modified │ │ │ │ │ + * inline. │ │ │ │ │ + * feature - {Object} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Object} the modified style │ │ │ │ │ */ │ │ │ │ │ - x: null, │ │ │ │ │ + createLiterals: function(style, feature) { │ │ │ │ │ + var context = OpenLayers.Util.extend({}, feature.attributes || feature.data); │ │ │ │ │ + OpenLayers.Util.extend(context, this.context); │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: y │ │ │ │ │ - * {float} │ │ │ │ │ - */ │ │ │ │ │ - y: null, │ │ │ │ │ + for (var i in this.propertyStyles) { │ │ │ │ │ + style[i] = OpenLayers.Style.createLiteral(style[i], context, feature, i); │ │ │ │ │ + } │ │ │ │ │ + return style; │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Geometry.Point │ │ │ │ │ - * Construct a point geometry. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * x - {float} │ │ │ │ │ - * y - {float} │ │ │ │ │ + * Method: findPropertyStyles │ │ │ │ │ + * Looks into all rules for this style and the defaultStyle to collect │ │ │ │ │ + * all the style hash property names containing ${...} strings that have │ │ │ │ │ + * to be replaced using the createLiteral method before returning them. │ │ │ │ │ * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Object} hash of property names that need createLiteral parsing. The │ │ │ │ │ + * name of the property is the key, and the value is true; │ │ │ │ │ */ │ │ │ │ │ - initialize: function(x, y) { │ │ │ │ │ - OpenLayers.Geometry.prototype.initialize.apply(this, arguments); │ │ │ │ │ + findPropertyStyles: function() { │ │ │ │ │ + var propertyStyles = {}; │ │ │ │ │ │ │ │ │ │ - this.x = parseFloat(x); │ │ │ │ │ - this.y = parseFloat(y); │ │ │ │ │ + // check the default style │ │ │ │ │ + var style = this.defaultStyle; │ │ │ │ │ + this.addPropertyStyles(propertyStyles, style); │ │ │ │ │ + │ │ │ │ │ + // walk through all rules to check for properties in their symbolizer │ │ │ │ │ + var rules = this.rules; │ │ │ │ │ + var symbolizer, value; │ │ │ │ │ + for (var i = 0, len = rules.length; i < len; i++) { │ │ │ │ │ + symbolizer = rules[i].symbolizer; │ │ │ │ │ + for (var key in symbolizer) { │ │ │ │ │ + value = symbolizer[key]; │ │ │ │ │ + if (typeof value == "object") { │ │ │ │ │ + // symbolizer key is "Point", "Line" or "Polygon" │ │ │ │ │ + this.addPropertyStyles(propertyStyles, value); │ │ │ │ │ + } else { │ │ │ │ │ + // symbolizer is a hash of style properties │ │ │ │ │ + this.addPropertyStyles(propertyStyles, symbolizer); │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return propertyStyles; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: clone │ │ │ │ │ + * Method: addPropertyStyles │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * propertyStyles - {Object} hash to add new property styles to. Will be │ │ │ │ │ + * modified inline │ │ │ │ │ + * symbolizer - {Object} search this symbolizer for property styles │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {} An exact clone of this OpenLayers.Geometry.Point │ │ │ │ │ + * {Object} propertyStyles hash │ │ │ │ │ */ │ │ │ │ │ - clone: function(obj) { │ │ │ │ │ - if (obj == null) { │ │ │ │ │ - obj = new OpenLayers.Geometry.Point(this.x, this.y); │ │ │ │ │ + addPropertyStyles: function(propertyStyles, symbolizer) { │ │ │ │ │ + var property; │ │ │ │ │ + for (var key in symbolizer) { │ │ │ │ │ + property = symbolizer[key]; │ │ │ │ │ + if (typeof property == "string" && │ │ │ │ │ + property.match(/\$\{\w+\}/)) { │ │ │ │ │ + propertyStyles[key] = true; │ │ │ │ │ + } │ │ │ │ │ } │ │ │ │ │ + return propertyStyles; │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - // catch any randomly tagged-on properties │ │ │ │ │ - OpenLayers.Util.applyDefaults(obj, this); │ │ │ │ │ - │ │ │ │ │ - return obj; │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: addRules │ │ │ │ │ + * Adds rules to this style. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * rules - {Array()} │ │ │ │ │ + */ │ │ │ │ │ + addRules: function(rules) { │ │ │ │ │ + Array.prototype.push.apply(this.rules, rules); │ │ │ │ │ + this.propertyStyles = this.findPropertyStyles(); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: calculateBounds │ │ │ │ │ - * Create a new Bounds based on the lon/lat │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: setDefaultStyle │ │ │ │ │ + * Sets the default style for this style object. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * style - {Object} Hash of style properties │ │ │ │ │ */ │ │ │ │ │ - calculateBounds: function() { │ │ │ │ │ - this.bounds = new OpenLayers.Bounds(this.x, this.y, │ │ │ │ │ - this.x, this.y); │ │ │ │ │ + setDefaultStyle: function(style) { │ │ │ │ │ + this.defaultStyle = style; │ │ │ │ │ + this.propertyStyles = this.findPropertyStyles(); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: distanceTo │ │ │ │ │ - * Calculate the closest distance between two geometries (on the x-y plane). │ │ │ │ │ - * │ │ │ │ │ + * Method: getSymbolizerPrefix │ │ │ │ │ + * Returns the correct symbolizer prefix according to the │ │ │ │ │ + * geometry type of the passed geometry │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * geometry - {} The target geometry. │ │ │ │ │ - * options - {Object} Optional properties for configuring the distance │ │ │ │ │ - * calculation. │ │ │ │ │ - * │ │ │ │ │ - * Valid options: │ │ │ │ │ - * details - {Boolean} Return details from the distance calculation. │ │ │ │ │ - * Default is false. │ │ │ │ │ - * edge - {Boolean} Calculate the distance from this geometry to the │ │ │ │ │ - * nearest edge of the target geometry. Default is true. If true, │ │ │ │ │ - * calling distanceTo from a geometry that is wholly contained within │ │ │ │ │ - * the target will result in a non-zero distance. If false, whenever │ │ │ │ │ - * geometries intersect, calling distanceTo will return 0. If false, │ │ │ │ │ - * details cannot be returned. │ │ │ │ │ - * │ │ │ │ │ + * geometry - {} │ │ │ │ │ + * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Number | Object} The distance between this geometry and the target. │ │ │ │ │ - * If details is true, the return will be an object with distance, │ │ │ │ │ - * x0, y0, x1, and x2 properties. The x0 and y0 properties represent │ │ │ │ │ - * the coordinates of the closest point on this geometry. The x1 and y1 │ │ │ │ │ - * properties represent the coordinates of the closest point on the │ │ │ │ │ - * target geometry. │ │ │ │ │ + * {String} key of the according symbolizer │ │ │ │ │ */ │ │ │ │ │ - distanceTo: function(geometry, options) { │ │ │ │ │ - var edge = !(options && options.edge === false); │ │ │ │ │ - var details = edge && options && options.details; │ │ │ │ │ - var distance, x0, y0, x1, y1, result; │ │ │ │ │ - if (geometry instanceof OpenLayers.Geometry.Point) { │ │ │ │ │ - x0 = this.x; │ │ │ │ │ - y0 = this.y; │ │ │ │ │ - x1 = geometry.x; │ │ │ │ │ - y1 = geometry.y; │ │ │ │ │ - distance = Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2)); │ │ │ │ │ - result = !details ? │ │ │ │ │ - distance : { │ │ │ │ │ - x0: x0, │ │ │ │ │ - y0: y0, │ │ │ │ │ - x1: x1, │ │ │ │ │ - y1: y1, │ │ │ │ │ - distance: distance │ │ │ │ │ - }; │ │ │ │ │ - } else { │ │ │ │ │ - result = geometry.distanceTo(this, options); │ │ │ │ │ - if (details) { │ │ │ │ │ - // switch coord order since this geom is target │ │ │ │ │ - result = { │ │ │ │ │ - x0: result.x1, │ │ │ │ │ - y0: result.y1, │ │ │ │ │ - x1: result.x0, │ │ │ │ │ - y1: result.y0, │ │ │ │ │ - distance: result.distance │ │ │ │ │ - }; │ │ │ │ │ + getSymbolizerPrefix: function(geometry) { │ │ │ │ │ + var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES; │ │ │ │ │ + for (var i = 0, len = prefixes.length; i < len; i++) { │ │ │ │ │ + if (geometry.CLASS_NAME.indexOf(prefixes[i]) != -1) { │ │ │ │ │ + return prefixes[i]; │ │ │ │ │ } │ │ │ │ │ } │ │ │ │ │ - return result; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: equals │ │ │ │ │ - * Determine whether another geometry is equivalent to this one. Geometries │ │ │ │ │ - * are considered equivalent if all components have the same coordinates. │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: clone │ │ │ │ │ + * Clones this style. │ │ │ │ │ * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * geom - {} The geometry to test. │ │ │ │ │ - * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Boolean} The supplied geometry is equivalent to this geometry. │ │ │ │ │ + * {} Clone of this style. │ │ │ │ │ */ │ │ │ │ │ - equals: function(geom) { │ │ │ │ │ - var equals = false; │ │ │ │ │ - if (geom != null) { │ │ │ │ │ - equals = ((this.x == geom.x && this.y == geom.y) || │ │ │ │ │ - (isNaN(this.x) && isNaN(this.y) && isNaN(geom.x) && isNaN(geom.y))); │ │ │ │ │ + clone: function() { │ │ │ │ │ + var options = OpenLayers.Util.extend({}, this); │ │ │ │ │ + // clone rules │ │ │ │ │ + if (this.rules) { │ │ │ │ │ + options.rules = []; │ │ │ │ │ + for (var i = 0, len = this.rules.length; i < len; ++i) { │ │ │ │ │ + options.rules.push(this.rules[i].clone()); │ │ │ │ │ + } │ │ │ │ │ } │ │ │ │ │ - return equals; │ │ │ │ │ + // clone context │ │ │ │ │ + options.context = this.context && OpenLayers.Util.extend({}, this.context); │ │ │ │ │ + //clone default style │ │ │ │ │ + var defaultStyle = OpenLayers.Util.extend({}, this.defaultStyle); │ │ │ │ │ + return new OpenLayers.Style(defaultStyle, options); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ + CLASS_NAME: "OpenLayers.Style" │ │ │ │ │ +}); │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Function: createLiteral │ │ │ │ │ + * converts a style value holding a combination of PropertyName and Literal │ │ │ │ │ + * into a Literal, taking the property values from the passed features. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * value - {String} value to parse. If this string contains a construct like │ │ │ │ │ + * "foo ${bar}", then "foo " will be taken as literal, and "${bar}" │ │ │ │ │ + * will be replaced by the value of the "bar" attribute of the passed │ │ │ │ │ + * feature. │ │ │ │ │ + * context - {Object} context to take attribute values from │ │ │ │ │ + * feature - {} optional feature to pass to │ │ │ │ │ + * for evaluating functions in the │ │ │ │ │ + * context. │ │ │ │ │ + * property - {String} optional, name of the property for which the literal is │ │ │ │ │ + * being created for evaluating functions in the context. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {String} the parsed value. In the example of the value parameter above, the │ │ │ │ │ + * result would be "foo valueOfBar", assuming that the passed feature has an │ │ │ │ │ + * attribute named "bar" with the value "valueOfBar". │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Style.createLiteral = function(value, context, feature, property) { │ │ │ │ │ + if (typeof value == "string" && value.indexOf("${") != -1) { │ │ │ │ │ + value = OpenLayers.String.format(value, context, [feature, property]); │ │ │ │ │ + value = (isNaN(value) || !value) ? value : parseFloat(value); │ │ │ │ │ + } │ │ │ │ │ + return value; │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Constant: OpenLayers.Style.SYMBOLIZER_PREFIXES │ │ │ │ │ + * {Array} prefixes of the sld symbolizers. These are the │ │ │ │ │ + * same as the main geometry types │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text', │ │ │ │ │ + 'Raster' │ │ │ │ │ +]; │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Rule.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + * @requires OpenLayers/Util.js │ │ │ │ │ + * @requires OpenLayers/Style.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Rule │ │ │ │ │ + * This class represents an SLD Rule, as being used for rule-based SLD styling. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Rule = OpenLayers.Class({ │ │ │ │ │ + │ │ │ │ │ /** │ │ │ │ │ - * Method: toShortString │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} Shortened String representation of Point object. │ │ │ │ │ - * (ex. "5, 42") │ │ │ │ │ + * Property: id │ │ │ │ │ + * {String} A unique id for this session. │ │ │ │ │ */ │ │ │ │ │ - toShortString: function() { │ │ │ │ │ - return (this.x + ", " + this.y); │ │ │ │ │ - }, │ │ │ │ │ + id: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: move │ │ │ │ │ - * Moves a geometry by the given displacement along positive x and y axes. │ │ │ │ │ - * This modifies the position of the geometry and clears the cached │ │ │ │ │ - * bounds. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * x - {Float} Distance to move geometry in positive x direction. │ │ │ │ │ - * y - {Float} Distance to move geometry in positive y direction. │ │ │ │ │ + * APIProperty: name │ │ │ │ │ + * {String} name of this rule │ │ │ │ │ */ │ │ │ │ │ - move: function(x, y) { │ │ │ │ │ - this.x = this.x + x; │ │ │ │ │ - this.y = this.y + y; │ │ │ │ │ - this.clearBounds(); │ │ │ │ │ - }, │ │ │ │ │ + name: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: rotate │ │ │ │ │ - * Rotate a point around another. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * angle - {Float} Rotation angle in degrees (measured counterclockwise │ │ │ │ │ - * from the positive x-axis) │ │ │ │ │ - * origin - {} Center point for the rotation │ │ │ │ │ + * Property: title │ │ │ │ │ + * {String} Title of this rule (set if included in SLD) │ │ │ │ │ */ │ │ │ │ │ - rotate: function(angle, origin) { │ │ │ │ │ - angle *= Math.PI / 180; │ │ │ │ │ - var radius = this.distanceTo(origin); │ │ │ │ │ - var theta = angle + Math.atan2(this.y - origin.y, this.x - origin.x); │ │ │ │ │ - this.x = origin.x + (radius * Math.cos(theta)); │ │ │ │ │ - this.y = origin.y + (radius * Math.sin(theta)); │ │ │ │ │ - this.clearBounds(); │ │ │ │ │ - }, │ │ │ │ │ + title: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getCentroid │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} The centroid of the collection │ │ │ │ │ + * Property: description │ │ │ │ │ + * {String} Description of this rule (set if abstract is included in SLD) │ │ │ │ │ */ │ │ │ │ │ - getCentroid: function() { │ │ │ │ │ - return new OpenLayers.Geometry.Point(this.x, this.y); │ │ │ │ │ - }, │ │ │ │ │ + description: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: resize │ │ │ │ │ - * Resize a point relative to some origin. For points, this has the effect │ │ │ │ │ - * of scaling a vector (from the origin to the point). This method is │ │ │ │ │ - * more useful on geometry collection subclasses. │ │ │ │ │ + * Property: context │ │ │ │ │ + * {Object} An optional object with properties that the rule should be │ │ │ │ │ + * evaluated against. If no context is specified, feature.attributes will │ │ │ │ │ + * be used. │ │ │ │ │ + */ │ │ │ │ │ + context: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: filter │ │ │ │ │ + * {} Optional filter for the rule. │ │ │ │ │ + */ │ │ │ │ │ + filter: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: elseFilter │ │ │ │ │ + * {Boolean} Determines whether this rule is only to be applied only if │ │ │ │ │ + * no other rules match (ElseFilter according to the SLD specification). │ │ │ │ │ + * Default is false. For instances of OpenLayers.Rule, if elseFilter is │ │ │ │ │ + * false, the rule will always apply. For subclasses, the else property is │ │ │ │ │ + * ignored. │ │ │ │ │ + */ │ │ │ │ │ + elseFilter: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: symbolizer │ │ │ │ │ + * {Object} Symbolizer or hash of symbolizers for this rule. If hash of │ │ │ │ │ + * symbolizers, keys are one or more of ["Point", "Line", "Polygon"]. The │ │ │ │ │ + * latter if useful if it is required to style e.g. vertices of a line │ │ │ │ │ + * with a point symbolizer. Note, however, that this is not implemented │ │ │ │ │ + * yet in OpenLayers, but it is the way how symbolizers are defined in │ │ │ │ │ + * SLD. │ │ │ │ │ + */ │ │ │ │ │ + symbolizer: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: symbolizers │ │ │ │ │ + * {Array} Collection of symbolizers associated with this rule. If │ │ │ │ │ + * provided at construction, the symbolizers array has precedence │ │ │ │ │ + * over the deprecated symbolizer property. Note that multiple │ │ │ │ │ + * symbolizers are not currently supported by the vector renderers. │ │ │ │ │ + * Rules with multiple symbolizers are currently only useful for │ │ │ │ │ + * maintaining elements in an SLD document. │ │ │ │ │ + */ │ │ │ │ │ + symbolizers: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: minScaleDenominator │ │ │ │ │ + * {Number} or {String} minimum scale at which to draw the feature. │ │ │ │ │ + * In the case of a String, this can be a combination of text and │ │ │ │ │ + * propertyNames in the form "literal ${propertyName}" │ │ │ │ │ + */ │ │ │ │ │ + minScaleDenominator: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: maxScaleDenominator │ │ │ │ │ + * {Number} or {String} maximum scale at which to draw the feature. │ │ │ │ │ + * In the case of a String, this can be a combination of text and │ │ │ │ │ + * propertyNames in the form "literal ${propertyName}" │ │ │ │ │ + */ │ │ │ │ │ + maxScaleDenominator: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Rule │ │ │ │ │ + * Creates a Rule. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * scale - {Float} Ratio of the new distance from the origin to the old │ │ │ │ │ - * distance from the origin. A scale of 2 doubles the │ │ │ │ │ - * distance between the point and origin. │ │ │ │ │ - * origin - {} Point of origin for resizing │ │ │ │ │ - * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1. │ │ │ │ │ + * options - {Object} An optional object with properties to set on the │ │ │ │ │ + * rule │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {} - The current geometry. │ │ │ │ │ + * {} │ │ │ │ │ */ │ │ │ │ │ - resize: function(scale, origin, ratio) { │ │ │ │ │ - ratio = (ratio == undefined) ? 1 : ratio; │ │ │ │ │ - this.x = origin.x + (scale * ratio * (this.x - origin.x)); │ │ │ │ │ - this.y = origin.y + (scale * (this.y - origin.y)); │ │ │ │ │ - this.clearBounds(); │ │ │ │ │ - return this; │ │ │ │ │ + initialize: function(options) { │ │ │ │ │ + this.symbolizer = {}; │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ + if (this.symbolizers) { │ │ │ │ │ + delete this.symbolizer; │ │ │ │ │ + } │ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: destroy │ │ │ │ │ + * nullify references to prevent circular references and memory leaks │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + for (var i in this.symbolizer) { │ │ │ │ │ + this.symbolizer[i] = null; │ │ │ │ │ + } │ │ │ │ │ + this.symbolizer = null; │ │ │ │ │ + delete this.symbolizers; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: intersects │ │ │ │ │ - * Determine if the input geometry intersects this one. │ │ │ │ │ - * │ │ │ │ │ + * APIMethod: evaluate │ │ │ │ │ + * evaluates this rule for a specific feature │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * geometry - {} Any type of geometry. │ │ │ │ │ - * │ │ │ │ │ + * feature - {} feature to apply the rule to. │ │ │ │ │ + * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Boolean} The input geometry intersects this one. │ │ │ │ │ + * {Boolean} true if the rule applies, false if it does not. │ │ │ │ │ + * This rule is the default rule and always returns true. │ │ │ │ │ */ │ │ │ │ │ - intersects: function(geometry) { │ │ │ │ │ - var intersect = false; │ │ │ │ │ - if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { │ │ │ │ │ - intersect = this.equals(geometry); │ │ │ │ │ - } else { │ │ │ │ │ - intersect = geometry.intersects(this); │ │ │ │ │ + evaluate: function(feature) { │ │ │ │ │ + var context = this.getContext(feature); │ │ │ │ │ + var applies = true; │ │ │ │ │ + │ │ │ │ │ + if (this.minScaleDenominator || this.maxScaleDenominator) { │ │ │ │ │ + var scale = feature.layer.map.getScale(); │ │ │ │ │ } │ │ │ │ │ - return intersect; │ │ │ │ │ + │ │ │ │ │ + // check if within minScale/maxScale bounds │ │ │ │ │ + if (this.minScaleDenominator) { │ │ │ │ │ + applies = scale >= OpenLayers.Style.createLiteral( │ │ │ │ │ + this.minScaleDenominator, context); │ │ │ │ │ + } │ │ │ │ │ + if (applies && this.maxScaleDenominator) { │ │ │ │ │ + applies = scale < OpenLayers.Style.createLiteral( │ │ │ │ │ + this.maxScaleDenominator, context); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // check if optional filter applies │ │ │ │ │ + if (applies && this.filter) { │ │ │ │ │ + // feature id filters get the feature, others get the context │ │ │ │ │ + if (this.filter.CLASS_NAME == "OpenLayers.Filter.FeatureId") { │ │ │ │ │ + applies = this.filter.evaluate(feature); │ │ │ │ │ + } else { │ │ │ │ │ + applies = this.filter.evaluate(context); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + return applies; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: transform │ │ │ │ │ - * Translate the x,y properties of the point from source to dest. │ │ │ │ │ + * Method: getContext │ │ │ │ │ + * Gets the context for evaluating this rule │ │ │ │ │ * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * source - {} │ │ │ │ │ - * dest - {} │ │ │ │ │ + * Paramters: │ │ │ │ │ + * feature - {} feature to take the context from if │ │ │ │ │ + * none is specified. │ │ │ │ │ + */ │ │ │ │ │ + getContext: function(feature) { │ │ │ │ │ + var context = this.context; │ │ │ │ │ + if (!context) { │ │ │ │ │ + context = feature.attributes || feature.data; │ │ │ │ │ + } │ │ │ │ │ + if (typeof this.context == "function") { │ │ │ │ │ + context = this.context(feature); │ │ │ │ │ + } │ │ │ │ │ + return context; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: clone │ │ │ │ │ + * Clones this rule. │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {} │ │ │ │ │ + * {} Clone of this rule. │ │ │ │ │ */ │ │ │ │ │ - transform: function(source, dest) { │ │ │ │ │ - if ((source && dest)) { │ │ │ │ │ - OpenLayers.Projection.transform( │ │ │ │ │ - this, source, dest); │ │ │ │ │ - this.bounds = null; │ │ │ │ │ + clone: function() { │ │ │ │ │ + var options = OpenLayers.Util.extend({}, this); │ │ │ │ │ + if (this.symbolizers) { │ │ │ │ │ + // clone symbolizers │ │ │ │ │ + var len = this.symbolizers.length; │ │ │ │ │ + options.symbolizers = new Array(len); │ │ │ │ │ + for (var i = 0; i < len; ++i) { │ │ │ │ │ + options.symbolizers[i] = this.symbolizers[i].clone(); │ │ │ │ │ + } │ │ │ │ │ + } else { │ │ │ │ │ + // clone symbolizer │ │ │ │ │ + options.symbolizer = {}; │ │ │ │ │ + var value, type; │ │ │ │ │ + for (var key in this.symbolizer) { │ │ │ │ │ + value = this.symbolizer[key]; │ │ │ │ │ + type = typeof value; │ │ │ │ │ + if (type === "object") { │ │ │ │ │ + options.symbolizer[key] = OpenLayers.Util.extend({}, value); │ │ │ │ │ + } else if (type === "string") { │ │ │ │ │ + options.symbolizer[key] = value; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ } │ │ │ │ │ - return this; │ │ │ │ │ + // clone filter │ │ │ │ │ + options.filter = this.filter && this.filter.clone(); │ │ │ │ │ + // clone context │ │ │ │ │ + options.context = this.context && OpenLayers.Util.extend({}, this.context); │ │ │ │ │ + return new OpenLayers.Rule(options); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ + CLASS_NAME: "OpenLayers.Rule" │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Symbolizer.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Symbolizer │ │ │ │ │ + * Base class representing a symbolizer used for feature rendering. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Symbolizer = OpenLayers.Class({ │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getVertices │ │ │ │ │ - * Return a list of all points in this geometry. │ │ │ │ │ + * APIProperty: zIndex │ │ │ │ │ + * {Number} The zIndex determines the rendering order for a symbolizer. │ │ │ │ │ + * Symbolizers with larger zIndex values are rendered over symbolizers │ │ │ │ │ + * with smaller zIndex values. Default is 0. │ │ │ │ │ + */ │ │ │ │ │ + zIndex: 0, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Symbolizer │ │ │ │ │ + * Instances of this class are not useful. See one of the subclasses. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * nodes - {Boolean} For lines, only return vertices that are │ │ │ │ │ - * endpoints. If false, for lines, only vertices that are not │ │ │ │ │ - * endpoints will be returned. If not provided, all vertices will │ │ │ │ │ - * be returned. │ │ │ │ │ + * config - {Object} An object containing properties to be set on the │ │ │ │ │ + * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ + * construction. │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Array} A list of all vertices in the geometry. │ │ │ │ │ + * A new symbolizer. │ │ │ │ │ */ │ │ │ │ │ - getVertices: function(nodes) { │ │ │ │ │ - return [this]; │ │ │ │ │ + initialize: function(config) { │ │ │ │ │ + OpenLayers.Util.extend(this, config); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Geometry.Point" │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: clone │ │ │ │ │ + * Create a copy of this symbolizer. │ │ │ │ │ + * │ │ │ │ │ + * Returns a symbolizer of the same type with the same properties. │ │ │ │ │ + */ │ │ │ │ │ + clone: function() { │ │ │ │ │ + var Type = eval(this.CLASS_NAME); │ │ │ │ │ + return new Type(OpenLayers.Util.extend({}, this)); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Symbolizer" │ │ │ │ │ + │ │ │ │ │ }); │ │ │ │ │ + │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Geometry/Collection.js │ │ │ │ │ + OpenLayers/Symbolizer/Point.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/Geometry.js │ │ │ │ │ + * @requires OpenLayers/Symbolizer.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Geometry.Collection │ │ │ │ │ - * A Collection is exactly what it sounds like: A collection of different │ │ │ │ │ - * Geometries. These are stored in the local parameter (which │ │ │ │ │ - * can be passed as a parameter to the constructor). │ │ │ │ │ - * │ │ │ │ │ - * As new geometries are added to the collection, they are NOT cloned. │ │ │ │ │ - * When removing geometries, they need to be specified by reference (ie you │ │ │ │ │ - * have to pass in the *exact* geometry to be removed). │ │ │ │ │ - * │ │ │ │ │ - * The and functions here merely iterate through │ │ │ │ │ - * the components, summing their respective areas and lengths. │ │ │ │ │ - * │ │ │ │ │ - * Create a new instance with the constructor. │ │ │ │ │ - * │ │ │ │ │ - * Inherits from: │ │ │ │ │ - * - │ │ │ │ │ + * Class: OpenLayers.Symbolizer.Point │ │ │ │ │ + * A symbolizer used to render point features. │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Geometry.Collection = OpenLayers.Class(OpenLayers.Geometry, { │ │ │ │ │ +OpenLayers.Symbolizer.Point = OpenLayers.Class(OpenLayers.Symbolizer, { │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: components │ │ │ │ │ - * {Array()} The component parts of this geometry │ │ │ │ │ + * APIProperty: strokeColor │ │ │ │ │ + * {String} Color for line stroke. This is a RGB hex value (e.g. "#ff0000" │ │ │ │ │ + * for red). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - components: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: componentTypes │ │ │ │ │ - * {Array(String)} An array of class names representing the types of │ │ │ │ │ - * components that the collection can include. A null value means the │ │ │ │ │ - * component types are not restricted. │ │ │ │ │ + * APIProperty: strokeOpacity │ │ │ │ │ + * {Number} Stroke opacity (0-1). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - componentTypes: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Geometry.Collection │ │ │ │ │ - * Creates a Geometry Collection -- a list of geoms. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * components - {Array()} Optional array of geometries │ │ │ │ │ - * │ │ │ │ │ + * APIProperty: strokeWidth │ │ │ │ │ + * {Number} Pixel stroke width. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - initialize: function(components) { │ │ │ │ │ - OpenLayers.Geometry.prototype.initialize.apply(this, arguments); │ │ │ │ │ - this.components = []; │ │ │ │ │ - if (components != null) { │ │ │ │ │ - this.addComponents(components); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: destroy │ │ │ │ │ - * Destroy this geometry. │ │ │ │ │ + * APIProperty: strokeLinecap │ │ │ │ │ + * {String} Stroke cap type ("butt", "round", or "square"). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - this.components.length = 0; │ │ │ │ │ - this.components = null; │ │ │ │ │ - OpenLayers.Geometry.prototype.destroy.apply(this, arguments); │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: clone │ │ │ │ │ - * Clone this geometry. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} An exact clone of this collection │ │ │ │ │ + * Property: strokeDashstyle │ │ │ │ │ + * {String} Stroke dash style according to the SLD spec. Note that the │ │ │ │ │ + * OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot", │ │ │ │ │ + * "longdash", "longdashdot", or "solid") will not work in SLD, but │ │ │ │ │ + * most SLD patterns will render correctly in OpenLayers. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - clone: function() { │ │ │ │ │ - var geometry = eval("new " + this.CLASS_NAME + "()"); │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ - geometry.addComponent(this.components[i].clone()); │ │ │ │ │ - } │ │ │ │ │ │ │ │ │ │ - // catch any randomly tagged-on properties │ │ │ │ │ - OpenLayers.Util.applyDefaults(geometry, this); │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: fillColor │ │ │ │ │ + * {String} RGB hex fill color (e.g. "#ff0000" for red). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ │ │ │ │ │ - return geometry; │ │ │ │ │ - }, │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: fillOpacity │ │ │ │ │ + * {Number} Fill opacity (0-1). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: getComponentsString │ │ │ │ │ - * Get a string representing the components for this collection │ │ │ │ │ + * APIProperty: pointRadius │ │ │ │ │ + * {Number} Pixel point radius. │ │ │ │ │ * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} A string representation of the components of this geometry │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - getComponentsString: function() { │ │ │ │ │ - var strings = []; │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ - strings.push(this.components[i].toShortString()); │ │ │ │ │ - } │ │ │ │ │ - return strings.join(","); │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: calculateBounds │ │ │ │ │ - * Recalculate the bounds by iterating through the components and │ │ │ │ │ - * calling calling extendBounds() on each item. │ │ │ │ │ + * APIProperty: externalGraphic │ │ │ │ │ + * {String} Url to an external graphic that will be used for rendering │ │ │ │ │ + * points. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - calculateBounds: function() { │ │ │ │ │ - this.bounds = null; │ │ │ │ │ - var bounds = new OpenLayers.Bounds(); │ │ │ │ │ - var components = this.components; │ │ │ │ │ - if (components) { │ │ │ │ │ - for (var i = 0, len = components.length; i < len; i++) { │ │ │ │ │ - bounds.extend(components[i].getBounds()); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - // to preserve old behavior, we only set bounds if non-null │ │ │ │ │ - // in the future, we could add bounds.isEmpty() │ │ │ │ │ - if (bounds.left != null && bounds.bottom != null && │ │ │ │ │ - bounds.right != null && bounds.top != null) { │ │ │ │ │ - this.setBounds(bounds); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: addComponents │ │ │ │ │ - * Add components to this geometry. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * components - {Array()} An array of geometries to add │ │ │ │ │ + * APIProperty: graphicWidth │ │ │ │ │ + * {Number} Pixel width for sizing an external graphic. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - addComponents: function(components) { │ │ │ │ │ - if (!(OpenLayers.Util.isArray(components))) { │ │ │ │ │ - components = [components]; │ │ │ │ │ - } │ │ │ │ │ - for (var i = 0, len = components.length; i < len; i++) { │ │ │ │ │ - this.addComponent(components[i]); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: addComponent │ │ │ │ │ - * Add a new component (geometry) to the collection. If this.componentTypes │ │ │ │ │ - * is set, then the component class name must be in the componentTypes array. │ │ │ │ │ - * │ │ │ │ │ - * The bounds cache is reset. │ │ │ │ │ + * APIProperty: graphicHeight │ │ │ │ │ + * {Number} Pixel height for sizing an external graphic. │ │ │ │ │ * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * component - {} A geometry to add │ │ │ │ │ - * index - {int} Optional index into the array to insert the component │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} The component geometry was successfully added │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - addComponent: function(component, index) { │ │ │ │ │ - var added = false; │ │ │ │ │ - if (component) { │ │ │ │ │ - if (this.componentTypes == null || │ │ │ │ │ - (OpenLayers.Util.indexOf(this.componentTypes, │ │ │ │ │ - component.CLASS_NAME) > -1)) { │ │ │ │ │ │ │ │ │ │ - if (index != null && (index < this.components.length)) { │ │ │ │ │ - var components1 = this.components.slice(0, index); │ │ │ │ │ - var components2 = this.components.slice(index, │ │ │ │ │ - this.components.length); │ │ │ │ │ - components1.push(component); │ │ │ │ │ - this.components = components1.concat(components2); │ │ │ │ │ - } else { │ │ │ │ │ - this.components.push(component); │ │ │ │ │ - } │ │ │ │ │ - component.parent = this; │ │ │ │ │ - this.clearBounds(); │ │ │ │ │ - added = true; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return added; │ │ │ │ │ - }, │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: graphicOpacity │ │ │ │ │ + * {Number} Opacity (0-1) for an external graphic. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: removeComponents │ │ │ │ │ - * Remove components from this geometry. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * components - {Array()} The components to be removed │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} A component was removed. │ │ │ │ │ + * APIProperty: graphicXOffset │ │ │ │ │ + * {Number} Pixel offset along the positive x axis for displacing an │ │ │ │ │ + * external graphic. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - removeComponents: function(components) { │ │ │ │ │ - var removed = false; │ │ │ │ │ │ │ │ │ │ - if (!(OpenLayers.Util.isArray(components))) { │ │ │ │ │ - components = [components]; │ │ │ │ │ - } │ │ │ │ │ - for (var i = components.length - 1; i >= 0; --i) { │ │ │ │ │ - removed = this.removeComponent(components[i]) || removed; │ │ │ │ │ - } │ │ │ │ │ - return removed; │ │ │ │ │ - }, │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: graphicYOffset │ │ │ │ │ + * {Number} Pixel offset along the positive y axis for displacing an │ │ │ │ │ + * external graphic. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: removeComponent │ │ │ │ │ - * Remove a component from this geometry. │ │ │ │ │ + * APIProperty: rotation │ │ │ │ │ + * {Number} The rotation of a graphic in the clockwise direction about its │ │ │ │ │ + * center point (or any point off center as specified by │ │ │ │ │ + * and ). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: graphicName │ │ │ │ │ + * {String} Named graphic to use when rendering points. Supported values │ │ │ │ │ + * include "circle", "square", "star", "x", "cross", and "triangle". │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Symbolizer.Point │ │ │ │ │ + * Create a symbolizer for rendering points. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * component - {} │ │ │ │ │ + * config - {Object} An object containing properties to be set on the │ │ │ │ │ + * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ + * construction. │ │ │ │ │ * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} The component was removed. │ │ │ │ │ + * Returns: │ │ │ │ │ + * A new point symbolizer. │ │ │ │ │ */ │ │ │ │ │ - removeComponent: function(component) { │ │ │ │ │ + initialize: function(config) { │ │ │ │ │ + OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments); │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - OpenLayers.Util.removeItem(this.components, component); │ │ │ │ │ + CLASS_NAME: "OpenLayers.Symbolizer.Point" │ │ │ │ │ │ │ │ │ │ - // clearBounds() so that it gets recalculated on the next call │ │ │ │ │ - // to this.getBounds(); │ │ │ │ │ - this.clearBounds(); │ │ │ │ │ - return true; │ │ │ │ │ - }, │ │ │ │ │ +}); │ │ │ │ │ + │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Symbolizer/Line.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Symbolizer.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Symbolizer.Line │ │ │ │ │ + * A symbolizer used to render line features. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Symbolizer.Line = OpenLayers.Class(OpenLayers.Symbolizer, { │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getLength │ │ │ │ │ - * Calculate the length of this geometry │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Float} The length of the geometry │ │ │ │ │ + * APIProperty: strokeColor │ │ │ │ │ + * {String} Color for line stroke. This is a RGB hex value (e.g. "#ff0000" │ │ │ │ │ + * for red). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - getLength: function() { │ │ │ │ │ - var length = 0.0; │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ - length += this.components[i].getLength(); │ │ │ │ │ - } │ │ │ │ │ - return length; │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getArea │ │ │ │ │ - * Calculate the area of this geometry. Note how this function is overridden │ │ │ │ │ - * in . │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Float} The area of the collection by summing its parts │ │ │ │ │ + * APIProperty: strokeOpacity │ │ │ │ │ + * {Number} Stroke opacity (0-1). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - getArea: function() { │ │ │ │ │ - var area = 0.0; │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ - area += this.components[i].getArea(); │ │ │ │ │ - } │ │ │ │ │ - return area; │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: getGeodesicArea │ │ │ │ │ - * Calculate the approximate area of the polygon were it projected onto │ │ │ │ │ - * the earth. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * projection - {} The spatial reference system │ │ │ │ │ - * for the geometry coordinates. If not provided, Geographic/WGS84 is │ │ │ │ │ - * assumed. │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: strokeWidth │ │ │ │ │ + * {Number} Pixel stroke width. │ │ │ │ │ * │ │ │ │ │ - * Reference: │ │ │ │ │ - * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for │ │ │ │ │ - * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion │ │ │ │ │ - * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409 │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {float} The approximate geodesic area of the geometry in square meters. │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - getGeodesicArea: function(projection) { │ │ │ │ │ - var area = 0.0; │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ - area += this.components[i].getGeodesicArea(projection); │ │ │ │ │ - } │ │ │ │ │ - return area; │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getCentroid │ │ │ │ │ - * │ │ │ │ │ - * Compute the centroid for this geometry collection. │ │ │ │ │ + * APIProperty: strokeLinecap │ │ │ │ │ + * {String} Stroke cap type ("butt", "round", or "square"). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: strokeDashstyle │ │ │ │ │ + * {String} Stroke dash style according to the SLD spec. Note that the │ │ │ │ │ + * OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot", │ │ │ │ │ + * "longdash", "longdashdot", or "solid") will not work in SLD, but │ │ │ │ │ + * most SLD patterns will render correctly in OpenLayers. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Symbolizer.Line │ │ │ │ │ + * Create a symbolizer for rendering lines. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * weighted - {Boolean} Perform the getCentroid computation recursively, │ │ │ │ │ - * returning an area weighted average of all geometries in this collection. │ │ │ │ │ + * config - {Object} An object containing properties to be set on the │ │ │ │ │ + * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ + * construction. │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {} The centroid of the collection │ │ │ │ │ + * A new line symbolizer. │ │ │ │ │ */ │ │ │ │ │ - getCentroid: function(weighted) { │ │ │ │ │ - if (!weighted) { │ │ │ │ │ - return this.components.length && this.components[0].getCentroid(); │ │ │ │ │ - } │ │ │ │ │ - var len = this.components.length; │ │ │ │ │ - if (!len) { │ │ │ │ │ - return false; │ │ │ │ │ - } │ │ │ │ │ + initialize: function(config) { │ │ │ │ │ + OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments); │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - var areas = []; │ │ │ │ │ - var centroids = []; │ │ │ │ │ - var areaSum = 0; │ │ │ │ │ - var minArea = Number.MAX_VALUE; │ │ │ │ │ - var component; │ │ │ │ │ - for (var i = 0; i < len; ++i) { │ │ │ │ │ - component = this.components[i]; │ │ │ │ │ - var area = component.getArea(); │ │ │ │ │ - var centroid = component.getCentroid(true); │ │ │ │ │ - if (isNaN(area) || isNaN(centroid.x) || isNaN(centroid.y)) { │ │ │ │ │ - continue; │ │ │ │ │ - } │ │ │ │ │ - areas.push(area); │ │ │ │ │ - areaSum += area; │ │ │ │ │ - minArea = (area < minArea && area > 0) ? area : minArea; │ │ │ │ │ - centroids.push(centroid); │ │ │ │ │ - } │ │ │ │ │ - len = areas.length; │ │ │ │ │ - if (areaSum === 0) { │ │ │ │ │ - // all the components in this collection have 0 area │ │ │ │ │ - // probably a collection of points -- weight all the points the same │ │ │ │ │ - for (var i = 0; i < len; ++i) { │ │ │ │ │ - areas[i] = 1; │ │ │ │ │ - } │ │ │ │ │ - areaSum = areas.length; │ │ │ │ │ - } else { │ │ │ │ │ - // normalize all the areas where the smallest area will get │ │ │ │ │ - // a value of 1 │ │ │ │ │ - for (var i = 0; i < len; ++i) { │ │ │ │ │ - areas[i] /= minArea; │ │ │ │ │ - } │ │ │ │ │ - areaSum /= minArea; │ │ │ │ │ - } │ │ │ │ │ + CLASS_NAME: "OpenLayers.Symbolizer.Line" │ │ │ │ │ │ │ │ │ │ - var xSum = 0, │ │ │ │ │ - ySum = 0, │ │ │ │ │ - centroid, area; │ │ │ │ │ - for (var i = 0; i < len; ++i) { │ │ │ │ │ - centroid = centroids[i]; │ │ │ │ │ - area = areas[i]; │ │ │ │ │ - xSum += centroid.x * area; │ │ │ │ │ - ySum += centroid.y * area; │ │ │ │ │ - } │ │ │ │ │ +}); │ │ │ │ │ │ │ │ │ │ - return new OpenLayers.Geometry.Point(xSum / areaSum, ySum / areaSum); │ │ │ │ │ - }, │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Symbolizer/Polygon.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Symbolizer.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Symbolizer.Polygon │ │ │ │ │ + * A symbolizer used to render line features. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Symbolizer.Polygon = OpenLayers.Class(OpenLayers.Symbolizer, { │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getGeodesicLength │ │ │ │ │ - * Calculate the approximate length of the geometry were it projected onto │ │ │ │ │ - * the earth. │ │ │ │ │ - * │ │ │ │ │ - * projection - {} The spatial reference system │ │ │ │ │ - * for the geometry coordinates. If not provided, Geographic/WGS84 is │ │ │ │ │ - * assumed. │ │ │ │ │ + * APIProperty: strokeColor │ │ │ │ │ + * {String} Color for line stroke. This is a RGB hex value (e.g. "#ff0000" │ │ │ │ │ + * for red). │ │ │ │ │ * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Float} The appoximate geodesic length of the geometry in meters. │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - getGeodesicLength: function(projection) { │ │ │ │ │ - var length = 0.0; │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ - length += this.components[i].getGeodesicLength(projection); │ │ │ │ │ - } │ │ │ │ │ - return length; │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: move │ │ │ │ │ - * Moves a geometry by the given displacement along positive x and y axes. │ │ │ │ │ - * This modifies the position of the geometry and clears the cached │ │ │ │ │ - * bounds. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * x - {Float} Distance to move geometry in positive x direction. │ │ │ │ │ - * y - {Float} Distance to move geometry in positive y direction. │ │ │ │ │ + * APIProperty: strokeOpacity │ │ │ │ │ + * {Number} Stroke opacity (0-1). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - move: function(x, y) { │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ - this.components[i].move(x, y); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: rotate │ │ │ │ │ - * Rotate a geometry around some origin │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * angle - {Float} Rotation angle in degrees (measured counterclockwise │ │ │ │ │ - * from the positive x-axis) │ │ │ │ │ - * origin - {} Center point for the rotation │ │ │ │ │ + * APIProperty: strokeWidth │ │ │ │ │ + * {Number} Pixel stroke width. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - rotate: function(angle, origin) { │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; ++i) { │ │ │ │ │ - this.components[i].rotate(angle, origin); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: resize │ │ │ │ │ - * Resize a geometry relative to some origin. Use this method to apply │ │ │ │ │ - * a uniform scaling to a geometry. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * scale - {Float} Factor by which to scale the geometry. A scale of 2 │ │ │ │ │ - * doubles the size of the geometry in each dimension │ │ │ │ │ - * (lines, for example, will be twice as long, and polygons │ │ │ │ │ - * will have four times the area). │ │ │ │ │ - * origin - {} Point of origin for resizing │ │ │ │ │ - * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1. │ │ │ │ │ + * APIProperty: strokeLinecap │ │ │ │ │ + * {String} Stroke cap type ("butt", "round", or "square"). │ │ │ │ │ * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} - The current geometry. │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - resize: function(scale, origin, ratio) { │ │ │ │ │ - for (var i = 0; i < this.components.length; ++i) { │ │ │ │ │ - this.components[i].resize(scale, origin, ratio); │ │ │ │ │ - } │ │ │ │ │ - return this; │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: distanceTo │ │ │ │ │ - * Calculate the closest distance between two geometries (on the x-y plane). │ │ │ │ │ + * Property: strokeDashstyle │ │ │ │ │ + * {String} Stroke dash style according to the SLD spec. Note that the │ │ │ │ │ + * OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot", │ │ │ │ │ + * "longdash", "longdashdot", or "solid") will not work in SLD, but │ │ │ │ │ + * most SLD patterns will render correctly in OpenLayers. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: fillColor │ │ │ │ │ + * {String} RGB hex fill color (e.g. "#ff0000" for red). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: fillOpacity │ │ │ │ │ + * {Number} Fill opacity (0-1). │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Symbolizer.Polygon │ │ │ │ │ + * Create a symbolizer for rendering polygons. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * geometry - {} The target geometry. │ │ │ │ │ - * options - {Object} Optional properties for configuring the distance │ │ │ │ │ - * calculation. │ │ │ │ │ - * │ │ │ │ │ - * Valid options: │ │ │ │ │ - * details - {Boolean} Return details from the distance calculation. │ │ │ │ │ - * Default is false. │ │ │ │ │ - * edge - {Boolean} Calculate the distance from this geometry to the │ │ │ │ │ - * nearest edge of the target geometry. Default is true. If true, │ │ │ │ │ - * calling distanceTo from a geometry that is wholly contained within │ │ │ │ │ - * the target will result in a non-zero distance. If false, whenever │ │ │ │ │ - * geometries intersect, calling distanceTo will return 0. If false, │ │ │ │ │ - * details cannot be returned. │ │ │ │ │ + * config - {Object} An object containing properties to be set on the │ │ │ │ │ + * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ + * construction. │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Number | Object} The distance between this geometry and the target. │ │ │ │ │ - * If details is true, the return will be an object with distance, │ │ │ │ │ - * x0, y0, x1, and y1 properties. The x0 and y0 properties represent │ │ │ │ │ - * the coordinates of the closest point on this geometry. The x1 and y1 │ │ │ │ │ - * properties represent the coordinates of the closest point on the │ │ │ │ │ - * target geometry. │ │ │ │ │ + * A new polygon symbolizer. │ │ │ │ │ */ │ │ │ │ │ - distanceTo: function(geometry, options) { │ │ │ │ │ - var edge = !(options && options.edge === false); │ │ │ │ │ - var details = edge && options && options.details; │ │ │ │ │ - var result, best, distance; │ │ │ │ │ - var min = Number.POSITIVE_INFINITY; │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; ++i) { │ │ │ │ │ - result = this.components[i].distanceTo(geometry, options); │ │ │ │ │ - distance = details ? result.distance : result; │ │ │ │ │ - if (distance < min) { │ │ │ │ │ - min = distance; │ │ │ │ │ - best = result; │ │ │ │ │ - if (min == 0) { │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return best; │ │ │ │ │ + initialize: function(config) { │ │ │ │ │ + OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ + CLASS_NAME: "OpenLayers.Symbolizer.Polygon" │ │ │ │ │ + │ │ │ │ │ +}); │ │ │ │ │ + │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Symbolizer/Text.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Symbolizer.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Symbolizer.Text │ │ │ │ │ + * A symbolizer used to render text labels for features. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Symbolizer.Text = OpenLayers.Class(OpenLayers.Symbolizer, { │ │ │ │ │ + │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: equals │ │ │ │ │ - * Determine whether another geometry is equivalent to this one. Geometries │ │ │ │ │ - * are considered equivalent if all components have the same coordinates. │ │ │ │ │ + * APIProperty: label │ │ │ │ │ + * {String} The text for the label. │ │ │ │ │ * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * geometry - {} The geometry to test. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} The supplied geometry is equivalent to this geometry. │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - equals: function(geometry) { │ │ │ │ │ - var equivalent = true; │ │ │ │ │ - if (!geometry || !geometry.CLASS_NAME || │ │ │ │ │ - (this.CLASS_NAME != geometry.CLASS_NAME)) { │ │ │ │ │ - equivalent = false; │ │ │ │ │ - } else if (!(OpenLayers.Util.isArray(geometry.components)) || │ │ │ │ │ - (geometry.components.length != this.components.length)) { │ │ │ │ │ - equivalent = false; │ │ │ │ │ - } else { │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; ++i) { │ │ │ │ │ - if (!this.components[i].equals(geometry.components[i])) { │ │ │ │ │ - equivalent = false; │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return equivalent; │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: transform │ │ │ │ │ - * Reproject the components geometry from source to dest. │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: fontFamily │ │ │ │ │ + * {String} The font family for the label. │ │ │ │ │ * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * source - {} │ │ │ │ │ - * dest - {} │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: fontSize │ │ │ │ │ + * {String} The font size for the label. │ │ │ │ │ * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: fontWeight │ │ │ │ │ + * {String} The font weight for the label. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - transform: function(source, dest) { │ │ │ │ │ - if (source && dest) { │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ - var component = this.components[i]; │ │ │ │ │ - component.transform(source, dest); │ │ │ │ │ - } │ │ │ │ │ - this.bounds = null; │ │ │ │ │ - } │ │ │ │ │ - return this; │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: intersects │ │ │ │ │ - * Determine if the input geometry intersects this one. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * geometry - {} Any type of geometry. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} The input geometry intersects this one. │ │ │ │ │ + * Property: fontStyle │ │ │ │ │ + * {String} The font style for the label. │ │ │ │ │ + * │ │ │ │ │ + * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ */ │ │ │ │ │ - intersects: function(geometry) { │ │ │ │ │ - var intersect = false; │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; ++i) { │ │ │ │ │ - intersect = geometry.intersects(this.components[i]); │ │ │ │ │ - if (intersect) { │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return intersect; │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getVertices │ │ │ │ │ - * Return a list of all points in this geometry. │ │ │ │ │ + * Constructor: OpenLayers.Symbolizer.Text │ │ │ │ │ + * Create a symbolizer for rendering text labels. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * nodes - {Boolean} For lines, only return vertices that are │ │ │ │ │ - * endpoints. If false, for lines, only vertices that are not │ │ │ │ │ - * endpoints will be returned. If not provided, all vertices will │ │ │ │ │ - * be returned. │ │ │ │ │ + * config - {Object} An object containing properties to be set on the │ │ │ │ │ + * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ + * construction. │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Array} A list of all vertices in the geometry. │ │ │ │ │ + * A new text symbolizer. │ │ │ │ │ */ │ │ │ │ │ - getVertices: function(nodes) { │ │ │ │ │ - var vertices = []; │ │ │ │ │ - for (var i = 0, len = this.components.length; i < len; ++i) { │ │ │ │ │ - Array.prototype.push.apply( │ │ │ │ │ - vertices, this.components[i].getVertices(nodes) │ │ │ │ │ - ); │ │ │ │ │ - } │ │ │ │ │ - return vertices; │ │ │ │ │ + initialize: function(config) { │ │ │ │ │ + OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ + CLASS_NAME: "OpenLayers.Symbolizer.Text" │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Geometry.Collection" │ │ │ │ │ }); │ │ │ │ │ + │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Geometry/MultiPoint.js │ │ │ │ │ + OpenLayers/Symbolizer/Raster.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/Geometry/Collection.js │ │ │ │ │ - * @requires OpenLayers/Geometry/Point.js │ │ │ │ │ + * @requires OpenLayers/Symbolizer.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Geometry.MultiPoint │ │ │ │ │ - * MultiPoint is a collection of Points. Create a new instance with the │ │ │ │ │ - * constructor. │ │ │ │ │ - * │ │ │ │ │ - * Inherits from: │ │ │ │ │ - * - │ │ │ │ │ - * - │ │ │ │ │ + * Class: OpenLayers.Symbolizer.Raster │ │ │ │ │ + * A symbolizer used to render raster images. │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Geometry.MultiPoint = OpenLayers.Class( │ │ │ │ │ - OpenLayers.Geometry.Collection, { │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: componentTypes │ │ │ │ │ - * {Array(String)} An array of class names representing the types of │ │ │ │ │ - * components that the collection can include. A null value means the │ │ │ │ │ - * component types are not restricted. │ │ │ │ │ - */ │ │ │ │ │ - componentTypes: ["OpenLayers.Geometry.Point"], │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Geometry.MultiPoint │ │ │ │ │ - * Create a new MultiPoint Geometry │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * components - {Array()} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} │ │ │ │ │ - */ │ │ │ │ │ +OpenLayers.Symbolizer.Raster = OpenLayers.Class(OpenLayers.Symbolizer, { │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: addPoint │ │ │ │ │ - * Wrapper for │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * point - {} Point to be added │ │ │ │ │ - * index - {Integer} Optional index │ │ │ │ │ - */ │ │ │ │ │ - addPoint: function(point, index) { │ │ │ │ │ - this.addComponent(point, index); │ │ │ │ │ - }, │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Symbolizer.Raster │ │ │ │ │ + * Create a symbolizer for rendering rasters. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * config - {Object} An object containing properties to be set on the │ │ │ │ │ + * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ + * construction. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * A new raster symbolizer. │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(config) { │ │ │ │ │ + OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments); │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: removePoint │ │ │ │ │ - * Wrapper for │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * point - {} Point to be removed │ │ │ │ │ - */ │ │ │ │ │ - removePoint: function(point) { │ │ │ │ │ - this.removeComponent(point); │ │ │ │ │ - }, │ │ │ │ │ + CLASS_NAME: "OpenLayers.Symbolizer.Raster" │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Geometry.MultiPoint" │ │ │ │ │ - }); │ │ │ │ │ +}); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Geometry/Curve.js │ │ │ │ │ + OpenLayers/Style2.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/Geometry/MultiPoint.js │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + * @requires OpenLayers/Rule.js │ │ │ │ │ + * @requires OpenLayers/Symbolizer/Point.js │ │ │ │ │ + * @requires OpenLayers/Symbolizer/Line.js │ │ │ │ │ + * @requires OpenLayers/Symbolizer/Polygon.js │ │ │ │ │ + * @requires OpenLayers/Symbolizer/Text.js │ │ │ │ │ + * @requires OpenLayers/Symbolizer/Raster.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Geometry.Curve │ │ │ │ │ - * A Curve is a MultiPoint, whose points are assumed to be connected. To │ │ │ │ │ - * this end, we provide a "getLength()" function, which iterates through │ │ │ │ │ - * the points, summing the distances between them. │ │ │ │ │ - * │ │ │ │ │ - * Inherits: │ │ │ │ │ - * - │ │ │ │ │ + * Class: OpenLayers.Style2 │ │ │ │ │ + * This class represents a collection of rules for rendering features. │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Geometry.Curve = OpenLayers.Class(OpenLayers.Geometry.MultiPoint, { │ │ │ │ │ +OpenLayers.Style2 = OpenLayers.Class({ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: componentTypes │ │ │ │ │ - * {Array(String)} An array of class names representing the types of │ │ │ │ │ - * components that the collection can include. A null │ │ │ │ │ - * value means the component types are not restricted. │ │ │ │ │ + * Property: id │ │ │ │ │ + * {String} A unique id for this session. │ │ │ │ │ */ │ │ │ │ │ - componentTypes: ["OpenLayers.Geometry.Point"], │ │ │ │ │ + id: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Geometry.Curve │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * point - {Array()} │ │ │ │ │ + * APIProperty: name │ │ │ │ │ + * {String} Style identifier. │ │ │ │ │ */ │ │ │ │ │ + name: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getLength │ │ │ │ │ - * │ │ │ │ │ + * APIProperty: title │ │ │ │ │ + * {String} Title of this style. │ │ │ │ │ + */ │ │ │ │ │ + title: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: description │ │ │ │ │ + * {String} Description of this style. │ │ │ │ │ + */ │ │ │ │ │ + description: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: layerName │ │ │ │ │ + * {} Name of the layer that this style belongs to, usually │ │ │ │ │ + * according to the NamedLayer attribute of an SLD document. │ │ │ │ │ + */ │ │ │ │ │ + layerName: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: isDefault │ │ │ │ │ + * {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + isDefault: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: rules │ │ │ │ │ + * {Array()} Collection of rendering rules. │ │ │ │ │ + */ │ │ │ │ │ + rules: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Style2 │ │ │ │ │ + * Creates a style representing a collection of rendering rules. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * config - {Object} An object containing properties to be set on the │ │ │ │ │ + * style. Any documented properties may be set at construction. │ │ │ │ │ + * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Float} The length of the curve │ │ │ │ │ + * {} A new style object. │ │ │ │ │ */ │ │ │ │ │ - getLength: function() { │ │ │ │ │ - var length = 0.0; │ │ │ │ │ - if (this.components && (this.components.length > 1)) { │ │ │ │ │ - for (var i = 1, len = this.components.length; i < len; i++) { │ │ │ │ │ - length += this.components[i - 1].distanceTo(this.components[i]); │ │ │ │ │ - } │ │ │ │ │ + initialize: function(config) { │ │ │ │ │ + OpenLayers.Util.extend(this, config); │ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: destroy │ │ │ │ │ + * nullify references to prevent circular references and memory leaks │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + for (var i = 0, len = this.rules.length; i < len; i++) { │ │ │ │ │ + this.rules[i].destroy(); │ │ │ │ │ } │ │ │ │ │ - return length; │ │ │ │ │ + delete this.rules; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getGeodesicLength │ │ │ │ │ - * Calculate the approximate length of the geometry were it projected onto │ │ │ │ │ - * the earth. │ │ │ │ │ - * │ │ │ │ │ - * projection - {} The spatial reference system │ │ │ │ │ - * for the geometry coordinates. If not provided, Geographic/WGS84 is │ │ │ │ │ - * assumed. │ │ │ │ │ + * APIMethod: clone │ │ │ │ │ + * Clones this style. │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Float} The appoximate geodesic length of the geometry in meters. │ │ │ │ │ + * {} Clone of this style. │ │ │ │ │ */ │ │ │ │ │ - getGeodesicLength: function(projection) { │ │ │ │ │ - var geom = this; // so we can work with a clone if needed │ │ │ │ │ - if (projection) { │ │ │ │ │ - var gg = new OpenLayers.Projection("EPSG:4326"); │ │ │ │ │ - if (!gg.equals(projection)) { │ │ │ │ │ - geom = this.clone().transform(projection, gg); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - var length = 0.0; │ │ │ │ │ - if (geom.components && (geom.components.length > 1)) { │ │ │ │ │ - var p1, p2; │ │ │ │ │ - for (var i = 1, len = geom.components.length; i < len; i++) { │ │ │ │ │ - p1 = geom.components[i - 1]; │ │ │ │ │ - p2 = geom.components[i]; │ │ │ │ │ - // this returns km and requires lon/lat properties │ │ │ │ │ - length += OpenLayers.Util.distVincenty({ │ │ │ │ │ - lon: p1.x, │ │ │ │ │ - lat: p1.y │ │ │ │ │ - }, { │ │ │ │ │ - lon: p2.x, │ │ │ │ │ - lat: p2.y │ │ │ │ │ - }); │ │ │ │ │ + clone: function() { │ │ │ │ │ + var config = OpenLayers.Util.extend({}, this); │ │ │ │ │ + // clone rules │ │ │ │ │ + if (this.rules) { │ │ │ │ │ + config.rules = []; │ │ │ │ │ + for (var i = 0, len = this.rules.length; i < len; ++i) { │ │ │ │ │ + config.rules.push(this.rules[i].clone()); │ │ │ │ │ } │ │ │ │ │ } │ │ │ │ │ - // convert to m │ │ │ │ │ - return length * 1000; │ │ │ │ │ + return new OpenLayers.Style2(config); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Geometry.Curve" │ │ │ │ │ + CLASS_NAME: "OpenLayers.Style2" │ │ │ │ │ }); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Geometry/LineString.js │ │ │ │ │ + OpenLayers/Projection.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/Geometry/Curve.js │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + * @requires OpenLayers/Util.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Geometry.LineString │ │ │ │ │ - * A LineString is a Curve which, once two points have been added to it, can │ │ │ │ │ - * never be less than two points long. │ │ │ │ │ - * │ │ │ │ │ - * Inherits from: │ │ │ │ │ - * - │ │ │ │ │ + * Namespace: OpenLayers.Projection │ │ │ │ │ + * Methods for coordinate transforms between coordinate systems. By default, │ │ │ │ │ + * OpenLayers ships with the ability to transform coordinates between │ │ │ │ │ + * geographic (EPSG:4326) and web or spherical mercator (EPSG:900913 et al.) │ │ │ │ │ + * coordinate reference systems. See the method for details │ │ │ │ │ + * on usage. │ │ │ │ │ + * │ │ │ │ │ + * Additional transforms may be added by using the │ │ │ │ │ + * library. If the proj4js library is included, the method │ │ │ │ │ + * will work between any two coordinate reference systems with proj4js │ │ │ │ │ + * definitions. │ │ │ │ │ + * │ │ │ │ │ + * If the proj4js library is not included, or if you wish to allow transforms │ │ │ │ │ + * between arbitrary coordinate reference systems, use the │ │ │ │ │ + * method to register a custom transform method. │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, { │ │ │ │ │ +OpenLayers.Projection = OpenLayers.Class({ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Geometry.LineString │ │ │ │ │ - * Create a new LineString geometry │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * points - {Array()} An array of points used to │ │ │ │ │ - * generate the linestring │ │ │ │ │ - * │ │ │ │ │ + * Property: proj │ │ │ │ │ + * {Object} Proj4js.Proj instance. │ │ │ │ │ */ │ │ │ │ │ + proj: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: removeComponent │ │ │ │ │ - * Only allows removal of a point if there are three or more points in │ │ │ │ │ - * the linestring. (otherwise the result would be just a single point) │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * point - {} The point to be removed │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} The component was removed. │ │ │ │ │ + * Property: projCode │ │ │ │ │ + * {String} │ │ │ │ │ */ │ │ │ │ │ - removeComponent: function(point) { │ │ │ │ │ - var removed = this.components && (this.components.length > 2); │ │ │ │ │ - if (removed) { │ │ │ │ │ - OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this, │ │ │ │ │ - arguments); │ │ │ │ │ - } │ │ │ │ │ - return removed; │ │ │ │ │ - }, │ │ │ │ │ + projCode: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: intersects │ │ │ │ │ - * Test for instersection between two geometries. This is a cheapo │ │ │ │ │ - * implementation of the Bently-Ottmann algorigithm. It doesn't │ │ │ │ │ - * really keep track of a sweep line data structure. It is closer │ │ │ │ │ - * to the brute force method, except that segments are sorted and │ │ │ │ │ - * potential intersections are only calculated when bounding boxes │ │ │ │ │ - * intersect. │ │ │ │ │ + * Property: titleRegEx │ │ │ │ │ + * {RegExp} regular expression to strip the title from a proj4js definition │ │ │ │ │ + */ │ │ │ │ │ + titleRegEx: /\+title=[^\+]*/, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Projection │ │ │ │ │ + * This class offers several methods for interacting with a wrapped │ │ │ │ │ + * pro4js projection object. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * geometry - {} │ │ │ │ │ + * projCode - {String} A string identifying the Well Known Identifier for │ │ │ │ │ + * the projection. │ │ │ │ │ + * options - {Object} An optional object to set additional properties │ │ │ │ │ + * on the projection. │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Boolean} The input geometry intersects this geometry. │ │ │ │ │ + * {} A projection object. │ │ │ │ │ */ │ │ │ │ │ - intersects: function(geometry) { │ │ │ │ │ - var intersect = false; │ │ │ │ │ - var type = geometry.CLASS_NAME; │ │ │ │ │ - if (type == "OpenLayers.Geometry.LineString" || │ │ │ │ │ - type == "OpenLayers.Geometry.LinearRing" || │ │ │ │ │ - type == "OpenLayers.Geometry.Point") { │ │ │ │ │ - var segs1 = this.getSortedSegments(); │ │ │ │ │ - var segs2; │ │ │ │ │ - if (type == "OpenLayers.Geometry.Point") { │ │ │ │ │ - segs2 = [{ │ │ │ │ │ - x1: geometry.x, │ │ │ │ │ - y1: geometry.y, │ │ │ │ │ - x2: geometry.x, │ │ │ │ │ - y2: geometry.y │ │ │ │ │ - }]; │ │ │ │ │ - } else { │ │ │ │ │ - segs2 = geometry.getSortedSegments(); │ │ │ │ │ - } │ │ │ │ │ - var seg1, seg1x1, seg1x2, seg1y1, seg1y2, │ │ │ │ │ - seg2, seg2y1, seg2y2; │ │ │ │ │ - // sweep right │ │ │ │ │ - outer: for (var i = 0, len = segs1.length; i < len; ++i) { │ │ │ │ │ - seg1 = segs1[i]; │ │ │ │ │ - seg1x1 = seg1.x1; │ │ │ │ │ - seg1x2 = seg1.x2; │ │ │ │ │ - seg1y1 = seg1.y1; │ │ │ │ │ - seg1y2 = seg1.y2; │ │ │ │ │ - inner: for (var j = 0, jlen = segs2.length; j < jlen; ++j) { │ │ │ │ │ - seg2 = segs2[j]; │ │ │ │ │ - if (seg2.x1 > seg1x2) { │ │ │ │ │ - // seg1 still left of seg2 │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - if (seg2.x2 < seg1x1) { │ │ │ │ │ - // seg2 still left of seg1 │ │ │ │ │ - continue; │ │ │ │ │ - } │ │ │ │ │ - seg2y1 = seg2.y1; │ │ │ │ │ - seg2y2 = seg2.y2; │ │ │ │ │ - if (Math.min(seg2y1, seg2y2) > Math.max(seg1y1, seg1y2)) { │ │ │ │ │ - // seg2 above seg1 │ │ │ │ │ - continue; │ │ │ │ │ - } │ │ │ │ │ - if (Math.max(seg2y1, seg2y2) < Math.min(seg1y1, seg1y2)) { │ │ │ │ │ - // seg2 below seg1 │ │ │ │ │ - continue; │ │ │ │ │ - } │ │ │ │ │ - if (OpenLayers.Geometry.segmentsIntersect(seg1, seg2)) { │ │ │ │ │ - intersect = true; │ │ │ │ │ - break outer; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } else { │ │ │ │ │ - intersect = geometry.intersects(this); │ │ │ │ │ + initialize: function(projCode, options) { │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ + this.projCode = projCode; │ │ │ │ │ + if (typeof Proj4js == "object") { │ │ │ │ │ + this.proj = new Proj4js.Proj(projCode); │ │ │ │ │ } │ │ │ │ │ - return intersect; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: getSortedSegments │ │ │ │ │ + * APIMethod: getCode │ │ │ │ │ + * Get the string SRS code. │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Array} An array of segment objects. Segment objects have properties │ │ │ │ │ - * x1, y1, x2, and y2. The start point is represented by x1 and y1. │ │ │ │ │ - * The end point is represented by x2 and y2. Start and end are │ │ │ │ │ - * ordered so that x1 < x2. │ │ │ │ │ + * {String} The SRS code. │ │ │ │ │ */ │ │ │ │ │ - getSortedSegments: function() { │ │ │ │ │ - var numSeg = this.components.length - 1; │ │ │ │ │ - var segments = new Array(numSeg), │ │ │ │ │ - point1, point2; │ │ │ │ │ - for (var i = 0; i < numSeg; ++i) { │ │ │ │ │ - point1 = this.components[i]; │ │ │ │ │ - point2 = this.components[i + 1]; │ │ │ │ │ - if (point1.x < point2.x) { │ │ │ │ │ - segments[i] = { │ │ │ │ │ - x1: point1.x, │ │ │ │ │ - y1: point1.y, │ │ │ │ │ - x2: point2.x, │ │ │ │ │ - y2: point2.y │ │ │ │ │ - }; │ │ │ │ │ - } else { │ │ │ │ │ - segments[i] = { │ │ │ │ │ - x1: point2.x, │ │ │ │ │ - y1: point2.y, │ │ │ │ │ - x2: point1.x, │ │ │ │ │ - y2: point1.y │ │ │ │ │ - }; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - // more efficient to define this somewhere static │ │ │ │ │ - function byX1(seg1, seg2) { │ │ │ │ │ - return seg1.x1 - seg2.x1; │ │ │ │ │ - } │ │ │ │ │ - return segments.sort(byX1); │ │ │ │ │ + getCode: function() { │ │ │ │ │ + return this.proj ? this.proj.srsCode : this.projCode; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: splitWithSegment │ │ │ │ │ - * Split this geometry with the given segment. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * seg - {Object} An object with x1, y1, x2, and y2 properties referencing │ │ │ │ │ - * segment endpoint coordinates. │ │ │ │ │ - * options - {Object} Properties of this object will be used to determine │ │ │ │ │ - * how the split is conducted. │ │ │ │ │ + * APIMethod: getUnits │ │ │ │ │ + * Get the units string for the projection -- returns null if │ │ │ │ │ + * proj4js is not available. │ │ │ │ │ * │ │ │ │ │ - * Valid options: │ │ │ │ │ - * edge - {Boolean} Allow splitting when only edges intersect. Default is │ │ │ │ │ + * Returns: │ │ │ │ │ + * {String} The units abbreviation. │ │ │ │ │ + */ │ │ │ │ │ + getUnits: function() { │ │ │ │ │ + return this.proj ? this.proj.units : null; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: toString │ │ │ │ │ + * Convert projection to string (getCode wrapper). │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {String} The projection code. │ │ │ │ │ + */ │ │ │ │ │ + toString: function() { │ │ │ │ │ + return this.getCode(); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: equals │ │ │ │ │ + * Test equality of two projection instances. Determines equality based │ │ │ │ │ + * soley on the projection code. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The two projections are equivalent. │ │ │ │ │ + */ │ │ │ │ │ + equals: function(projection) { │ │ │ │ │ + var p = projection, │ │ │ │ │ + equals = false; │ │ │ │ │ + if (p) { │ │ │ │ │ + if (!(p instanceof OpenLayers.Projection)) { │ │ │ │ │ + p = new OpenLayers.Projection(p); │ │ │ │ │ + } │ │ │ │ │ + if ((typeof Proj4js == "object") && this.proj.defData && p.proj.defData) { │ │ │ │ │ + equals = this.proj.defData.replace(this.titleRegEx, "") == │ │ │ │ │ + p.proj.defData.replace(this.titleRegEx, ""); │ │ │ │ │ + } else if (p.getCode) { │ │ │ │ │ + var source = this.getCode(), │ │ │ │ │ + target = p.getCode(); │ │ │ │ │ + equals = source == target || │ │ │ │ │ + !!OpenLayers.Projection.transforms[source] && │ │ │ │ │ + OpenLayers.Projection.transforms[source][target] === │ │ │ │ │ + OpenLayers.Projection.nullTransform; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return equals; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /* Method: destroy │ │ │ │ │ + * Destroy projection object. │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + delete this.proj; │ │ │ │ │ + delete this.projCode; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Projection" │ │ │ │ │ +}); │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Property: transforms │ │ │ │ │ + * {Object} Transforms is an object, with from properties, each of which may │ │ │ │ │ + * have a to property. This allows you to define projections without │ │ │ │ │ + * requiring support for proj4js to be included. │ │ │ │ │ + * │ │ │ │ │ + * This object has keys which correspond to a 'source' projection object. The │ │ │ │ │ + * keys should be strings, corresponding to the projection.getCode() value. │ │ │ │ │ + * Each source projection object should have a set of destination projection │ │ │ │ │ + * keys included in the object. │ │ │ │ │ + * │ │ │ │ │ + * Each value in the destination object should be a transformation function, │ │ │ │ │ + * where the function is expected to be passed an object with a .x and a .y │ │ │ │ │ + * property. The function should return the object, with the .x and .y │ │ │ │ │ + * transformed according to the transformation function. │ │ │ │ │ + * │ │ │ │ │ + * Note - Properties on this object should not be set directly. To add a │ │ │ │ │ + * transform method to this object, use the method. For an │ │ │ │ │ + * example of usage, see the OpenLayers.Layer.SphericalMercator file. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Projection.transforms = {}; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * APIProperty: defaults │ │ │ │ │ + * {Object} Defaults for the SRS codes known to OpenLayers (currently │ │ │ │ │ + * EPSG:4326, CRS:84, urn:ogc:def:crs:EPSG:6.6:4326, EPSG:900913, EPSG:3857, │ │ │ │ │ + * EPSG:102113 and EPSG:102100). Keys are the SRS code, values are units, │ │ │ │ │ + * maxExtent (the validity extent for the SRS) and yx (true if this SRS is │ │ │ │ │ + * known to have a reverse axis order). │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Projection.defaults = { │ │ │ │ │ + "EPSG:4326": { │ │ │ │ │ + units: "degrees", │ │ │ │ │ + maxExtent: [-180, -90, 180, 90], │ │ │ │ │ + yx: true │ │ │ │ │ + }, │ │ │ │ │ + "CRS:84": { │ │ │ │ │ + units: "degrees", │ │ │ │ │ + maxExtent: [-180, -90, 180, 90] │ │ │ │ │ + }, │ │ │ │ │ + "EPSG:900913": { │ │ │ │ │ + units: "m", │ │ │ │ │ + maxExtent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34] │ │ │ │ │ + } │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * APIMethod: addTransform │ │ │ │ │ + * Set a custom transform method between two projections. Use this method in │ │ │ │ │ + * cases where the proj4js lib is not available or where custom projections │ │ │ │ │ + * need to be handled. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * from - {String} The code for the source projection │ │ │ │ │ + * to - {String} the code for the destination projection │ │ │ │ │ + * method - {Function} A function that takes a point as an argument and │ │ │ │ │ + * transforms that point from the source to the destination projection │ │ │ │ │ + * in place. The original point should be modified. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Projection.addTransform = function(from, to, method) { │ │ │ │ │ + if (method === OpenLayers.Projection.nullTransform) { │ │ │ │ │ + var defaults = OpenLayers.Projection.defaults[from]; │ │ │ │ │ + if (defaults && !OpenLayers.Projection.defaults[to]) { │ │ │ │ │ + OpenLayers.Projection.defaults[to] = defaults; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + if (!OpenLayers.Projection.transforms[from]) { │ │ │ │ │ + OpenLayers.Projection.transforms[from] = {}; │ │ │ │ │ + } │ │ │ │ │ + OpenLayers.Projection.transforms[from][to] = method; │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * APIMethod: transform │ │ │ │ │ + * Transform a point coordinate from one projection to another. Note that │ │ │ │ │ + * the input point is transformed in place. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * point - { | Object} An object with x and y │ │ │ │ │ + * properties representing coordinates in those dimensions. │ │ │ │ │ + * source - {OpenLayers.Projection} Source map coordinate system │ │ │ │ │ + * dest - {OpenLayers.Projection} Destination map coordinate system │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * point - {object} A transformed coordinate. The original point is modified. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Projection.transform = function(point, source, dest) { │ │ │ │ │ + if (source && dest) { │ │ │ │ │ + if (!(source instanceof OpenLayers.Projection)) { │ │ │ │ │ + source = new OpenLayers.Projection(source); │ │ │ │ │ + } │ │ │ │ │ + if (!(dest instanceof OpenLayers.Projection)) { │ │ │ │ │ + dest = new OpenLayers.Projection(dest); │ │ │ │ │ + } │ │ │ │ │ + if (source.proj && dest.proj) { │ │ │ │ │ + point = Proj4js.transform(source.proj, dest.proj, point); │ │ │ │ │ + } else { │ │ │ │ │ + var sourceCode = source.getCode(); │ │ │ │ │ + var destCode = dest.getCode(); │ │ │ │ │ + var transforms = OpenLayers.Projection.transforms; │ │ │ │ │ + if (transforms[sourceCode] && transforms[sourceCode][destCode]) { │ │ │ │ │ + transforms[sourceCode][destCode](point); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return point; │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * APIFunction: nullTransform │ │ │ │ │ + * A null transformation - useful for defining projection aliases when │ │ │ │ │ + * proj4js is not available: │ │ │ │ │ + * │ │ │ │ │ + * (code) │ │ │ │ │ + * OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:900913", │ │ │ │ │ + * OpenLayers.Projection.nullTransform); │ │ │ │ │ + * OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:3857", │ │ │ │ │ + * OpenLayers.Projection.nullTransform); │ │ │ │ │ + * (end) │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Projection.nullTransform = function(point) { │ │ │ │ │ + return point; │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Note: Transforms for web mercator <-> geographic │ │ │ │ │ + * OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113 and EPSG:102100. │ │ │ │ │ + * OpenLayers originally started referring to EPSG:900913 as web mercator. │ │ │ │ │ + * The EPSG has declared EPSG:3857 to be web mercator. │ │ │ │ │ + * ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as │ │ │ │ │ + * 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. │ │ │ │ │ + * For geographic, OpenLayers recognizes EPSG:4326, CRS:84 and │ │ │ │ │ + * urn:ogc:def:crs:EPSG:6.6:4326. OpenLayers also knows about the reverse axis │ │ │ │ │ + * order for EPSG:4326. │ │ │ │ │ + */ │ │ │ │ │ +(function() { │ │ │ │ │ + │ │ │ │ │ + var pole = 20037508.34; │ │ │ │ │ + │ │ │ │ │ + function inverseMercator(xy) { │ │ │ │ │ + xy.x = 180 * xy.x / pole; │ │ │ │ │ + xy.y = 180 / Math.PI * (2 * Math.atan(Math.exp((xy.y / pole) * Math.PI)) - Math.PI / 2); │ │ │ │ │ + return xy; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + function forwardMercator(xy) { │ │ │ │ │ + xy.x = xy.x * pole / 180; │ │ │ │ │ + var y = Math.log(Math.tan((90 + xy.y) * Math.PI / 360)) / Math.PI * pole; │ │ │ │ │ + xy.y = Math.max(-20037508.34, Math.min(y, 20037508.34)); │ │ │ │ │ + return xy; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + function map(base, codes) { │ │ │ │ │ + var add = OpenLayers.Projection.addTransform; │ │ │ │ │ + var same = OpenLayers.Projection.nullTransform; │ │ │ │ │ + var i, len, code, other, j; │ │ │ │ │ + for (i = 0, len = codes.length; i < len; ++i) { │ │ │ │ │ + code = codes[i]; │ │ │ │ │ + add(base, code, forwardMercator); │ │ │ │ │ + add(code, base, inverseMercator); │ │ │ │ │ + for (j = i + 1; j < len; ++j) { │ │ │ │ │ + other = codes[j]; │ │ │ │ │ + add(code, other, same); │ │ │ │ │ + add(other, code, same); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // list of equivalent codes for web mercator │ │ │ │ │ + var mercator = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"], │ │ │ │ │ + geographic = ["CRS:84", "urn:ogc:def:crs:EPSG:6.6:4326", "EPSG:4326"], │ │ │ │ │ + i; │ │ │ │ │ + for (i = mercator.length - 1; i >= 0; --i) { │ │ │ │ │ + map(mercator[i], geographic); │ │ │ │ │ + } │ │ │ │ │ + for (i = geographic.length - 1; i >= 0; --i) { │ │ │ │ │ + map(geographic[i], mercator); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ +})(); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Events.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Util.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Namespace: OpenLayers.Event │ │ │ │ │ + * Utility functions for event handling. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Event = { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: observers │ │ │ │ │ + * {Object} A hashtable cache of the event observers. Keyed by │ │ │ │ │ + * element._eventCacheID │ │ │ │ │ + */ │ │ │ │ │ + observers: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: KEY_SPACE │ │ │ │ │ + * {int} │ │ │ │ │ + */ │ │ │ │ │ + KEY_SPACE: 32, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: KEY_BACKSPACE │ │ │ │ │ + * {int} │ │ │ │ │ + */ │ │ │ │ │ + KEY_BACKSPACE: 8, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: KEY_TAB │ │ │ │ │ + * {int} │ │ │ │ │ + */ │ │ │ │ │ + KEY_TAB: 9, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: KEY_RETURN │ │ │ │ │ + * {int} │ │ │ │ │ + */ │ │ │ │ │ + KEY_RETURN: 13, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: KEY_ESC │ │ │ │ │ + * {int} │ │ │ │ │ + */ │ │ │ │ │ + KEY_ESC: 27, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: KEY_LEFT │ │ │ │ │ + * {int} │ │ │ │ │ + */ │ │ │ │ │ + KEY_LEFT: 37, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: KEY_UP │ │ │ │ │ + * {int} │ │ │ │ │ + */ │ │ │ │ │ + KEY_UP: 38, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: KEY_RIGHT │ │ │ │ │ + * {int} │ │ │ │ │ + */ │ │ │ │ │ + KEY_RIGHT: 39, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: KEY_DOWN │ │ │ │ │ + * {int} │ │ │ │ │ + */ │ │ │ │ │ + KEY_DOWN: 40, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: KEY_DELETE │ │ │ │ │ + * {int} │ │ │ │ │ + */ │ │ │ │ │ + KEY_DELETE: 46, │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: element │ │ │ │ │ + * Cross browser event element detection. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * event - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {DOMElement} The element that caused the event │ │ │ │ │ + */ │ │ │ │ │ + element: function(event) { │ │ │ │ │ + return event.target || event.srcElement; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: isSingleTouch │ │ │ │ │ + * Determine whether event was caused by a single touch │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * event - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + isSingleTouch: function(event) { │ │ │ │ │ + return event.touches && event.touches.length == 1; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: isMultiTouch │ │ │ │ │ + * Determine whether event was caused by a multi touch │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * event - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + isMultiTouch: function(event) { │ │ │ │ │ + return event.touches && event.touches.length > 1; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: isLeftClick │ │ │ │ │ + * Determine whether event was caused by a left click. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * event - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + isLeftClick: function(event) { │ │ │ │ │ + return (((event.which) && (event.which == 1)) || │ │ │ │ │ + ((event.button) && (event.button == 1))); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: isRightClick │ │ │ │ │ + * Determine whether event was caused by a right mouse click. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * event - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + isRightClick: function(event) { │ │ │ │ │ + return (((event.which) && (event.which == 3)) || │ │ │ │ │ + ((event.button) && (event.button == 2))); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: stop │ │ │ │ │ + * Stops an event from propagating. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * event - {Event} │ │ │ │ │ + * allowDefault - {Boolean} If true, we stop the event chain but │ │ │ │ │ + * still allow the default browser behaviour (text selection, │ │ │ │ │ + * radio-button clicking, etc). Default is false. │ │ │ │ │ + */ │ │ │ │ │ + stop: function(event, allowDefault) { │ │ │ │ │ + │ │ │ │ │ + if (!allowDefault) { │ │ │ │ │ + OpenLayers.Event.preventDefault(event); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + if (event.stopPropagation) { │ │ │ │ │ + event.stopPropagation(); │ │ │ │ │ + } else { │ │ │ │ │ + event.cancelBubble = true; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: preventDefault │ │ │ │ │ + * Cancels the event if it is cancelable, without stopping further │ │ │ │ │ + * propagation of the event. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * event - {Event} │ │ │ │ │ + */ │ │ │ │ │ + preventDefault: function(event) { │ │ │ │ │ + if (event.preventDefault) { │ │ │ │ │ + event.preventDefault(); │ │ │ │ │ + } else { │ │ │ │ │ + event.returnValue = false; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: findElement │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * event - {Event} │ │ │ │ │ + * tagName - {String} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {DOMElement} The first node with the given tagName, starting from the │ │ │ │ │ + * node the event was triggered on and traversing the DOM upwards │ │ │ │ │ + */ │ │ │ │ │ + findElement: function(event, tagName) { │ │ │ │ │ + var element = OpenLayers.Event.element(event); │ │ │ │ │ + while (element.parentNode && (!element.tagName || │ │ │ │ │ + (element.tagName.toUpperCase() != tagName.toUpperCase()))) { │ │ │ │ │ + element = element.parentNode; │ │ │ │ │ + } │ │ │ │ │ + return element; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: observe │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * elementParam - {DOMElement || String} │ │ │ │ │ + * name - {String} │ │ │ │ │ + * observer - {function} │ │ │ │ │ + * useCapture - {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + observe: function(elementParam, name, observer, useCapture) { │ │ │ │ │ + var element = OpenLayers.Util.getElement(elementParam); │ │ │ │ │ + useCapture = useCapture || false; │ │ │ │ │ + │ │ │ │ │ + if (name == 'keypress' && │ │ │ │ │ + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || │ │ │ │ │ + element.attachEvent)) { │ │ │ │ │ + name = 'keydown'; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + //if observers cache has not yet been created, create it │ │ │ │ │ + if (!this.observers) { │ │ │ │ │ + this.observers = {}; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + //if not already assigned, make a new unique cache ID │ │ │ │ │ + if (!element._eventCacheID) { │ │ │ │ │ + var idPrefix = "eventCacheID_"; │ │ │ │ │ + if (element.id) { │ │ │ │ │ + idPrefix = element.id + "_" + idPrefix; │ │ │ │ │ + } │ │ │ │ │ + element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + var cacheID = element._eventCacheID; │ │ │ │ │ + │ │ │ │ │ + //if there is not yet a hash entry for this element, add one │ │ │ │ │ + if (!this.observers[cacheID]) { │ │ │ │ │ + this.observers[cacheID] = []; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + //add a new observer to this element's list │ │ │ │ │ + this.observers[cacheID].push({ │ │ │ │ │ + 'element': element, │ │ │ │ │ + 'name': name, │ │ │ │ │ + 'observer': observer, │ │ │ │ │ + 'useCapture': useCapture │ │ │ │ │ + }); │ │ │ │ │ + │ │ │ │ │ + //add the actual browser event listener │ │ │ │ │ + if (element.addEventListener) { │ │ │ │ │ + element.addEventListener(name, observer, useCapture); │ │ │ │ │ + } else if (element.attachEvent) { │ │ │ │ │ + element.attachEvent('on' + name, observer); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: stopObservingElement │ │ │ │ │ + * Given the id of an element to stop observing, cycle through the │ │ │ │ │ + * element's cached observers, calling stopObserving on each one, │ │ │ │ │ + * skipping those entries which can no longer be removed. │ │ │ │ │ + * │ │ │ │ │ + * parameters: │ │ │ │ │ + * elementParam - {DOMElement || String} │ │ │ │ │ + */ │ │ │ │ │ + stopObservingElement: function(elementParam) { │ │ │ │ │ + var element = OpenLayers.Util.getElement(elementParam); │ │ │ │ │ + var cacheID = element._eventCacheID; │ │ │ │ │ + │ │ │ │ │ + this._removeElementObservers(OpenLayers.Event.observers[cacheID]); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: _removeElementObservers │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * elementObservers - {Array(Object)} Array of (element, name, │ │ │ │ │ + * observer, usecapture) objects, │ │ │ │ │ + * taken directly from hashtable │ │ │ │ │ + */ │ │ │ │ │ + _removeElementObservers: function(elementObservers) { │ │ │ │ │ + if (elementObservers) { │ │ │ │ │ + for (var i = elementObservers.length - 1; i >= 0; i--) { │ │ │ │ │ + var entry = elementObservers[i]; │ │ │ │ │ + OpenLayers.Event.stopObserving.apply(this, [ │ │ │ │ │ + entry.element, entry.name, entry.observer, entry.useCapture │ │ │ │ │ + ]); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: stopObserving │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * elementParam - {DOMElement || String} │ │ │ │ │ + * name - {String} │ │ │ │ │ + * observer - {function} │ │ │ │ │ + * useCapture - {Boolean} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Whether or not the event observer was removed │ │ │ │ │ + */ │ │ │ │ │ + stopObserving: function(elementParam, name, observer, useCapture) { │ │ │ │ │ + useCapture = useCapture || false; │ │ │ │ │ + │ │ │ │ │ + var element = OpenLayers.Util.getElement(elementParam); │ │ │ │ │ + var cacheID = element._eventCacheID; │ │ │ │ │ + │ │ │ │ │ + if (name == 'keypress') { │ │ │ │ │ + if (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || │ │ │ │ │ + element.detachEvent) { │ │ │ │ │ + name = 'keydown'; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // find element's entry in this.observers cache and remove it │ │ │ │ │ + var foundEntry = false; │ │ │ │ │ + var elementObservers = OpenLayers.Event.observers[cacheID]; │ │ │ │ │ + if (elementObservers) { │ │ │ │ │ + │ │ │ │ │ + // find the specific event type in the element's list │ │ │ │ │ + var i = 0; │ │ │ │ │ + while (!foundEntry && i < elementObservers.length) { │ │ │ │ │ + var cacheEntry = elementObservers[i]; │ │ │ │ │ + │ │ │ │ │ + if ((cacheEntry.name == name) && │ │ │ │ │ + (cacheEntry.observer == observer) && │ │ │ │ │ + (cacheEntry.useCapture == useCapture)) { │ │ │ │ │ + │ │ │ │ │ + elementObservers.splice(i, 1); │ │ │ │ │ + if (elementObservers.length == 0) { │ │ │ │ │ + delete OpenLayers.Event.observers[cacheID]; │ │ │ │ │ + } │ │ │ │ │ + foundEntry = true; │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + i++; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + //actually remove the event listener from browser │ │ │ │ │ + if (foundEntry) { │ │ │ │ │ + if (element.removeEventListener) { │ │ │ │ │ + element.removeEventListener(name, observer, useCapture); │ │ │ │ │ + } else if (element && element.detachEvent) { │ │ │ │ │ + element.detachEvent('on' + name, observer); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return foundEntry; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: unloadCache │ │ │ │ │ + * Cycle through all the element entries in the events cache and call │ │ │ │ │ + * stopObservingElement on each. │ │ │ │ │ + */ │ │ │ │ │ + unloadCache: function() { │ │ │ │ │ + // check for OpenLayers.Event before checking for observers, because │ │ │ │ │ + // OpenLayers.Event may be undefined in IE if no map instance was │ │ │ │ │ + // created │ │ │ │ │ + if (OpenLayers.Event && OpenLayers.Event.observers) { │ │ │ │ │ + for (var cacheID in OpenLayers.Event.observers) { │ │ │ │ │ + var elementObservers = OpenLayers.Event.observers[cacheID]; │ │ │ │ │ + OpenLayers.Event._removeElementObservers.apply(this, │ │ │ │ │ + [elementObservers]); │ │ │ │ │ + } │ │ │ │ │ + OpenLayers.Event.observers = false; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Event" │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ +/* prevent memory leaks in IE */ │ │ │ │ │ +OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false); │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Events │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Events = OpenLayers.Class({ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: BROWSER_EVENTS │ │ │ │ │ + * {Array(String)} supported events │ │ │ │ │ + */ │ │ │ │ │ + BROWSER_EVENTS: [ │ │ │ │ │ + "mouseover", "mouseout", │ │ │ │ │ + "mousedown", "mouseup", "mousemove", │ │ │ │ │ + "click", "dblclick", "rightclick", "dblrightclick", │ │ │ │ │ + "resize", "focus", "blur", │ │ │ │ │ + "touchstart", "touchmove", "touchend", │ │ │ │ │ + "keydown" │ │ │ │ │ + ], │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: listeners │ │ │ │ │ + * {Object} Hashtable of Array(Function): events listener functions │ │ │ │ │ + */ │ │ │ │ │ + listeners: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: object │ │ │ │ │ + * {Object} the code object issuing application events │ │ │ │ │ + */ │ │ │ │ │ + object: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: element │ │ │ │ │ + * {DOMElement} the DOM element receiving browser events │ │ │ │ │ + */ │ │ │ │ │ + element: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: eventHandler │ │ │ │ │ + * {Function} bound event handler attached to elements │ │ │ │ │ + */ │ │ │ │ │ + eventHandler: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: fallThrough │ │ │ │ │ + * {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + fallThrough: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: includeXY │ │ │ │ │ + * {Boolean} Should the .xy property automatically be created for browser │ │ │ │ │ + * mouse events? In general, this should be false. If it is true, then │ │ │ │ │ + * mouse events will automatically generate a '.xy' property on the │ │ │ │ │ + * event object that is passed. (Prior to OpenLayers 2.7, this was true │ │ │ │ │ + * by default.) Otherwise, you can call the getMousePosition on the │ │ │ │ │ + * relevant events handler on the object available via the 'evt.object' │ │ │ │ │ + * property of the evt object. So, for most events, you can call: │ │ │ │ │ + * function named(evt) { │ │ │ │ │ + * this.xy = this.object.events.getMousePosition(evt) │ │ │ │ │ + * } │ │ │ │ │ + * │ │ │ │ │ + * This option typically defaults to false for performance reasons: │ │ │ │ │ + * when creating an events object whose primary purpose is to manage │ │ │ │ │ + * relatively positioned mouse events within a div, it may make │ │ │ │ │ + * sense to set it to true. │ │ │ │ │ + * │ │ │ │ │ + * This option is also used to control whether the events object caches │ │ │ │ │ + * offsets. If this is false, it will not: the reason for this is that │ │ │ │ │ + * it is only expected to be called many times if the includeXY property │ │ │ │ │ + * is set to true. If you set this to true, you are expected to clear │ │ │ │ │ + * the offset cache manually (using this.clearMouseCache()) if: │ │ │ │ │ + * the border of the element changes │ │ │ │ │ + * the location of the element in the page changes │ │ │ │ │ + */ │ │ │ │ │ + includeXY: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: extensions │ │ │ │ │ + * {Object} Event extensions registered with this instance. Keys are │ │ │ │ │ + * event types, values are {OpenLayers.Events.*} extension instances or │ │ │ │ │ + * {Boolean} for events that an instantiated extension provides in │ │ │ │ │ + * addition to the one it was created for. │ │ │ │ │ + * │ │ │ │ │ + * Extensions create an event in addition to browser events, which usually │ │ │ │ │ + * fires when a sequence of browser events is completed. Extensions are │ │ │ │ │ + * automatically instantiated when a listener is registered for an event │ │ │ │ │ + * provided by an extension. │ │ │ │ │ + * │ │ │ │ │ + * Extensions are created in the namespace using │ │ │ │ │ + * , and named after the event they provide. │ │ │ │ │ + * The constructor receives the target instance as │ │ │ │ │ + * argument. Extensions that need to capture browser events before they │ │ │ │ │ + * propagate can register their listeners events using , with │ │ │ │ │ + * {extension: true} as 4th argument. │ │ │ │ │ + * │ │ │ │ │ + * If an extension creates more than one event, an alias for each event │ │ │ │ │ + * type should be created and reference the same class. The constructor │ │ │ │ │ + * should set a reference in the target's extensions registry to itself. │ │ │ │ │ + * │ │ │ │ │ + * Below is a minimal extension that provides the "foostart" and "fooend" │ │ │ │ │ + * event types, which replace the native "click" event type if clicked on │ │ │ │ │ + * an element with the css class "foo": │ │ │ │ │ + * │ │ │ │ │ + * (code) │ │ │ │ │ + * OpenLayers.Events.foostart = OpenLayers.Class({ │ │ │ │ │ + * initialize: function(target) { │ │ │ │ │ + * this.target = target; │ │ │ │ │ + * this.target.register("click", this, this.doStuff, {extension: true}); │ │ │ │ │ + * // only required if extension provides more than one event type │ │ │ │ │ + * this.target.extensions["foostart"] = true; │ │ │ │ │ + * this.target.extensions["fooend"] = true; │ │ │ │ │ + * }, │ │ │ │ │ + * destroy: function() { │ │ │ │ │ + * var target = this.target; │ │ │ │ │ + * target.unregister("click", this, this.doStuff); │ │ │ │ │ + * delete this.target; │ │ │ │ │ + * // only required if extension provides more than one event type │ │ │ │ │ + * delete target.extensions["foostart"]; │ │ │ │ │ + * delete target.extensions["fooend"]; │ │ │ │ │ + * }, │ │ │ │ │ + * doStuff: function(evt) { │ │ │ │ │ + * var propagate = true; │ │ │ │ │ + * if (OpenLayers.Event.element(evt).className === "foo") { │ │ │ │ │ + * propagate = false; │ │ │ │ │ + * var target = this.target; │ │ │ │ │ + * target.triggerEvent("foostart"); │ │ │ │ │ + * window.setTimeout(function() { │ │ │ │ │ + * target.triggerEvent("fooend"); │ │ │ │ │ + * }, 1000); │ │ │ │ │ + * } │ │ │ │ │ + * return propagate; │ │ │ │ │ + * } │ │ │ │ │ + * }); │ │ │ │ │ + * // only required if extension provides more than one event type │ │ │ │ │ + * OpenLayers.Events.fooend = OpenLayers.Events.foostart; │ │ │ │ │ + * (end) │ │ │ │ │ + * │ │ │ │ │ + */ │ │ │ │ │ + extensions: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: extensionCount │ │ │ │ │ + * {Object} Keys are event types (like in ), values are the │ │ │ │ │ + * number of extension listeners for each event type. │ │ │ │ │ + */ │ │ │ │ │ + extensionCount: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: clearMouseListener │ │ │ │ │ + * A version of that is bound to this instance so that │ │ │ │ │ + * it can be used with and │ │ │ │ │ + * . │ │ │ │ │ + */ │ │ │ │ │ + clearMouseListener: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Events │ │ │ │ │ + * Construct an OpenLayers.Events object. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} The js object to which this Events object is being added │ │ │ │ │ + * element - {DOMElement} A dom element to respond to browser events │ │ │ │ │ + * eventTypes - {Array(String)} Deprecated. Array of custom application │ │ │ │ │ + * events. A listener may be registered for any named event, regardless │ │ │ │ │ + * of the values provided here. │ │ │ │ │ + * fallThrough - {Boolean} Allow events to fall through after these have │ │ │ │ │ + * been handled? │ │ │ │ │ + * options - {Object} Options for the events object. │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(object, element, eventTypes, fallThrough, options) { │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ + this.object = object; │ │ │ │ │ + this.fallThrough = fallThrough; │ │ │ │ │ + this.listeners = {}; │ │ │ │ │ + this.extensions = {}; │ │ │ │ │ + this.extensionCount = {}; │ │ │ │ │ + this._msTouches = []; │ │ │ │ │ + │ │ │ │ │ + // if a dom element is specified, add a listeners list │ │ │ │ │ + // for browser events on the element and register them │ │ │ │ │ + if (element != null) { │ │ │ │ │ + this.attachToElement(element); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: destroy │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + for (var e in this.extensions) { │ │ │ │ │ + if (typeof this.extensions[e] !== "boolean") { │ │ │ │ │ + this.extensions[e].destroy(); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + this.extensions = null; │ │ │ │ │ + if (this.element) { │ │ │ │ │ + OpenLayers.Event.stopObservingElement(this.element); │ │ │ │ │ + if (this.element.hasScrollEvent) { │ │ │ │ │ + OpenLayers.Event.stopObserving( │ │ │ │ │ + window, "scroll", this.clearMouseListener │ │ │ │ │ + ); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + this.element = null; │ │ │ │ │ + │ │ │ │ │ + this.listeners = null; │ │ │ │ │ + this.object = null; │ │ │ │ │ + this.fallThrough = null; │ │ │ │ │ + this.eventHandler = null; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: addEventType │ │ │ │ │ + * Deprecated. Any event can be triggered without adding it first. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * eventName - {String} │ │ │ │ │ + */ │ │ │ │ │ + addEventType: function(eventName) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: attachToElement │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {HTMLDOMElement} a DOM element to attach browser events to │ │ │ │ │ + */ │ │ │ │ │ + attachToElement: function(element) { │ │ │ │ │ + if (this.element) { │ │ │ │ │ + OpenLayers.Event.stopObservingElement(this.element); │ │ │ │ │ + } else { │ │ │ │ │ + // keep a bound copy of handleBrowserEvent() so that we can │ │ │ │ │ + // pass the same function to both Event.observe() and .stopObserving() │ │ │ │ │ + this.eventHandler = OpenLayers.Function.bindAsEventListener( │ │ │ │ │ + this.handleBrowserEvent, this │ │ │ │ │ + ); │ │ │ │ │ + │ │ │ │ │ + // to be used with observe and stopObserving │ │ │ │ │ + this.clearMouseListener = OpenLayers.Function.bind( │ │ │ │ │ + this.clearMouseCache, this │ │ │ │ │ + ); │ │ │ │ │ + } │ │ │ │ │ + this.element = element; │ │ │ │ │ + var msTouch = !!window.navigator.msMaxTouchPoints; │ │ │ │ │ + var type; │ │ │ │ │ + for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) { │ │ │ │ │ + type = this.BROWSER_EVENTS[i]; │ │ │ │ │ + // register the event cross-browser │ │ │ │ │ + OpenLayers.Event.observe(element, type, this.eventHandler); │ │ │ │ │ + if (msTouch && type.indexOf('touch') === 0) { │ │ │ │ │ + this.addMsTouchListener(element, type, this.eventHandler); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + // disable dragstart in IE so that mousedown/move/up works normally │ │ │ │ │ + OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: on │ │ │ │ │ + * Convenience method for registering listeners with a common scope. │ │ │ │ │ + * Internally, this method calls as shown in the examples │ │ │ │ │ + * below. │ │ │ │ │ + * │ │ │ │ │ + * Example use: │ │ │ │ │ + * (code) │ │ │ │ │ + * // register a single listener for the "loadstart" event │ │ │ │ │ + * events.on({"loadstart": loadStartListener}); │ │ │ │ │ + * │ │ │ │ │ + * // this is equivalent to the following │ │ │ │ │ + * events.register("loadstart", undefined, loadStartListener); │ │ │ │ │ + * │ │ │ │ │ + * // register multiple listeners to be called with the same `this` object │ │ │ │ │ + * events.on({ │ │ │ │ │ + * "loadstart": loadStartListener, │ │ │ │ │ + * "loadend": loadEndListener, │ │ │ │ │ + * scope: object │ │ │ │ │ + * }); │ │ │ │ │ + * │ │ │ │ │ + * // this is equivalent to the following │ │ │ │ │ + * events.register("loadstart", object, loadStartListener); │ │ │ │ │ + * events.register("loadend", object, loadEndListener); │ │ │ │ │ + * (end) │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} │ │ │ │ │ + */ │ │ │ │ │ + on: function(object) { │ │ │ │ │ + for (var type in object) { │ │ │ │ │ + if (type != "scope" && object.hasOwnProperty(type)) { │ │ │ │ │ + this.register(type, object.scope, object[type]); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: register │ │ │ │ │ + * Register an event on the events object. │ │ │ │ │ + * │ │ │ │ │ + * When the event is triggered, the 'func' function will be called, in the │ │ │ │ │ + * context of 'obj'. Imagine we were to register an event, specifying an │ │ │ │ │ + * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the │ │ │ │ │ + * context in the callback function will be our Bounds object. This means │ │ │ │ │ + * that within our callback function, we can access the properties and │ │ │ │ │ + * methods of the Bounds object through the "this" variable. So our │ │ │ │ │ + * callback could execute something like: │ │ │ │ │ + * : leftStr = "Left: " + this.left; │ │ │ │ │ + * │ │ │ │ │ + * or │ │ │ │ │ + * │ │ │ │ │ + * : centerStr = "Center: " + this.getCenterLonLat(); │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * type - {String} Name of the event to register │ │ │ │ │ + * obj - {Object} The object to bind the context to for the callback#. │ │ │ │ │ + * If no object is specified, default is the Events's 'object' property. │ │ │ │ │ + * func - {Function} The callback function. If no callback is │ │ │ │ │ + * specified, this function does nothing. │ │ │ │ │ + * priority - {Boolean|Object} If true, adds the new listener to the │ │ │ │ │ + * *front* of the events queue instead of to the end. │ │ │ │ │ + * │ │ │ │ │ + * Valid options for priority: │ │ │ │ │ + * extension - {Boolean} If true, then the event will be registered as │ │ │ │ │ + * extension event. Extension events are handled before all other │ │ │ │ │ + * events. │ │ │ │ │ + */ │ │ │ │ │ + register: function(type, obj, func, priority) { │ │ │ │ │ + if (type in OpenLayers.Events && !this.extensions[type]) { │ │ │ │ │ + this.extensions[type] = new OpenLayers.Events[type](this); │ │ │ │ │ + } │ │ │ │ │ + if (func != null) { │ │ │ │ │ + if (obj == null) { │ │ │ │ │ + obj = this.object; │ │ │ │ │ + } │ │ │ │ │ + var listeners = this.listeners[type]; │ │ │ │ │ + if (!listeners) { │ │ │ │ │ + listeners = []; │ │ │ │ │ + this.listeners[type] = listeners; │ │ │ │ │ + this.extensionCount[type] = 0; │ │ │ │ │ + } │ │ │ │ │ + var listener = { │ │ │ │ │ + obj: obj, │ │ │ │ │ + func: func │ │ │ │ │ + }; │ │ │ │ │ + if (priority) { │ │ │ │ │ + listeners.splice(this.extensionCount[type], 0, listener); │ │ │ │ │ + if (typeof priority === "object" && priority.extension) { │ │ │ │ │ + this.extensionCount[type]++; │ │ │ │ │ + } │ │ │ │ │ + } else { │ │ │ │ │ + listeners.push(listener); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: registerPriority │ │ │ │ │ + * Same as register() but adds the new listener to the *front* of the │ │ │ │ │ + * events queue instead of to the end. │ │ │ │ │ + * │ │ │ │ │ + * TODO: get rid of this in 3.0 - Decide whether listeners should be │ │ │ │ │ + * called in the order they were registered or in reverse order. │ │ │ │ │ + * │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * type - {String} Name of the event to register │ │ │ │ │ + * obj - {Object} The object to bind the context to for the callback#. │ │ │ │ │ + * If no object is specified, default is the Events's │ │ │ │ │ + * 'object' property. │ │ │ │ │ + * func - {Function} The callback function. If no callback is │ │ │ │ │ + * specified, this function does nothing. │ │ │ │ │ + */ │ │ │ │ │ + registerPriority: function(type, obj, func) { │ │ │ │ │ + this.register(type, obj, func, true); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: un │ │ │ │ │ + * Convenience method for unregistering listeners with a common scope. │ │ │ │ │ + * Internally, this method calls as shown in the examples │ │ │ │ │ + * below. │ │ │ │ │ + * │ │ │ │ │ + * Example use: │ │ │ │ │ + * (code) │ │ │ │ │ + * // unregister a single listener for the "loadstart" event │ │ │ │ │ + * events.un({"loadstart": loadStartListener}); │ │ │ │ │ + * │ │ │ │ │ + * // this is equivalent to the following │ │ │ │ │ + * events.unregister("loadstart", undefined, loadStartListener); │ │ │ │ │ + * │ │ │ │ │ + * // unregister multiple listeners with the same `this` object │ │ │ │ │ + * events.un({ │ │ │ │ │ + * "loadstart": loadStartListener, │ │ │ │ │ + * "loadend": loadEndListener, │ │ │ │ │ + * scope: object │ │ │ │ │ + * }); │ │ │ │ │ + * │ │ │ │ │ + * // this is equivalent to the following │ │ │ │ │ + * events.unregister("loadstart", object, loadStartListener); │ │ │ │ │ + * events.unregister("loadend", object, loadEndListener); │ │ │ │ │ + * (end) │ │ │ │ │ + */ │ │ │ │ │ + un: function(object) { │ │ │ │ │ + for (var type in object) { │ │ │ │ │ + if (type != "scope" && object.hasOwnProperty(type)) { │ │ │ │ │ + this.unregister(type, object.scope, object[type]); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: unregister │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * type - {String} │ │ │ │ │ + * obj - {Object} If none specified, defaults to this.object │ │ │ │ │ + * func - {Function} │ │ │ │ │ + */ │ │ │ │ │ + unregister: function(type, obj, func) { │ │ │ │ │ + if (obj == null) { │ │ │ │ │ + obj = this.object; │ │ │ │ │ + } │ │ │ │ │ + var listeners = this.listeners[type]; │ │ │ │ │ + if (listeners != null) { │ │ │ │ │ + for (var i = 0, len = listeners.length; i < len; i++) { │ │ │ │ │ + if (listeners[i].obj == obj && listeners[i].func == func) { │ │ │ │ │ + listeners.splice(i, 1); │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: remove │ │ │ │ │ + * Remove all listeners for a given event type. If type is not registered, │ │ │ │ │ + * does nothing. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * type - {String} │ │ │ │ │ + */ │ │ │ │ │ + remove: function(type) { │ │ │ │ │ + if (this.listeners[type] != null) { │ │ │ │ │ + this.listeners[type] = []; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: triggerEvent │ │ │ │ │ + * Trigger a specified registered event. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * type - {String} │ │ │ │ │ + * evt - {Event || Object} will be passed to the listeners. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The last listener return. If a listener returns false, the │ │ │ │ │ + * chain of listeners will stop getting called. │ │ │ │ │ + */ │ │ │ │ │ + triggerEvent: function(type, evt) { │ │ │ │ │ + var listeners = this.listeners[type]; │ │ │ │ │ + │ │ │ │ │ + // fast path │ │ │ │ │ + if (!listeners || listeners.length == 0) { │ │ │ │ │ + return undefined; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // prep evt object with object & div references │ │ │ │ │ + if (evt == null) { │ │ │ │ │ + evt = {}; │ │ │ │ │ + } │ │ │ │ │ + evt.object = this.object; │ │ │ │ │ + evt.element = this.element; │ │ │ │ │ + if (!evt.type) { │ │ │ │ │ + evt.type = type; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // execute all callbacks registered for specified type │ │ │ │ │ + // get a clone of the listeners array to │ │ │ │ │ + // allow for splicing during callbacks │ │ │ │ │ + listeners = listeners.slice(); │ │ │ │ │ + var continueChain; │ │ │ │ │ + for (var i = 0, len = listeners.length; i < len; i++) { │ │ │ │ │ + var callback = listeners[i]; │ │ │ │ │ + // bind the context to callback.obj │ │ │ │ │ + continueChain = callback.func.apply(callback.obj, [evt]); │ │ │ │ │ + │ │ │ │ │ + if ((continueChain != undefined) && (continueChain == false)) { │ │ │ │ │ + // if callback returns false, execute no more callbacks. │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + // don't fall through to other DOM elements │ │ │ │ │ + if (!this.fallThrough) { │ │ │ │ │ + OpenLayers.Event.stop(evt, true); │ │ │ │ │ + } │ │ │ │ │ + return continueChain; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: handleBrowserEvent │ │ │ │ │ + * Basically just a wrapper to the triggerEvent() function, but takes │ │ │ │ │ + * care to set a property 'xy' on the event with the current mouse │ │ │ │ │ + * position. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} │ │ │ │ │ + */ │ │ │ │ │ + handleBrowserEvent: function(evt) { │ │ │ │ │ + var type = evt.type, │ │ │ │ │ + listeners = this.listeners[type]; │ │ │ │ │ + if (!listeners || listeners.length == 0) { │ │ │ │ │ + // noone's listening, bail out │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + // add clientX & clientY to all events - corresponds to average x, y │ │ │ │ │ + var touches = evt.touches; │ │ │ │ │ + if (touches && touches[0]) { │ │ │ │ │ + var x = 0; │ │ │ │ │ + var y = 0; │ │ │ │ │ + var num = touches.length; │ │ │ │ │ + var touch; │ │ │ │ │ + for (var i = 0; i < num; ++i) { │ │ │ │ │ + touch = this.getTouchClientXY(touches[i]); │ │ │ │ │ + x += touch.clientX; │ │ │ │ │ + y += touch.clientY; │ │ │ │ │ + } │ │ │ │ │ + evt.clientX = x / num; │ │ │ │ │ + evt.clientY = y / num; │ │ │ │ │ + } │ │ │ │ │ + if (this.includeXY) { │ │ │ │ │ + evt.xy = this.getMousePosition(evt); │ │ │ │ │ + } │ │ │ │ │ + this.triggerEvent(type, evt); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: getTouchClientXY │ │ │ │ │ + * WebKit has a few bugs for clientX/clientY. This method detects them │ │ │ │ │ + * and calculate the correct values. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Touch} a Touch object from a TouchEvent │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Object} An object with only clientX and clientY properties with the │ │ │ │ │ + * calculated values. │ │ │ │ │ + */ │ │ │ │ │ + getTouchClientXY: function(evt) { │ │ │ │ │ + // olMochWin is to override window, used for testing │ │ │ │ │ + var win = window.olMockWin || window, │ │ │ │ │ + winPageX = win.pageXOffset, │ │ │ │ │ + winPageY = win.pageYOffset, │ │ │ │ │ + x = evt.clientX, │ │ │ │ │ + y = evt.clientY; │ │ │ │ │ + │ │ │ │ │ + if (evt.pageY === 0 && Math.floor(y) > Math.floor(evt.pageY) || │ │ │ │ │ + evt.pageX === 0 && Math.floor(x) > Math.floor(evt.pageX)) { │ │ │ │ │ + // iOS4 include scroll offset in clientX/Y │ │ │ │ │ + x = x - winPageX; │ │ │ │ │ + y = y - winPageY; │ │ │ │ │ + } else if (y < (evt.pageY - winPageY) || x < (evt.pageX - winPageX)) { │ │ │ │ │ + // Some Android browsers have totally bogus values for clientX/Y │ │ │ │ │ + // when scrolling/zooming a page │ │ │ │ │ + x = evt.pageX - winPageX; │ │ │ │ │ + y = evt.pageY - winPageY; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + evt.olClientX = x; │ │ │ │ │ + evt.olClientY = y; │ │ │ │ │ + │ │ │ │ │ + return { │ │ │ │ │ + clientX: x, │ │ │ │ │ + clientY: y │ │ │ │ │ + }; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: clearMouseCache │ │ │ │ │ + * Clear cached data about the mouse position. This should be called any │ │ │ │ │ + * time the element that events are registered on changes position │ │ │ │ │ + * within the page. │ │ │ │ │ + */ │ │ │ │ │ + clearMouseCache: function() { │ │ │ │ │ + this.element.scrolls = null; │ │ │ │ │ + this.element.lefttop = null; │ │ │ │ │ + this.element.offsets = null; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: getMousePosition │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} The current xy coordinate of the mouse, adjusted │ │ │ │ │ + * for offsets │ │ │ │ │ + */ │ │ │ │ │ + getMousePosition: function(evt) { │ │ │ │ │ + if (!this.includeXY) { │ │ │ │ │ + this.clearMouseCache(); │ │ │ │ │ + } else if (!this.element.hasScrollEvent) { │ │ │ │ │ + OpenLayers.Event.observe(window, "scroll", this.clearMouseListener); │ │ │ │ │ + this.element.hasScrollEvent = true; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + if (!this.element.scrolls) { │ │ │ │ │ + var viewportElement = OpenLayers.Util.getViewportElement(); │ │ │ │ │ + this.element.scrolls = [ │ │ │ │ │ + window.pageXOffset || viewportElement.scrollLeft, │ │ │ │ │ + window.pageYOffset || viewportElement.scrollTop │ │ │ │ │ + ]; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + if (!this.element.lefttop) { │ │ │ │ │ + this.element.lefttop = [ │ │ │ │ │ + (document.documentElement.clientLeft || 0), │ │ │ │ │ + (document.documentElement.clientTop || 0) │ │ │ │ │ + ]; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + if (!this.element.offsets) { │ │ │ │ │ + this.element.offsets = OpenLayers.Util.pagePosition(this.element); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + return new OpenLayers.Pixel( │ │ │ │ │ + (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0] - │ │ │ │ │ + this.element.lefttop[0], │ │ │ │ │ + (evt.clientY + this.element.scrolls[1]) - this.element.offsets[1] - │ │ │ │ │ + this.element.lefttop[1] │ │ │ │ │ + ); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: addMsTouchListener │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} The DOM element to register the listener on │ │ │ │ │ + * type - {String} The event type │ │ │ │ │ + * handler - {Function} the handler │ │ │ │ │ + */ │ │ │ │ │ + addMsTouchListener: function(element, type, handler) { │ │ │ │ │ + var eventHandler = this.eventHandler; │ │ │ │ │ + var touches = this._msTouches; │ │ │ │ │ + │ │ │ │ │ + function msHandler(evt) { │ │ │ │ │ + handler(OpenLayers.Util.applyDefaults({ │ │ │ │ │ + stopPropagation: function() { │ │ │ │ │ + for (var i = touches.length - 1; i >= 0; --i) { │ │ │ │ │ + touches[i].stopPropagation(); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + preventDefault: function() { │ │ │ │ │ + for (var i = touches.length - 1; i >= 0; --i) { │ │ │ │ │ + touches[i].preventDefault(); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + type: type │ │ │ │ │ + }, evt)); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + switch (type) { │ │ │ │ │ + case 'touchstart': │ │ │ │ │ + return this.addMsTouchListenerStart(element, type, msHandler); │ │ │ │ │ + case 'touchend': │ │ │ │ │ + return this.addMsTouchListenerEnd(element, type, msHandler); │ │ │ │ │ + case 'touchmove': │ │ │ │ │ + return this.addMsTouchListenerMove(element, type, msHandler); │ │ │ │ │ + default: │ │ │ │ │ + throw 'Unknown touch event type'; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: addMsTouchListenerStart │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} The DOM element to register the listener on │ │ │ │ │ + * type - {String} The event type │ │ │ │ │ + * handler - {Function} the handler │ │ │ │ │ + */ │ │ │ │ │ + addMsTouchListenerStart: function(element, type, handler) { │ │ │ │ │ + var touches = this._msTouches; │ │ │ │ │ + │ │ │ │ │ + var cb = function(e) { │ │ │ │ │ + │ │ │ │ │ + var alreadyInArray = false; │ │ │ │ │ + for (var i = 0, ii = touches.length; i < ii; ++i) { │ │ │ │ │ + if (touches[i].pointerId == e.pointerId) { │ │ │ │ │ + alreadyInArray = true; │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + if (!alreadyInArray) { │ │ │ │ │ + touches.push(e); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + e.touches = touches.slice(); │ │ │ │ │ + handler(e); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + OpenLayers.Event.observe(element, 'MSPointerDown', cb); │ │ │ │ │ + │ │ │ │ │ + // Need to also listen for end events to keep the _msTouches list │ │ │ │ │ + // accurate │ │ │ │ │ + var internalCb = function(e) { │ │ │ │ │ + for (var i = 0, ii = touches.length; i < ii; ++i) { │ │ │ │ │ + if (touches[i].pointerId == e.pointerId) { │ │ │ │ │ + touches.splice(i, 1); │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }; │ │ │ │ │ + OpenLayers.Event.observe(element, 'MSPointerUp', internalCb); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: addMsTouchListenerMove │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} The DOM element to register the listener on │ │ │ │ │ + * type - {String} The event type │ │ │ │ │ + * handler - {Function} the handler │ │ │ │ │ + */ │ │ │ │ │ + addMsTouchListenerMove: function(element, type, handler) { │ │ │ │ │ + var touches = this._msTouches; │ │ │ │ │ + var cb = function(e) { │ │ │ │ │ + │ │ │ │ │ + //Don't fire touch moves when mouse isn't down │ │ │ │ │ + if (e.pointerType == e.MSPOINTER_TYPE_MOUSE && e.buttons == 0) { │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + if (touches.length == 1 && touches[0].pageX == e.pageX && │ │ │ │ │ + touches[0].pageY == e.pageY) { │ │ │ │ │ + // don't trigger event when pointer has not moved │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + for (var i = 0, ii = touches.length; i < ii; ++i) { │ │ │ │ │ + if (touches[i].pointerId == e.pointerId) { │ │ │ │ │ + touches[i] = e; │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + e.touches = touches.slice(); │ │ │ │ │ + handler(e); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + OpenLayers.Event.observe(element, 'MSPointerMove', cb); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: addMsTouchListenerEnd │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * element - {DOMElement} The DOM element to register the listener on │ │ │ │ │ + * type - {String} The event type │ │ │ │ │ + * handler - {Function} the handler │ │ │ │ │ + */ │ │ │ │ │ + addMsTouchListenerEnd: function(element, type, handler) { │ │ │ │ │ + var touches = this._msTouches; │ │ │ │ │ + │ │ │ │ │ + var cb = function(e) { │ │ │ │ │ + │ │ │ │ │ + for (var i = 0, ii = touches.length; i < ii; ++i) { │ │ │ │ │ + if (touches[i].pointerId == e.pointerId) { │ │ │ │ │ + touches.splice(i, 1); │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + e.touches = touches.slice(); │ │ │ │ │ + handler(e); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + OpenLayers.Event.observe(element, 'MSPointerUp', cb); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Events" │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Request/XMLHttpRequest.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +// XMLHttpRequest.js Copyright (C) 2010 Sergey Ilinsky (http://www.ilinsky.com) │ │ │ │ │ +// │ │ │ │ │ +// Licensed under the Apache License, Version 2.0 (the "License"); │ │ │ │ │ +// you may not use this file except in compliance with the License. │ │ │ │ │ +// You may obtain a copy of the License at │ │ │ │ │ +// │ │ │ │ │ +// http://www.apache.org/licenses/LICENSE-2.0 │ │ │ │ │ +// │ │ │ │ │ +// Unless required by applicable law or agreed to in writing, software │ │ │ │ │ +// distributed under the License is distributed on an "AS IS" BASIS, │ │ │ │ │ +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ │ │ │ │ +// See the License for the specific language governing permissions and │ │ │ │ │ +// limitations under the License. │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Request.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +(function() { │ │ │ │ │ + │ │ │ │ │ + // Save reference to earlier defined object implementation (if any) │ │ │ │ │ + var oXMLHttpRequest = window.XMLHttpRequest; │ │ │ │ │ + │ │ │ │ │ + // Define on browser type │ │ │ │ │ + var bGecko = !!window.controllers, │ │ │ │ │ + bIE = window.document.all && !window.opera, │ │ │ │ │ + bIE7 = bIE && window.navigator.userAgent.match(/MSIE 7.0/); │ │ │ │ │ + │ │ │ │ │ + // Enables "XMLHttpRequest()" call next to "new XMLHttpReques()" │ │ │ │ │ + function fXMLHttpRequest() { │ │ │ │ │ + this._object = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP"); │ │ │ │ │ + this._listeners = []; │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + // Constructor │ │ │ │ │ + function cXMLHttpRequest() { │ │ │ │ │ + return new fXMLHttpRequest; │ │ │ │ │ + }; │ │ │ │ │ + cXMLHttpRequest.prototype = fXMLHttpRequest.prototype; │ │ │ │ │ + │ │ │ │ │ + // BUGFIX: Firefox with Firebug installed would break pages if not executed │ │ │ │ │ + if (bGecko && oXMLHttpRequest.wrapped) │ │ │ │ │ + cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped; │ │ │ │ │ + │ │ │ │ │ + // Constants │ │ │ │ │ + cXMLHttpRequest.UNSENT = 0; │ │ │ │ │ + cXMLHttpRequest.OPENED = 1; │ │ │ │ │ + cXMLHttpRequest.HEADERS_RECEIVED = 2; │ │ │ │ │ + cXMLHttpRequest.LOADING = 3; │ │ │ │ │ + cXMLHttpRequest.DONE = 4; │ │ │ │ │ + │ │ │ │ │ + // Public Properties │ │ │ │ │ + cXMLHttpRequest.prototype.readyState = cXMLHttpRequest.UNSENT; │ │ │ │ │ + cXMLHttpRequest.prototype.responseText = ''; │ │ │ │ │ + cXMLHttpRequest.prototype.responseXML = null; │ │ │ │ │ + cXMLHttpRequest.prototype.status = 0; │ │ │ │ │ + cXMLHttpRequest.prototype.statusText = ''; │ │ │ │ │ + │ │ │ │ │ + // Priority proposal │ │ │ │ │ + cXMLHttpRequest.prototype.priority = "NORMAL"; │ │ │ │ │ + │ │ │ │ │ + // Instance-level Events Handlers │ │ │ │ │ + cXMLHttpRequest.prototype.onreadystatechange = null; │ │ │ │ │ + │ │ │ │ │ + // Class-level Events Handlers │ │ │ │ │ + cXMLHttpRequest.onreadystatechange = null; │ │ │ │ │ + cXMLHttpRequest.onopen = null; │ │ │ │ │ + cXMLHttpRequest.onsend = null; │ │ │ │ │ + cXMLHttpRequest.onabort = null; │ │ │ │ │ + │ │ │ │ │ + // Public Methods │ │ │ │ │ + cXMLHttpRequest.prototype.open = function(sMethod, sUrl, bAsync, sUser, sPassword) { │ │ │ │ │ + // Delete headers, required when object is reused │ │ │ │ │ + delete this._headers; │ │ │ │ │ + │ │ │ │ │ + // When bAsync parameter value is omitted, use true as default │ │ │ │ │ + if (arguments.length < 3) │ │ │ │ │ + bAsync = true; │ │ │ │ │ + │ │ │ │ │ + // Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests │ │ │ │ │ + this._async = bAsync; │ │ │ │ │ + │ │ │ │ │ + // Set the onreadystatechange handler │ │ │ │ │ + var oRequest = this, │ │ │ │ │ + nState = this.readyState, │ │ │ │ │ + fOnUnload; │ │ │ │ │ + │ │ │ │ │ + // BUGFIX: IE - memory leak on page unload (inter-page leak) │ │ │ │ │ + if (bIE && bAsync) { │ │ │ │ │ + fOnUnload = function() { │ │ │ │ │ + if (nState != cXMLHttpRequest.DONE) { │ │ │ │ │ + fCleanTransport(oRequest); │ │ │ │ │ + // Safe to abort here since onreadystatechange handler removed │ │ │ │ │ + oRequest.abort(); │ │ │ │ │ + } │ │ │ │ │ + }; │ │ │ │ │ + window.attachEvent("onunload", fOnUnload); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // Add method sniffer │ │ │ │ │ + if (cXMLHttpRequest.onopen) │ │ │ │ │ + cXMLHttpRequest.onopen.apply(this, arguments); │ │ │ │ │ + │ │ │ │ │ + if (arguments.length > 4) │ │ │ │ │ + this._object.open(sMethod, sUrl, bAsync, sUser, sPassword); │ │ │ │ │ + else │ │ │ │ │ + if (arguments.length > 3) │ │ │ │ │ + this._object.open(sMethod, sUrl, bAsync, sUser); │ │ │ │ │ + else │ │ │ │ │ + this._object.open(sMethod, sUrl, bAsync); │ │ │ │ │ + │ │ │ │ │ + this.readyState = cXMLHttpRequest.OPENED; │ │ │ │ │ + fReadyStateChange(this); │ │ │ │ │ + │ │ │ │ │ + this._object.onreadystatechange = function() { │ │ │ │ │ + if (bGecko && !bAsync) │ │ │ │ │ + return; │ │ │ │ │ + │ │ │ │ │ + // Synchronize state │ │ │ │ │ + oRequest.readyState = oRequest._object.readyState; │ │ │ │ │ + │ │ │ │ │ + // │ │ │ │ │ + fSynchronizeValues(oRequest); │ │ │ │ │ + │ │ │ │ │ + // BUGFIX: Firefox fires unnecessary DONE when aborting │ │ │ │ │ + if (oRequest._aborted) { │ │ │ │ │ + // Reset readyState to UNSENT │ │ │ │ │ + oRequest.readyState = cXMLHttpRequest.UNSENT; │ │ │ │ │ + │ │ │ │ │ + // Return now │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + if (oRequest.readyState == cXMLHttpRequest.DONE) { │ │ │ │ │ + // Free up queue │ │ │ │ │ + delete oRequest._data; │ │ │ │ │ + /* if (bAsync) │ │ │ │ │ + fQueue_remove(oRequest);*/ │ │ │ │ │ + // │ │ │ │ │ + fCleanTransport(oRequest); │ │ │ │ │ + // Uncomment this block if you need a fix for IE cache │ │ │ │ │ + /* │ │ │ │ │ + // BUGFIX: IE - cache issue │ │ │ │ │ + if (!oRequest._object.getResponseHeader("Date")) { │ │ │ │ │ + // Save object to cache │ │ │ │ │ + oRequest._cached = oRequest._object; │ │ │ │ │ + │ │ │ │ │ + // Instantiate a new transport object │ │ │ │ │ + cXMLHttpRequest.call(oRequest); │ │ │ │ │ + │ │ │ │ │ + // Re-send request │ │ │ │ │ + if (sUser) { │ │ │ │ │ + if (sPassword) │ │ │ │ │ + oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword); │ │ │ │ │ + else │ │ │ │ │ + oRequest._object.open(sMethod, sUrl, bAsync, sUser); │ │ │ │ │ + } │ │ │ │ │ + else │ │ │ │ │ + oRequest._object.open(sMethod, sUrl, bAsync); │ │ │ │ │ + oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified") || new window.Date(0)); │ │ │ │ │ + // Copy headers set │ │ │ │ │ + if (oRequest._headers) │ │ │ │ │ + for (var sHeader in oRequest._headers) │ │ │ │ │ + if (typeof oRequest._headers[sHeader] == "string") // Some frameworks prototype objects with functions │ │ │ │ │ + oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]); │ │ │ │ │ + │ │ │ │ │ + oRequest._object.onreadystatechange = function() { │ │ │ │ │ + // Synchronize state │ │ │ │ │ + oRequest.readyState = oRequest._object.readyState; │ │ │ │ │ + │ │ │ │ │ + if (oRequest._aborted) { │ │ │ │ │ + // │ │ │ │ │ + oRequest.readyState = cXMLHttpRequest.UNSENT; │ │ │ │ │ + │ │ │ │ │ + // Return │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + if (oRequest.readyState == cXMLHttpRequest.DONE) { │ │ │ │ │ + // Clean Object │ │ │ │ │ + fCleanTransport(oRequest); │ │ │ │ │ + │ │ │ │ │ + // get cached request │ │ │ │ │ + if (oRequest.status == 304) │ │ │ │ │ + oRequest._object = oRequest._cached; │ │ │ │ │ + │ │ │ │ │ + // │ │ │ │ │ + delete oRequest._cached; │ │ │ │ │ + │ │ │ │ │ + // │ │ │ │ │ + fSynchronizeValues(oRequest); │ │ │ │ │ + │ │ │ │ │ + // │ │ │ │ │ + fReadyStateChange(oRequest); │ │ │ │ │ + │ │ │ │ │ + // BUGFIX: IE - memory leak in interrupted │ │ │ │ │ + if (bIE && bAsync) │ │ │ │ │ + window.detachEvent("onunload", fOnUnload); │ │ │ │ │ + } │ │ │ │ │ + }; │ │ │ │ │ + oRequest._object.send(null); │ │ │ │ │ + │ │ │ │ │ + // Return now - wait until re-sent request is finished │ │ │ │ │ + return; │ │ │ │ │ + }; │ │ │ │ │ + */ │ │ │ │ │ + // BUGFIX: IE - memory leak in interrupted │ │ │ │ │ + if (bIE && bAsync) │ │ │ │ │ + window.detachEvent("onunload", fOnUnload); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice │ │ │ │ │ + if (nState != oRequest.readyState) │ │ │ │ │ + fReadyStateChange(oRequest); │ │ │ │ │ + │ │ │ │ │ + nState = oRequest.readyState; │ │ │ │ │ + } │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + function fXMLHttpRequest_send(oRequest) { │ │ │ │ │ + oRequest._object.send(oRequest._data); │ │ │ │ │ + │ │ │ │ │ + // BUGFIX: Gecko - missing readystatechange calls in synchronous requests │ │ │ │ │ + if (bGecko && !oRequest._async) { │ │ │ │ │ + oRequest.readyState = cXMLHttpRequest.OPENED; │ │ │ │ │ + │ │ │ │ │ + // Synchronize state │ │ │ │ │ + fSynchronizeValues(oRequest); │ │ │ │ │ + │ │ │ │ │ + // Simulate missing states │ │ │ │ │ + while (oRequest.readyState < cXMLHttpRequest.DONE) { │ │ │ │ │ + oRequest.readyState++; │ │ │ │ │ + fReadyStateChange(oRequest); │ │ │ │ │ + // Check if we are aborted │ │ │ │ │ + if (oRequest._aborted) │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }; │ │ │ │ │ + cXMLHttpRequest.prototype.send = function(vData) { │ │ │ │ │ + // Add method sniffer │ │ │ │ │ + if (cXMLHttpRequest.onsend) │ │ │ │ │ + cXMLHttpRequest.onsend.apply(this, arguments); │ │ │ │ │ + │ │ │ │ │ + if (!arguments.length) │ │ │ │ │ + vData = null; │ │ │ │ │ + │ │ │ │ │ + // BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required │ │ │ │ │ + // BUGFIX: IE - rewrites any custom mime-type to "text/xml" in case an XMLNode is sent │ │ │ │ │ + // BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard) │ │ │ │ │ + if (vData && vData.nodeType) { │ │ │ │ │ + vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml; │ │ │ │ │ + if (!this._headers["Content-Type"]) │ │ │ │ │ + this._object.setRequestHeader("Content-Type", "application/xml"); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + this._data = vData; │ │ │ │ │ + /* │ │ │ │ │ + // Add to queue │ │ │ │ │ + if (this._async) │ │ │ │ │ + fQueue_add(this); │ │ │ │ │ + else*/ │ │ │ │ │ + fXMLHttpRequest_send(this); │ │ │ │ │ + }; │ │ │ │ │ + cXMLHttpRequest.prototype.abort = function() { │ │ │ │ │ + // Add method sniffer │ │ │ │ │ + if (cXMLHttpRequest.onabort) │ │ │ │ │ + cXMLHttpRequest.onabort.apply(this, arguments); │ │ │ │ │ + │ │ │ │ │ + // BUGFIX: Gecko - unnecessary DONE when aborting │ │ │ │ │ + if (this.readyState > cXMLHttpRequest.UNSENT) │ │ │ │ │ + this._aborted = true; │ │ │ │ │ + │ │ │ │ │ + this._object.abort(); │ │ │ │ │ + │ │ │ │ │ + // BUGFIX: IE - memory leak │ │ │ │ │ + fCleanTransport(this); │ │ │ │ │ + │ │ │ │ │ + this.readyState = cXMLHttpRequest.UNSENT; │ │ │ │ │ + │ │ │ │ │ + delete this._data; │ │ │ │ │ + /* if (this._async) │ │ │ │ │ + fQueue_remove(this);*/ │ │ │ │ │ + }; │ │ │ │ │ + cXMLHttpRequest.prototype.getAllResponseHeaders = function() { │ │ │ │ │ + return this._object.getAllResponseHeaders(); │ │ │ │ │ + }; │ │ │ │ │ + cXMLHttpRequest.prototype.getResponseHeader = function(sName) { │ │ │ │ │ + return this._object.getResponseHeader(sName); │ │ │ │ │ + }; │ │ │ │ │ + cXMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) { │ │ │ │ │ + // BUGFIX: IE - cache issue │ │ │ │ │ + if (!this._headers) │ │ │ │ │ + this._headers = {}; │ │ │ │ │ + this._headers[sName] = sValue; │ │ │ │ │ + │ │ │ │ │ + return this._object.setRequestHeader(sName, sValue); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + // EventTarget interface implementation │ │ │ │ │ + cXMLHttpRequest.prototype.addEventListener = function(sName, fHandler, bUseCapture) { │ │ │ │ │ + for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) │ │ │ │ │ + if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture) │ │ │ │ │ + return; │ │ │ │ │ + // Add listener │ │ │ │ │ + this._listeners.push([sName, fHandler, bUseCapture]); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + cXMLHttpRequest.prototype.removeEventListener = function(sName, fHandler, bUseCapture) { │ │ │ │ │ + for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) │ │ │ │ │ + if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture) │ │ │ │ │ + break; │ │ │ │ │ + // Remove listener │ │ │ │ │ + if (oListener) │ │ │ │ │ + this._listeners.splice(nIndex, 1); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + cXMLHttpRequest.prototype.dispatchEvent = function(oEvent) { │ │ │ │ │ + var oEventPseudo = { │ │ │ │ │ + 'type': oEvent.type, │ │ │ │ │ + 'target': this, │ │ │ │ │ + 'currentTarget': this, │ │ │ │ │ + 'eventPhase': 2, │ │ │ │ │ + 'bubbles': oEvent.bubbles, │ │ │ │ │ + 'cancelable': oEvent.cancelable, │ │ │ │ │ + 'timeStamp': oEvent.timeStamp, │ │ │ │ │ + 'stopPropagation': function() {}, // There is no flow │ │ │ │ │ + 'preventDefault': function() {}, // There is no default action │ │ │ │ │ + 'initEvent': function() {} // Original event object should be initialized │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + // Execute onreadystatechange │ │ │ │ │ + if (oEventPseudo.type == "readystatechange" && this.onreadystatechange) │ │ │ │ │ + (this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]); │ │ │ │ │ + │ │ │ │ │ + // Execute listeners │ │ │ │ │ + for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) │ │ │ │ │ + if (oListener[0] == oEventPseudo.type && !oListener[2]) │ │ │ │ │ + (oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + // │ │ │ │ │ + cXMLHttpRequest.prototype.toString = function() { │ │ │ │ │ + return '[' + "object" + ' ' + "XMLHttpRequest" + ']'; │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + cXMLHttpRequest.toString = function() { │ │ │ │ │ + return '[' + "XMLHttpRequest" + ']'; │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + // Helper function │ │ │ │ │ + function fReadyStateChange(oRequest) { │ │ │ │ │ + // Sniffing code │ │ │ │ │ + if (cXMLHttpRequest.onreadystatechange) │ │ │ │ │ + cXMLHttpRequest.onreadystatechange.apply(oRequest); │ │ │ │ │ + │ │ │ │ │ + // Fake event │ │ │ │ │ + oRequest.dispatchEvent({ │ │ │ │ │ + 'type': "readystatechange", │ │ │ │ │ + 'bubbles': false, │ │ │ │ │ + 'cancelable': false, │ │ │ │ │ + 'timeStamp': new Date + 0 │ │ │ │ │ + }); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + function fGetDocument(oRequest) { │ │ │ │ │ + var oDocument = oRequest.responseXML, │ │ │ │ │ + sResponse = oRequest.responseText; │ │ │ │ │ + // Try parsing responseText │ │ │ │ │ + if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) { │ │ │ │ │ + oDocument = new window.ActiveXObject("Microsoft.XMLDOM"); │ │ │ │ │ + oDocument.async = false; │ │ │ │ │ + oDocument.validateOnParse = false; │ │ │ │ │ + oDocument.loadXML(sResponse); │ │ │ │ │ + } │ │ │ │ │ + // Check if there is no error in document │ │ │ │ │ + if (oDocument) │ │ │ │ │ + if ((bIE && oDocument.parseError != 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror")) │ │ │ │ │ + return null; │ │ │ │ │ + return oDocument; │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + function fSynchronizeValues(oRequest) { │ │ │ │ │ + try { │ │ │ │ │ + oRequest.responseText = oRequest._object.responseText; │ │ │ │ │ + } catch (e) {} │ │ │ │ │ + try { │ │ │ │ │ + oRequest.responseXML = fGetDocument(oRequest._object); │ │ │ │ │ + } catch (e) {} │ │ │ │ │ + try { │ │ │ │ │ + oRequest.status = oRequest._object.status; │ │ │ │ │ + } catch (e) {} │ │ │ │ │ + try { │ │ │ │ │ + oRequest.statusText = oRequest._object.statusText; │ │ │ │ │ + } catch (e) {} │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + function fCleanTransport(oRequest) { │ │ │ │ │ + // BUGFIX: IE - memory leak (on-page leak) │ │ │ │ │ + oRequest._object.onreadystatechange = new window.Function; │ │ │ │ │ + }; │ │ │ │ │ + /* │ │ │ │ │ + // Queue manager │ │ │ │ │ + var oQueuePending = {"CRITICAL":[],"HIGH":[],"NORMAL":[],"LOW":[],"LOWEST":[]}, │ │ │ │ │ + aQueueRunning = []; │ │ │ │ │ + function fQueue_add(oRequest) { │ │ │ │ │ + oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : "NORMAL"].push(oRequest); │ │ │ │ │ + // │ │ │ │ │ + setTimeout(fQueue_process); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + function fQueue_remove(oRequest) { │ │ │ │ │ + for (var nIndex = 0, bFound = false; nIndex < aQueueRunning.length; nIndex++) │ │ │ │ │ + if (bFound) │ │ │ │ │ + aQueueRunning[nIndex - 1] = aQueueRunning[nIndex]; │ │ │ │ │ + else │ │ │ │ │ + if (aQueueRunning[nIndex] == oRequest) │ │ │ │ │ + bFound = true; │ │ │ │ │ + if (bFound) │ │ │ │ │ + aQueueRunning.length--; │ │ │ │ │ + // │ │ │ │ │ + setTimeout(fQueue_process); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + function fQueue_process() { │ │ │ │ │ + if (aQueueRunning.length < 6) { │ │ │ │ │ + for (var sPriority in oQueuePending) { │ │ │ │ │ + if (oQueuePending[sPriority].length) { │ │ │ │ │ + var oRequest = oQueuePending[sPriority][0]; │ │ │ │ │ + oQueuePending[sPriority] = oQueuePending[sPriority].slice(1); │ │ │ │ │ + // │ │ │ │ │ + aQueueRunning.push(oRequest); │ │ │ │ │ + // Send request │ │ │ │ │ + fXMLHttpRequest_send(oRequest); │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }; │ │ │ │ │ + */ │ │ │ │ │ + // Internet Explorer 5.0 (missing apply) │ │ │ │ │ + if (!window.Function.prototype.apply) { │ │ │ │ │ + window.Function.prototype.apply = function(oRequest, oArguments) { │ │ │ │ │ + if (!oArguments) │ │ │ │ │ + oArguments = []; │ │ │ │ │ + oRequest.__func = this; │ │ │ │ │ + oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]); │ │ │ │ │ + delete oRequest.__func; │ │ │ │ │ + }; │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + // Register new object with window │ │ │ │ │ + /** │ │ │ │ │ + * Class: OpenLayers.Request.XMLHttpRequest │ │ │ │ │ + * Standard-compliant (W3C) cross-browser implementation of the │ │ │ │ │ + * XMLHttpRequest object. From │ │ │ │ │ + * http://code.google.com/p/xmlhttprequest/. │ │ │ │ │ + */ │ │ │ │ │ + if (!OpenLayers.Request) { │ │ │ │ │ + /** │ │ │ │ │ + * This allows for OpenLayers/Request.js to be included │ │ │ │ │ + * before or after this script. │ │ │ │ │ + */ │ │ │ │ │ + OpenLayers.Request = {}; │ │ │ │ │ + } │ │ │ │ │ + OpenLayers.Request.XMLHttpRequest = cXMLHttpRequest; │ │ │ │ │ +})(); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Request.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Events.js │ │ │ │ │ + * @requires OpenLayers/Request/XMLHttpRequest.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * TODO: deprecate me │ │ │ │ │ + * Use OpenLayers.Request.proxy instead. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.ProxyHost = ""; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Namespace: OpenLayers.Request │ │ │ │ │ + * The OpenLayers.Request namespace contains convenience methods for working │ │ │ │ │ + * with XMLHttpRequests. These methods work with a cross-browser │ │ │ │ │ + * W3C compliant class. │ │ │ │ │ + */ │ │ │ │ │ +if (!OpenLayers.Request) { │ │ │ │ │ + /** │ │ │ │ │ + * This allows for OpenLayers/Request/XMLHttpRequest.js to be included │ │ │ │ │ + * before or after this script. │ │ │ │ │ + */ │ │ │ │ │ + OpenLayers.Request = {}; │ │ │ │ │ +} │ │ │ │ │ +OpenLayers.Util.extend(OpenLayers.Request, { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: DEFAULT_CONFIG │ │ │ │ │ + * {Object} Default configuration for all requests. │ │ │ │ │ + */ │ │ │ │ │ + DEFAULT_CONFIG: { │ │ │ │ │ + method: "GET", │ │ │ │ │ + url: window.location.href, │ │ │ │ │ + async: true, │ │ │ │ │ + user: undefined, │ │ │ │ │ + password: undefined, │ │ │ │ │ + params: null, │ │ │ │ │ + proxy: OpenLayers.ProxyHost, │ │ │ │ │ + headers: {}, │ │ │ │ │ + data: null, │ │ │ │ │ + callback: function() {}, │ │ │ │ │ + success: null, │ │ │ │ │ + failure: null, │ │ │ │ │ + scope: null │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: URL_SPLIT_REGEX │ │ │ │ │ + */ │ │ │ │ │ + URL_SPLIT_REGEX: /([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: events │ │ │ │ │ + * {} An events object that handles all │ │ │ │ │ + * events on the {} object. │ │ │ │ │ + * │ │ │ │ │ + * All event listeners will receive an event object with three properties: │ │ │ │ │ + * request - {} The request object. │ │ │ │ │ + * config - {Object} The config object sent to the specific request method. │ │ │ │ │ + * requestUrl - {String} The request url. │ │ │ │ │ + * │ │ │ │ │ + * Supported event types: │ │ │ │ │ + * complete - Triggered when we have a response from the request, if a │ │ │ │ │ + * listener returns false, no further response processing will take │ │ │ │ │ + * place. │ │ │ │ │ + * success - Triggered when the HTTP response has a success code (200-299). │ │ │ │ │ + * failure - Triggered when the HTTP response does not have a success code. │ │ │ │ │ + */ │ │ │ │ │ + events: new OpenLayers.Events(this), │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: makeSameOrigin │ │ │ │ │ + * Using the specified proxy, returns a same origin url of the provided url. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * url - {String} An arbitrary url │ │ │ │ │ + * proxy {String|Function} The proxy to use to make the provided url a │ │ │ │ │ + * same origin url. │ │ │ │ │ + * │ │ │ │ │ + * Returns │ │ │ │ │ + * {String} the same origin url. If no proxy is provided, the returned url │ │ │ │ │ + * will be the same as the provided url. │ │ │ │ │ + */ │ │ │ │ │ + makeSameOrigin: function(url, proxy) { │ │ │ │ │ + var sameOrigin = url.indexOf("http") !== 0; │ │ │ │ │ + var urlParts = !sameOrigin && url.match(this.URL_SPLIT_REGEX); │ │ │ │ │ + if (urlParts) { │ │ │ │ │ + var location = window.location; │ │ │ │ │ + sameOrigin = │ │ │ │ │ + urlParts[1] == location.protocol && │ │ │ │ │ + urlParts[3] == location.hostname; │ │ │ │ │ + var uPort = urlParts[4], │ │ │ │ │ + lPort = location.port; │ │ │ │ │ + if (uPort != 80 && uPort != "" || lPort != "80" && lPort != "") { │ │ │ │ │ + sameOrigin = sameOrigin && uPort == lPort; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + if (!sameOrigin) { │ │ │ │ │ + if (proxy) { │ │ │ │ │ + if (typeof proxy == "function") { │ │ │ │ │ + url = proxy(url); │ │ │ │ │ + } else { │ │ │ │ │ + url = proxy + encodeURIComponent(url); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return url; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: issue │ │ │ │ │ + * Create a new XMLHttpRequest object, open it, set any headers, bind │ │ │ │ │ + * a callback to done state, and send any data. It is recommended that │ │ │ │ │ + * you use one , , , , , or . │ │ │ │ │ + * This method is only documented to provide detail on the configuration │ │ │ │ │ + * options available to all request methods. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * config - {Object} Object containing properties for configuring the │ │ │ │ │ + * request. Allowed configuration properties are described below. │ │ │ │ │ + * This object is modified and should not be reused. │ │ │ │ │ + * │ │ │ │ │ + * Allowed config properties: │ │ │ │ │ + * method - {String} One of GET, POST, PUT, DELETE, HEAD, or │ │ │ │ │ + * OPTIONS. Default is GET. │ │ │ │ │ + * url - {String} URL for the request. │ │ │ │ │ + * async - {Boolean} Open an asynchronous request. Default is true. │ │ │ │ │ + * user - {String} User for relevant authentication scheme. Set │ │ │ │ │ + * to null to clear current user. │ │ │ │ │ + * password - {String} Password for relevant authentication scheme. │ │ │ │ │ + * Set to null to clear current password. │ │ │ │ │ + * proxy - {String} Optional proxy. Defaults to │ │ │ │ │ + * . │ │ │ │ │ + * params - {Object} Any key:value pairs to be appended to the │ │ │ │ │ + * url as a query string. Assumes url doesn't already include a query │ │ │ │ │ + * string or hash. Typically, this is only appropriate for │ │ │ │ │ + * requests where the query string will be appended to the url. │ │ │ │ │ + * Parameter values that are arrays will be │ │ │ │ │ + * concatenated with a comma (note that this goes against form-encoding) │ │ │ │ │ + * as is done with . │ │ │ │ │ + * headers - {Object} Object with header:value pairs to be set on │ │ │ │ │ + * the request. │ │ │ │ │ + * data - {String | Document} Optional data to send with the request. │ │ │ │ │ + * Typically, this is only used with and requests. │ │ │ │ │ + * Make sure to provide the appropriate "Content-Type" header for your │ │ │ │ │ + * data. For and requests, the content type defaults to │ │ │ │ │ + * "application-xml". If your data is a different content type, or │ │ │ │ │ + * if you are using a different HTTP method, set the "Content-Type" │ │ │ │ │ + * header to match your data type. │ │ │ │ │ + * callback - {Function} Function to call when request is done. │ │ │ │ │ + * To determine if the request failed, check request.status (200 │ │ │ │ │ + * indicates success). │ │ │ │ │ + * success - {Function} Optional function to call if request status is in │ │ │ │ │ + * the 200s. This will be called in addition to callback above and │ │ │ │ │ + * would typically only be used as an alternative. │ │ │ │ │ + * failure - {Function} Optional function to call if request status is not │ │ │ │ │ + * in the 200s. This will be called in addition to callback above and │ │ │ │ │ + * would typically only be used as an alternative. │ │ │ │ │ + * scope - {Object} If callback is a public method on some object, │ │ │ │ │ + * set the scope to that object. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {XMLHttpRequest} Request object. To abort the request before a response │ │ │ │ │ + * is received, call abort() on the request object. │ │ │ │ │ + */ │ │ │ │ │ + issue: function(config) { │ │ │ │ │ + // apply default config - proxy host may have changed │ │ │ │ │ + var defaultConfig = OpenLayers.Util.extend( │ │ │ │ │ + this.DEFAULT_CONFIG, { │ │ │ │ │ + proxy: OpenLayers.ProxyHost │ │ │ │ │ + } │ │ │ │ │ + ); │ │ │ │ │ + config = config || {}; │ │ │ │ │ + config.headers = config.headers || {}; │ │ │ │ │ + config = OpenLayers.Util.applyDefaults(config, defaultConfig); │ │ │ │ │ + config.headers = OpenLayers.Util.applyDefaults(config.headers, defaultConfig.headers); │ │ │ │ │ + // Always set the "X-Requested-With" header to signal that this request │ │ │ │ │ + // was issued through the XHR-object. Since header keys are case │ │ │ │ │ + // insensitive and we want to allow overriding of the "X-Requested-With" │ │ │ │ │ + // header through the user we cannot use applyDefaults, but have to │ │ │ │ │ + // check manually whether we were called with a "X-Requested-With" │ │ │ │ │ + // header. │ │ │ │ │ + var customRequestedWithHeader = false, │ │ │ │ │ + headerKey; │ │ │ │ │ + for (headerKey in config.headers) { │ │ │ │ │ + if (config.headers.hasOwnProperty(headerKey)) { │ │ │ │ │ + if (headerKey.toLowerCase() === 'x-requested-with') { │ │ │ │ │ + customRequestedWithHeader = true; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + if (customRequestedWithHeader === false) { │ │ │ │ │ + // we did not have a custom "X-Requested-With" header │ │ │ │ │ + config.headers['X-Requested-With'] = 'XMLHttpRequest'; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // create request, open, and set headers │ │ │ │ │ + var request = new OpenLayers.Request.XMLHttpRequest(); │ │ │ │ │ + var url = OpenLayers.Util.urlAppend(config.url, │ │ │ │ │ + OpenLayers.Util.getParameterString(config.params || {})); │ │ │ │ │ + url = OpenLayers.Request.makeSameOrigin(url, config.proxy); │ │ │ │ │ + request.open( │ │ │ │ │ + config.method, url, config.async, config.user, config.password │ │ │ │ │ + ); │ │ │ │ │ + for (var header in config.headers) { │ │ │ │ │ + request.setRequestHeader(header, config.headers[header]); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + var events = this.events; │ │ │ │ │ + │ │ │ │ │ + // we want to execute runCallbacks with "this" as the │ │ │ │ │ + // execution scope │ │ │ │ │ + var self = this; │ │ │ │ │ + │ │ │ │ │ + request.onreadystatechange = function() { │ │ │ │ │ + if (request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) { │ │ │ │ │ + var proceed = events.triggerEvent( │ │ │ │ │ + "complete", { │ │ │ │ │ + request: request, │ │ │ │ │ + config: config, │ │ │ │ │ + requestUrl: url │ │ │ │ │ + } │ │ │ │ │ + ); │ │ │ │ │ + if (proceed !== false) { │ │ │ │ │ + self.runCallbacks({ │ │ │ │ │ + request: request, │ │ │ │ │ + config: config, │ │ │ │ │ + requestUrl: url │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + // send request (optionally with data) and return │ │ │ │ │ + // call in a timeout for asynchronous requests so the return is │ │ │ │ │ + // available before readyState == 4 for cached docs │ │ │ │ │ + if (config.async === false) { │ │ │ │ │ + request.send(config.data); │ │ │ │ │ + } else { │ │ │ │ │ + window.setTimeout(function() { │ │ │ │ │ + if (request.readyState !== 0) { // W3C: 0-UNSENT │ │ │ │ │ + request.send(config.data); │ │ │ │ │ + } │ │ │ │ │ + }, 0); │ │ │ │ │ + } │ │ │ │ │ + return request; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: runCallbacks │ │ │ │ │ + * Calls the complete, success and failure callbacks. Application │ │ │ │ │ + * can listen to the "complete" event, have the listener │ │ │ │ │ + * display a confirm window and always return false, and │ │ │ │ │ + * execute OpenLayers.Request.runCallbacks if the user │ │ │ │ │ + * hits "yes" in the confirm window. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * options - {Object} Hash containing request, config and requestUrl keys │ │ │ │ │ + */ │ │ │ │ │ + runCallbacks: function(options) { │ │ │ │ │ + var request = options.request; │ │ │ │ │ + var config = options.config; │ │ │ │ │ + │ │ │ │ │ + // bind callbacks to readyState 4 (done) │ │ │ │ │ + var complete = (config.scope) ? │ │ │ │ │ + OpenLayers.Function.bind(config.callback, config.scope) : │ │ │ │ │ + config.callback; │ │ │ │ │ + │ │ │ │ │ + // optional success callback │ │ │ │ │ + var success; │ │ │ │ │ + if (config.success) { │ │ │ │ │ + success = (config.scope) ? │ │ │ │ │ + OpenLayers.Function.bind(config.success, config.scope) : │ │ │ │ │ + config.success; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // optional failure callback │ │ │ │ │ + var failure; │ │ │ │ │ + if (config.failure) { │ │ │ │ │ + failure = (config.scope) ? │ │ │ │ │ + OpenLayers.Function.bind(config.failure, config.scope) : │ │ │ │ │ + config.failure; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + if (OpenLayers.Util.createUrlObject(config.url).protocol == "file:" && │ │ │ │ │ + request.responseText) { │ │ │ │ │ + request.status = 200; │ │ │ │ │ + } │ │ │ │ │ + complete(request); │ │ │ │ │ + │ │ │ │ │ + if (!request.status || (request.status >= 200 && request.status < 300)) { │ │ │ │ │ + this.events.triggerEvent("success", options); │ │ │ │ │ + if (success) { │ │ │ │ │ + success(request); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + if (request.status && (request.status < 200 || request.status >= 300)) { │ │ │ │ │ + this.events.triggerEvent("failure", options); │ │ │ │ │ + if (failure) { │ │ │ │ │ + failure(request); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: GET │ │ │ │ │ + * Send an HTTP GET request. Additional configuration properties are │ │ │ │ │ + * documented in the method, with the method property set │ │ │ │ │ + * to GET. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * config - {Object} Object with properties for configuring the request. │ │ │ │ │ + * See the method for documentation of allowed properties. │ │ │ │ │ + * This object is modified and should not be reused. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {XMLHttpRequest} Request object. │ │ │ │ │ + */ │ │ │ │ │ + GET: function(config) { │ │ │ │ │ + config = OpenLayers.Util.extend(config, { │ │ │ │ │ + method: "GET" │ │ │ │ │ + }); │ │ │ │ │ + return OpenLayers.Request.issue(config); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: POST │ │ │ │ │ + * Send a POST request. Additional configuration properties are │ │ │ │ │ + * documented in the method, with the method property set │ │ │ │ │ + * to POST and "Content-Type" header set to "application/xml". │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * config - {Object} Object with properties for configuring the request. │ │ │ │ │ + * See the method for documentation of allowed properties. The │ │ │ │ │ + * default "Content-Type" header will be set to "application-xml" if │ │ │ │ │ + * none is provided. This object is modified and should not be reused. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {XMLHttpRequest} Request object. │ │ │ │ │ + */ │ │ │ │ │ + POST: function(config) { │ │ │ │ │ + config = OpenLayers.Util.extend(config, { │ │ │ │ │ + method: "POST" │ │ │ │ │ + }); │ │ │ │ │ + // set content type to application/xml if it isn't already set │ │ │ │ │ + config.headers = config.headers ? config.headers : {}; │ │ │ │ │ + if (!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) { │ │ │ │ │ + config.headers["Content-Type"] = "application/xml"; │ │ │ │ │ + } │ │ │ │ │ + return OpenLayers.Request.issue(config); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: PUT │ │ │ │ │ + * Send an HTTP PUT request. Additional configuration properties are │ │ │ │ │ + * documented in the method, with the method property set │ │ │ │ │ + * to PUT and "Content-Type" header set to "application/xml". │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * config - {Object} Object with properties for configuring the request. │ │ │ │ │ + * See the method for documentation of allowed properties. The │ │ │ │ │ + * default "Content-Type" header will be set to "application-xml" if │ │ │ │ │ + * none is provided. This object is modified and should not be reused. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {XMLHttpRequest} Request object. │ │ │ │ │ + */ │ │ │ │ │ + PUT: function(config) { │ │ │ │ │ + config = OpenLayers.Util.extend(config, { │ │ │ │ │ + method: "PUT" │ │ │ │ │ + }); │ │ │ │ │ + // set content type to application/xml if it isn't already set │ │ │ │ │ + config.headers = config.headers ? config.headers : {}; │ │ │ │ │ + if (!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) { │ │ │ │ │ + config.headers["Content-Type"] = "application/xml"; │ │ │ │ │ + } │ │ │ │ │ + return OpenLayers.Request.issue(config); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: DELETE │ │ │ │ │ + * Send an HTTP DELETE request. Additional configuration properties are │ │ │ │ │ + * documented in the method, with the method property set │ │ │ │ │ + * to DELETE. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * config - {Object} Object with properties for configuring the request. │ │ │ │ │ + * See the method for documentation of allowed properties. │ │ │ │ │ + * This object is modified and should not be reused. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {XMLHttpRequest} Request object. │ │ │ │ │ + */ │ │ │ │ │ + DELETE: function(config) { │ │ │ │ │ + config = OpenLayers.Util.extend(config, { │ │ │ │ │ + method: "DELETE" │ │ │ │ │ + }); │ │ │ │ │ + return OpenLayers.Request.issue(config); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: HEAD │ │ │ │ │ + * Send an HTTP HEAD request. Additional configuration properties are │ │ │ │ │ + * documented in the method, with the method property set │ │ │ │ │ + * to HEAD. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * config - {Object} Object with properties for configuring the request. │ │ │ │ │ + * See the method for documentation of allowed properties. │ │ │ │ │ + * This object is modified and should not be reused. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {XMLHttpRequest} Request object. │ │ │ │ │ + */ │ │ │ │ │ + HEAD: function(config) { │ │ │ │ │ + config = OpenLayers.Util.extend(config, { │ │ │ │ │ + method: "HEAD" │ │ │ │ │ + }); │ │ │ │ │ + return OpenLayers.Request.issue(config); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: OPTIONS │ │ │ │ │ + * Send an HTTP OPTIONS request. Additional configuration properties are │ │ │ │ │ + * documented in the method, with the method property set │ │ │ │ │ + * to OPTIONS. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * config - {Object} Object with properties for configuring the request. │ │ │ │ │ + * See the method for documentation of allowed properties. │ │ │ │ │ + * This object is modified and should not be reused. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {XMLHttpRequest} Request object. │ │ │ │ │ + */ │ │ │ │ │ + OPTIONS: function(config) { │ │ │ │ │ + config = OpenLayers.Util.extend(config, { │ │ │ │ │ + method: "OPTIONS" │ │ │ │ │ + }); │ │ │ │ │ + return OpenLayers.Request.issue(config); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Geometry.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Geometry │ │ │ │ │ + * A Geometry is a description of a geographic object. Create an instance of │ │ │ │ │ + * this class with the constructor. This is a base class, │ │ │ │ │ + * typical geometry types are described by subclasses of this class. │ │ │ │ │ + * │ │ │ │ │ + * Note that if you use the method, you must │ │ │ │ │ + * explicitly include the OpenLayers.Format.WKT in your build. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Geometry = OpenLayers.Class({ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: id │ │ │ │ │ + * {String} A unique identifier for this geometry. │ │ │ │ │ + */ │ │ │ │ │ + id: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: parent │ │ │ │ │ + * {}This is set when a Geometry is added as component │ │ │ │ │ + * of another geometry │ │ │ │ │ + */ │ │ │ │ │ + parent: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: bounds │ │ │ │ │ + * {} The bounds of this geometry │ │ │ │ │ + */ │ │ │ │ │ + bounds: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Geometry │ │ │ │ │ + * Creates a geometry object. │ │ │ │ │ + */ │ │ │ │ │ + initialize: function() { │ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: destroy │ │ │ │ │ + * Destroy this geometry. │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + this.id = null; │ │ │ │ │ + this.bounds = null; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: clone │ │ │ │ │ + * Create a clone of this geometry. Does not set any non-standard │ │ │ │ │ + * properties of the cloned geometry. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} An exact clone of this geometry. │ │ │ │ │ + */ │ │ │ │ │ + clone: function() { │ │ │ │ │ + return new OpenLayers.Geometry(); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: setBounds │ │ │ │ │ + * Set the bounds for this Geometry. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * bounds - {} │ │ │ │ │ + */ │ │ │ │ │ + setBounds: function(bounds) { │ │ │ │ │ + if (bounds) { │ │ │ │ │ + this.bounds = bounds.clone(); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: clearBounds │ │ │ │ │ + * Nullify this components bounds and that of its parent as well. │ │ │ │ │ + */ │ │ │ │ │ + clearBounds: function() { │ │ │ │ │ + this.bounds = null; │ │ │ │ │ + if (this.parent) { │ │ │ │ │ + this.parent.clearBounds(); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: extendBounds │ │ │ │ │ + * Extend the existing bounds to include the new bounds. │ │ │ │ │ + * If geometry's bounds is not yet set, then set a new Bounds. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * newBounds - {} │ │ │ │ │ + */ │ │ │ │ │ + extendBounds: function(newBounds) { │ │ │ │ │ + var bounds = this.getBounds(); │ │ │ │ │ + if (!bounds) { │ │ │ │ │ + this.setBounds(newBounds); │ │ │ │ │ + } else { │ │ │ │ │ + this.bounds.extend(newBounds); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getBounds │ │ │ │ │ + * Get the bounds for this Geometry. If bounds is not set, it │ │ │ │ │ + * is calculated again, this makes queries faster. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} │ │ │ │ │ + */ │ │ │ │ │ + getBounds: function() { │ │ │ │ │ + if (this.bounds == null) { │ │ │ │ │ + this.calculateBounds(); │ │ │ │ │ + } │ │ │ │ │ + return this.bounds; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: calculateBounds │ │ │ │ │ + * Recalculate the bounds for the geometry. │ │ │ │ │ + */ │ │ │ │ │ + calculateBounds: function() { │ │ │ │ │ + // │ │ │ │ │ + // This should be overridden by subclasses. │ │ │ │ │ + // │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: distanceTo │ │ │ │ │ + * Calculate the closest distance between two geometries (on the x-y plane). │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * geometry - {} The target geometry. │ │ │ │ │ + * options - {Object} Optional properties for configuring the distance │ │ │ │ │ + * calculation. │ │ │ │ │ + * │ │ │ │ │ + * Valid options depend on the specific geometry type. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Number | Object} The distance between this geometry and the target. │ │ │ │ │ + * If details is true, the return will be an object with distance, │ │ │ │ │ + * x0, y0, x1, and x2 properties. The x0 and y0 properties represent │ │ │ │ │ + * the coordinates of the closest point on this geometry. The x1 and y1 │ │ │ │ │ + * properties represent the coordinates of the closest point on the │ │ │ │ │ + * target geometry. │ │ │ │ │ + */ │ │ │ │ │ + distanceTo: function(geometry, options) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getVertices │ │ │ │ │ + * Return a list of all points in this geometry. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * nodes - {Boolean} For lines, only return vertices that are │ │ │ │ │ + * endpoints. If false, for lines, only vertices that are not │ │ │ │ │ + * endpoints will be returned. If not provided, all vertices will │ │ │ │ │ + * be returned. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Array} A list of all vertices in the geometry. │ │ │ │ │ + */ │ │ │ │ │ + getVertices: function(nodes) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: atPoint │ │ │ │ │ + * Note - This is only an approximation based on the bounds of the │ │ │ │ │ + * geometry. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * lonlat - {|Object} OpenLayers.LonLat or an │ │ │ │ │ + * object with a 'lon' and 'lat' properties. │ │ │ │ │ + * toleranceLon - {float} Optional tolerance in Geometric Coords │ │ │ │ │ + * toleranceLat - {float} Optional tolerance in Geographic Coords │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Whether or not the geometry is at the specified location │ │ │ │ │ + */ │ │ │ │ │ + atPoint: function(lonlat, toleranceLon, toleranceLat) { │ │ │ │ │ + var atPoint = false; │ │ │ │ │ + var bounds = this.getBounds(); │ │ │ │ │ + if ((bounds != null) && (lonlat != null)) { │ │ │ │ │ + │ │ │ │ │ + var dX = (toleranceLon != null) ? toleranceLon : 0; │ │ │ │ │ + var dY = (toleranceLat != null) ? toleranceLat : 0; │ │ │ │ │ + │ │ │ │ │ + var toleranceBounds = │ │ │ │ │ + new OpenLayers.Bounds(this.bounds.left - dX, │ │ │ │ │ + this.bounds.bottom - dY, │ │ │ │ │ + this.bounds.right + dX, │ │ │ │ │ + this.bounds.top + dY); │ │ │ │ │ + │ │ │ │ │ + atPoint = toleranceBounds.containsLonLat(lonlat); │ │ │ │ │ + } │ │ │ │ │ + return atPoint; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: getLength │ │ │ │ │ + * Calculate the length of this geometry. This method is defined in │ │ │ │ │ + * subclasses. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Float} The length of the collection by summing its parts │ │ │ │ │ + */ │ │ │ │ │ + getLength: function() { │ │ │ │ │ + //to be overridden by geometries that actually have a length │ │ │ │ │ + // │ │ │ │ │ + return 0.0; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: getArea │ │ │ │ │ + * Calculate the area of this geometry. This method is defined in subclasses. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Float} The area of the collection by summing its parts │ │ │ │ │ + */ │ │ │ │ │ + getArea: function() { │ │ │ │ │ + //to be overridden by geometries that actually have an area │ │ │ │ │ + // │ │ │ │ │ + return 0.0; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getCentroid │ │ │ │ │ + * Calculate the centroid of this geometry. This method is defined in subclasses. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} The centroid of the collection │ │ │ │ │ + */ │ │ │ │ │ + getCentroid: function() { │ │ │ │ │ + return null; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: toString │ │ │ │ │ + * Returns a text representation of the geometry. If the WKT format is │ │ │ │ │ + * included in a build, this will be the Well-Known Text │ │ │ │ │ + * representation. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {String} String representation of this geometry. │ │ │ │ │ + */ │ │ │ │ │ + toString: function() { │ │ │ │ │ + var string; │ │ │ │ │ + if (OpenLayers.Format && OpenLayers.Format.WKT) { │ │ │ │ │ + string = OpenLayers.Format.WKT.prototype.write( │ │ │ │ │ + new OpenLayers.Feature.Vector(this) │ │ │ │ │ + ); │ │ │ │ │ + } else { │ │ │ │ │ + string = Object.prototype.toString.call(this); │ │ │ │ │ + } │ │ │ │ │ + return string; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry" │ │ │ │ │ +}); │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Function: OpenLayers.Geometry.fromWKT │ │ │ │ │ + * Generate a geometry given a Well-Known Text string. For this method to │ │ │ │ │ + * work, you must include the OpenLayers.Format.WKT in your build │ │ │ │ │ + * explicitly. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * wkt - {String} A string representing the geometry in Well-Known Text. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} A geometry of the appropriate class. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Geometry.fromWKT = function(wkt) { │ │ │ │ │ + var geom; │ │ │ │ │ + if (OpenLayers.Format && OpenLayers.Format.WKT) { │ │ │ │ │ + var format = OpenLayers.Geometry.fromWKT.format; │ │ │ │ │ + if (!format) { │ │ │ │ │ + format = new OpenLayers.Format.WKT(); │ │ │ │ │ + OpenLayers.Geometry.fromWKT.format = format; │ │ │ │ │ + } │ │ │ │ │ + var result = format.read(wkt); │ │ │ │ │ + if (result instanceof OpenLayers.Feature.Vector) { │ │ │ │ │ + geom = result.geometry; │ │ │ │ │ + } else if (OpenLayers.Util.isArray(result)) { │ │ │ │ │ + var len = result.length; │ │ │ │ │ + var components = new Array(len); │ │ │ │ │ + for (var i = 0; i < len; ++i) { │ │ │ │ │ + components[i] = result[i].geometry; │ │ │ │ │ + } │ │ │ │ │ + geom = new OpenLayers.Geometry.Collection(components); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return geom; │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Method: OpenLayers.Geometry.segmentsIntersect │ │ │ │ │ + * Determine whether two line segments intersect. Optionally calculates │ │ │ │ │ + * and returns the intersection point. This function is optimized for │ │ │ │ │ + * cases where seg1.x2 >= seg2.x1 || seg2.x2 >= seg1.x1. In those │ │ │ │ │ + * obvious cases where there is no intersection, the function should │ │ │ │ │ + * not be called. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * seg1 - {Object} Object representing a segment with properties x1, y1, x2, │ │ │ │ │ + * and y2. The start point is represented by x1 and y1. The end point │ │ │ │ │ + * is represented by x2 and y2. Start and end are ordered so that x1 < x2. │ │ │ │ │ + * seg2 - {Object} Object representing a segment with properties x1, y1, x2, │ │ │ │ │ + * and y2. The start point is represented by x1 and y1. The end point │ │ │ │ │ + * is represented by x2 and y2. Start and end are ordered so that x1 < x2. │ │ │ │ │ + * options - {Object} Optional properties for calculating the intersection. │ │ │ │ │ + * │ │ │ │ │ + * Valid options: │ │ │ │ │ + * point - {Boolean} Return the intersection point. If false, the actual │ │ │ │ │ + * intersection point will not be calculated. If true and the segments │ │ │ │ │ + * intersect, the intersection point will be returned. If true and │ │ │ │ │ + * the segments do not intersect, false will be returned. If true and │ │ │ │ │ + * the segments are coincident, true will be returned. │ │ │ │ │ + * tolerance - {Number} If a non-null value is provided, if the segments are │ │ │ │ │ + * within the tolerance distance, this will be considered an intersection. │ │ │ │ │ + * In addition, if the point option is true and the calculated intersection │ │ │ │ │ + * is within the tolerance distance of an end point, the endpoint will be │ │ │ │ │ + * returned instead of the calculated intersection. Further, if the │ │ │ │ │ + * intersection is within the tolerance of endpoints on both segments, or │ │ │ │ │ + * if two segment endpoints are within the tolerance distance of eachother │ │ │ │ │ + * (but no intersection is otherwise calculated), an endpoint on the │ │ │ │ │ + * first segment provided will be returned. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean | } The two segments intersect. │ │ │ │ │ + * If the point argument is true, the return will be the intersection │ │ │ │ │ + * point or false if none exists. If point is true and the segments │ │ │ │ │ + * are coincident, return will be true (and the instersection is equal │ │ │ │ │ + * to the shorter segment). │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, options) { │ │ │ │ │ + var point = options && options.point; │ │ │ │ │ + var tolerance = options && options.tolerance; │ │ │ │ │ + var intersection = false; │ │ │ │ │ + var x11_21 = seg1.x1 - seg2.x1; │ │ │ │ │ + var y11_21 = seg1.y1 - seg2.y1; │ │ │ │ │ + var x12_11 = seg1.x2 - seg1.x1; │ │ │ │ │ + var y12_11 = seg1.y2 - seg1.y1; │ │ │ │ │ + var y22_21 = seg2.y2 - seg2.y1; │ │ │ │ │ + var x22_21 = seg2.x2 - seg2.x1; │ │ │ │ │ + var d = (y22_21 * x12_11) - (x22_21 * y12_11); │ │ │ │ │ + var n1 = (x22_21 * y11_21) - (y22_21 * x11_21); │ │ │ │ │ + var n2 = (x12_11 * y11_21) - (y12_11 * x11_21); │ │ │ │ │ + if (d == 0) { │ │ │ │ │ + // parallel │ │ │ │ │ + if (n1 == 0 && n2 == 0) { │ │ │ │ │ + // coincident │ │ │ │ │ + intersection = true; │ │ │ │ │ + } │ │ │ │ │ + } else { │ │ │ │ │ + var along1 = n1 / d; │ │ │ │ │ + var along2 = n2 / d; │ │ │ │ │ + if (along1 >= 0 && along1 <= 1 && along2 >= 0 && along2 <= 1) { │ │ │ │ │ + // intersect │ │ │ │ │ + if (!point) { │ │ │ │ │ + intersection = true; │ │ │ │ │ + } else { │ │ │ │ │ + // calculate the intersection point │ │ │ │ │ + var x = seg1.x1 + (along1 * x12_11); │ │ │ │ │ + var y = seg1.y1 + (along1 * y12_11); │ │ │ │ │ + intersection = new OpenLayers.Geometry.Point(x, y); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + if (tolerance) { │ │ │ │ │ + var dist; │ │ │ │ │ + if (intersection) { │ │ │ │ │ + if (point) { │ │ │ │ │ + var segs = [seg1, seg2]; │ │ │ │ │ + var seg, x, y; │ │ │ │ │ + // check segment endpoints for proximity to intersection │ │ │ │ │ + // set intersection to first endpoint within the tolerance │ │ │ │ │ + outer: for (var i = 0; i < 2; ++i) { │ │ │ │ │ + seg = segs[i]; │ │ │ │ │ + for (var j = 1; j < 3; ++j) { │ │ │ │ │ + x = seg["x" + j]; │ │ │ │ │ + y = seg["y" + j]; │ │ │ │ │ + dist = Math.sqrt( │ │ │ │ │ + Math.pow(x - intersection.x, 2) + │ │ │ │ │ + Math.pow(y - intersection.y, 2) │ │ │ │ │ + ); │ │ │ │ │ + if (dist < tolerance) { │ │ │ │ │ + intersection.x = x; │ │ │ │ │ + intersection.y = y; │ │ │ │ │ + break outer; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + } │ │ │ │ │ + } else { │ │ │ │ │ + // no calculated intersection, but segments could be within │ │ │ │ │ + // the tolerance of one another │ │ │ │ │ + var segs = [seg1, seg2]; │ │ │ │ │ + var source, target, x, y, p, result; │ │ │ │ │ + // check segment endpoints for proximity to intersection │ │ │ │ │ + // set intersection to first endpoint within the tolerance │ │ │ │ │ + outer: for (var i = 0; i < 2; ++i) { │ │ │ │ │ + source = segs[i]; │ │ │ │ │ + target = segs[(i + 1) % 2]; │ │ │ │ │ + for (var j = 1; j < 3; ++j) { │ │ │ │ │ + p = { │ │ │ │ │ + x: source["x" + j], │ │ │ │ │ + y: source["y" + j] │ │ │ │ │ + }; │ │ │ │ │ + result = OpenLayers.Geometry.distanceToSegment(p, target); │ │ │ │ │ + if (result.distance < tolerance) { │ │ │ │ │ + if (point) { │ │ │ │ │ + intersection = new OpenLayers.Geometry.Point(p.x, p.y); │ │ │ │ │ + } else { │ │ │ │ │ + intersection = true; │ │ │ │ │ + } │ │ │ │ │ + break outer; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return intersection; │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Function: OpenLayers.Geometry.distanceToSegment │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * point - {Object} An object with x and y properties representing the │ │ │ │ │ + * point coordinates. │ │ │ │ │ + * segment - {Object} An object with x1, y1, x2, and y2 properties │ │ │ │ │ + * representing endpoint coordinates. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Object} An object with distance, along, x, and y properties. The distance │ │ │ │ │ + * will be the shortest distance between the input point and segment. │ │ │ │ │ + * The x and y properties represent the coordinates along the segment │ │ │ │ │ + * where the shortest distance meets the segment. The along attribute │ │ │ │ │ + * describes how far between the two segment points the given point is. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Geometry.distanceToSegment = function(point, segment) { │ │ │ │ │ + var result = OpenLayers.Geometry.distanceSquaredToSegment(point, segment); │ │ │ │ │ + result.distance = Math.sqrt(result.distance); │ │ │ │ │ + return result; │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Function: OpenLayers.Geometry.distanceSquaredToSegment │ │ │ │ │ + * │ │ │ │ │ + * Usually the distanceToSegment function should be used. This variant however │ │ │ │ │ + * can be used for comparisons where the exact distance is not important. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * point - {Object} An object with x and y properties representing the │ │ │ │ │ + * point coordinates. │ │ │ │ │ + * segment - {Object} An object with x1, y1, x2, and y2 properties │ │ │ │ │ + * representing endpoint coordinates. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Object} An object with squared distance, along, x, and y properties. │ │ │ │ │ + * The distance will be the shortest distance between the input point and │ │ │ │ │ + * segment. The x and y properties represent the coordinates along the │ │ │ │ │ + * segment where the shortest distance meets the segment. The along │ │ │ │ │ + * attribute describes how far between the two segment points the given │ │ │ │ │ + * point is. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Geometry.distanceSquaredToSegment = function(point, segment) { │ │ │ │ │ + var x0 = point.x; │ │ │ │ │ + var y0 = point.y; │ │ │ │ │ + var x1 = segment.x1; │ │ │ │ │ + var y1 = segment.y1; │ │ │ │ │ + var x2 = segment.x2; │ │ │ │ │ + var y2 = segment.y2; │ │ │ │ │ + var dx = x2 - x1; │ │ │ │ │ + var dy = y2 - y1; │ │ │ │ │ + var along = ((dx * (x0 - x1)) + (dy * (y0 - y1))) / │ │ │ │ │ + (Math.pow(dx, 2) + Math.pow(dy, 2)); │ │ │ │ │ + var x, y; │ │ │ │ │ + if (along <= 0.0) { │ │ │ │ │ + x = x1; │ │ │ │ │ + y = y1; │ │ │ │ │ + } else if (along >= 1.0) { │ │ │ │ │ + x = x2; │ │ │ │ │ + y = y2; │ │ │ │ │ + } else { │ │ │ │ │ + x = x1 + along * dx; │ │ │ │ │ + y = y1 + along * dy; │ │ │ │ │ + } │ │ │ │ │ + return { │ │ │ │ │ + distance: Math.pow(x - x0, 2) + Math.pow(y - y0, 2), │ │ │ │ │ + x: x, │ │ │ │ │ + y: y, │ │ │ │ │ + along: along │ │ │ │ │ + }; │ │ │ │ │ +}; │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Format.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + * @requires OpenLayers/Util.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Format │ │ │ │ │ + * Base class for format reading/writing a variety of formats. Subclasses │ │ │ │ │ + * of OpenLayers.Format are expected to have read and write methods. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Format = OpenLayers.Class({ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: options │ │ │ │ │ + * {Object} A reference to options passed to the constructor. │ │ │ │ │ + */ │ │ │ │ │ + options: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: externalProjection │ │ │ │ │ + * {} When passed a externalProjection and │ │ │ │ │ + * internalProjection, the format will reproject the geometries it │ │ │ │ │ + * reads or writes. The externalProjection is the projection used by │ │ │ │ │ + * the content which is passed into read or which comes out of write. │ │ │ │ │ + * In order to reproject, a projection transformation function for the │ │ │ │ │ + * specified projections must be available. This support may be │ │ │ │ │ + * provided via proj4js or via a custom transformation function. See │ │ │ │ │ + * {} for more information on │ │ │ │ │ + * custom transformations. │ │ │ │ │ + */ │ │ │ │ │ + externalProjection: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: internalProjection │ │ │ │ │ + * {} When passed a externalProjection and │ │ │ │ │ + * internalProjection, the format will reproject the geometries it │ │ │ │ │ + * reads or writes. The internalProjection is the projection used by │ │ │ │ │ + * the geometries which are returned by read or which are passed into │ │ │ │ │ + * write. In order to reproject, a projection transformation function │ │ │ │ │ + * for the specified projections must be available. This support may be │ │ │ │ │ + * provided via proj4js or via a custom transformation function. See │ │ │ │ │ + * {} for more information on │ │ │ │ │ + * custom transformations. │ │ │ │ │ + */ │ │ │ │ │ + internalProjection: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: data │ │ │ │ │ + * {Object} When is true, this is the parsed string sent to │ │ │ │ │ + * . │ │ │ │ │ + */ │ │ │ │ │ + data: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: keepData │ │ │ │ │ + * {Object} Maintain a reference () to the most recently read data. │ │ │ │ │ + * Default is false. │ │ │ │ │ + */ │ │ │ │ │ + keepData: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Format │ │ │ │ │ + * Instances of this class are not useful. See one of the subclasses. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * options - {Object} An optional object with properties to set on the │ │ │ │ │ + * format │ │ │ │ │ + * │ │ │ │ │ + * Valid options: │ │ │ │ │ + * keepData - {Boolean} If true, upon , the data property will be │ │ │ │ │ + * set to the parsed object (e.g. the json or xml object). │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * An instance of OpenLayers.Format │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(options) { │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ + this.options = options; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: destroy │ │ │ │ │ + * Clean up. │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: read │ │ │ │ │ + * Read data from a string, and return an object whose type depends on the │ │ │ │ │ + * subclass. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * data - {string} Data to read/parse. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * Depends on the subclass │ │ │ │ │ + */ │ │ │ │ │ + read: function(data) { │ │ │ │ │ + throw new Error('Read not implemented.'); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: write │ │ │ │ │ + * Accept an object, and return a string. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * object - {Object} Object to be serialized │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {String} A string representation of the object. │ │ │ │ │ + */ │ │ │ │ │ + write: function(object) { │ │ │ │ │ + throw new Error('Write not implemented.'); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Format" │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Geometry/Point.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Geometry.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Geometry.Point │ │ │ │ │ + * Point geometry class. │ │ │ │ │ + * │ │ │ │ │ + * Inherits from: │ │ │ │ │ + * - │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Geometry.Point = OpenLayers.Class(OpenLayers.Geometry, { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: x │ │ │ │ │ + * {float} │ │ │ │ │ + */ │ │ │ │ │ + x: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: y │ │ │ │ │ + * {float} │ │ │ │ │ + */ │ │ │ │ │ + y: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Geometry.Point │ │ │ │ │ + * Construct a point geometry. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * x - {float} │ │ │ │ │ + * y - {float} │ │ │ │ │ + * │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(x, y) { │ │ │ │ │ + OpenLayers.Geometry.prototype.initialize.apply(this, arguments); │ │ │ │ │ + │ │ │ │ │ + this.x = parseFloat(x); │ │ │ │ │ + this.y = parseFloat(y); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: clone │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} An exact clone of this OpenLayers.Geometry.Point │ │ │ │ │ + */ │ │ │ │ │ + clone: function(obj) { │ │ │ │ │ + if (obj == null) { │ │ │ │ │ + obj = new OpenLayers.Geometry.Point(this.x, this.y); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // catch any randomly tagged-on properties │ │ │ │ │ + OpenLayers.Util.applyDefaults(obj, this); │ │ │ │ │ + │ │ │ │ │ + return obj; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: calculateBounds │ │ │ │ │ + * Create a new Bounds based on the lon/lat │ │ │ │ │ + */ │ │ │ │ │ + calculateBounds: function() { │ │ │ │ │ + this.bounds = new OpenLayers.Bounds(this.x, this.y, │ │ │ │ │ + this.x, this.y); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: distanceTo │ │ │ │ │ + * Calculate the closest distance between two geometries (on the x-y plane). │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * geometry - {} The target geometry. │ │ │ │ │ + * options - {Object} Optional properties for configuring the distance │ │ │ │ │ + * calculation. │ │ │ │ │ + * │ │ │ │ │ + * Valid options: │ │ │ │ │ + * details - {Boolean} Return details from the distance calculation. │ │ │ │ │ + * Default is false. │ │ │ │ │ + * edge - {Boolean} Calculate the distance from this geometry to the │ │ │ │ │ + * nearest edge of the target geometry. Default is true. If true, │ │ │ │ │ + * calling distanceTo from a geometry that is wholly contained within │ │ │ │ │ + * the target will result in a non-zero distance. If false, whenever │ │ │ │ │ + * geometries intersect, calling distanceTo will return 0. If false, │ │ │ │ │ + * details cannot be returned. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Number | Object} The distance between this geometry and the target. │ │ │ │ │ + * If details is true, the return will be an object with distance, │ │ │ │ │ + * x0, y0, x1, and x2 properties. The x0 and y0 properties represent │ │ │ │ │ + * the coordinates of the closest point on this geometry. The x1 and y1 │ │ │ │ │ + * properties represent the coordinates of the closest point on the │ │ │ │ │ + * target geometry. │ │ │ │ │ + */ │ │ │ │ │ + distanceTo: function(geometry, options) { │ │ │ │ │ + var edge = !(options && options.edge === false); │ │ │ │ │ + var details = edge && options && options.details; │ │ │ │ │ + var distance, x0, y0, x1, y1, result; │ │ │ │ │ + if (geometry instanceof OpenLayers.Geometry.Point) { │ │ │ │ │ + x0 = this.x; │ │ │ │ │ + y0 = this.y; │ │ │ │ │ + x1 = geometry.x; │ │ │ │ │ + y1 = geometry.y; │ │ │ │ │ + distance = Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2)); │ │ │ │ │ + result = !details ? │ │ │ │ │ + distance : { │ │ │ │ │ + x0: x0, │ │ │ │ │ + y0: y0, │ │ │ │ │ + x1: x1, │ │ │ │ │ + y1: y1, │ │ │ │ │ + distance: distance │ │ │ │ │ + }; │ │ │ │ │ + } else { │ │ │ │ │ + result = geometry.distanceTo(this, options); │ │ │ │ │ + if (details) { │ │ │ │ │ + // switch coord order since this geom is target │ │ │ │ │ + result = { │ │ │ │ │ + x0: result.x1, │ │ │ │ │ + y0: result.y1, │ │ │ │ │ + x1: result.x0, │ │ │ │ │ + y1: result.y0, │ │ │ │ │ + distance: result.distance │ │ │ │ │ + }; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return result; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: equals │ │ │ │ │ + * Determine whether another geometry is equivalent to this one. Geometries │ │ │ │ │ + * are considered equivalent if all components have the same coordinates. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * geom - {} The geometry to test. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The supplied geometry is equivalent to this geometry. │ │ │ │ │ + */ │ │ │ │ │ + equals: function(geom) { │ │ │ │ │ + var equals = false; │ │ │ │ │ + if (geom != null) { │ │ │ │ │ + equals = ((this.x == geom.x && this.y == geom.y) || │ │ │ │ │ + (isNaN(this.x) && isNaN(this.y) && isNaN(geom.x) && isNaN(geom.y))); │ │ │ │ │ + } │ │ │ │ │ + return equals; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: toShortString │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {String} Shortened String representation of Point object. │ │ │ │ │ + * (ex. "5, 42") │ │ │ │ │ + */ │ │ │ │ │ + toShortString: function() { │ │ │ │ │ + return (this.x + ", " + this.y); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: move │ │ │ │ │ + * Moves a geometry by the given displacement along positive x and y axes. │ │ │ │ │ + * This modifies the position of the geometry and clears the cached │ │ │ │ │ + * bounds. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * x - {Float} Distance to move geometry in positive x direction. │ │ │ │ │ + * y - {Float} Distance to move geometry in positive y direction. │ │ │ │ │ + */ │ │ │ │ │ + move: function(x, y) { │ │ │ │ │ + this.x = this.x + x; │ │ │ │ │ + this.y = this.y + y; │ │ │ │ │ + this.clearBounds(); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: rotate │ │ │ │ │ + * Rotate a point around another. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * angle - {Float} Rotation angle in degrees (measured counterclockwise │ │ │ │ │ + * from the positive x-axis) │ │ │ │ │ + * origin - {} Center point for the rotation │ │ │ │ │ + */ │ │ │ │ │ + rotate: function(angle, origin) { │ │ │ │ │ + angle *= Math.PI / 180; │ │ │ │ │ + var radius = this.distanceTo(origin); │ │ │ │ │ + var theta = angle + Math.atan2(this.y - origin.y, this.x - origin.x); │ │ │ │ │ + this.x = origin.x + (radius * Math.cos(theta)); │ │ │ │ │ + this.y = origin.y + (radius * Math.sin(theta)); │ │ │ │ │ + this.clearBounds(); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getCentroid │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} The centroid of the collection │ │ │ │ │ + */ │ │ │ │ │ + getCentroid: function() { │ │ │ │ │ + return new OpenLayers.Geometry.Point(this.x, this.y); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: resize │ │ │ │ │ + * Resize a point relative to some origin. For points, this has the effect │ │ │ │ │ + * of scaling a vector (from the origin to the point). This method is │ │ │ │ │ + * more useful on geometry collection subclasses. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * scale - {Float} Ratio of the new distance from the origin to the old │ │ │ │ │ + * distance from the origin. A scale of 2 doubles the │ │ │ │ │ + * distance between the point and origin. │ │ │ │ │ + * origin - {} Point of origin for resizing │ │ │ │ │ + * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} - The current geometry. │ │ │ │ │ + */ │ │ │ │ │ + resize: function(scale, origin, ratio) { │ │ │ │ │ + ratio = (ratio == undefined) ? 1 : ratio; │ │ │ │ │ + this.x = origin.x + (scale * ratio * (this.x - origin.x)); │ │ │ │ │ + this.y = origin.y + (scale * (this.y - origin.y)); │ │ │ │ │ + this.clearBounds(); │ │ │ │ │ + return this; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: intersects │ │ │ │ │ + * Determine if the input geometry intersects this one. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * geometry - {} Any type of geometry. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The input geometry intersects this one. │ │ │ │ │ + */ │ │ │ │ │ + intersects: function(geometry) { │ │ │ │ │ + var intersect = false; │ │ │ │ │ + if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { │ │ │ │ │ + intersect = this.equals(geometry); │ │ │ │ │ + } else { │ │ │ │ │ + intersect = geometry.intersects(this); │ │ │ │ │ + } │ │ │ │ │ + return intersect; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: transform │ │ │ │ │ + * Translate the x,y properties of the point from source to dest. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * source - {} │ │ │ │ │ + * dest - {} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} │ │ │ │ │ + */ │ │ │ │ │ + transform: function(source, dest) { │ │ │ │ │ + if ((source && dest)) { │ │ │ │ │ + OpenLayers.Projection.transform( │ │ │ │ │ + this, source, dest); │ │ │ │ │ + this.bounds = null; │ │ │ │ │ + } │ │ │ │ │ + return this; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getVertices │ │ │ │ │ + * Return a list of all points in this geometry. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * nodes - {Boolean} For lines, only return vertices that are │ │ │ │ │ + * endpoints. If false, for lines, only vertices that are not │ │ │ │ │ + * endpoints will be returned. If not provided, all vertices will │ │ │ │ │ + * be returned. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Array} A list of all vertices in the geometry. │ │ │ │ │ + */ │ │ │ │ │ + getVertices: function(nodes) { │ │ │ │ │ + return [this]; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.Point" │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Geometry/Collection.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Geometry.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Geometry.Collection │ │ │ │ │ + * A Collection is exactly what it sounds like: A collection of different │ │ │ │ │ + * Geometries. These are stored in the local parameter (which │ │ │ │ │ + * can be passed as a parameter to the constructor). │ │ │ │ │ + * │ │ │ │ │ + * As new geometries are added to the collection, they are NOT cloned. │ │ │ │ │ + * When removing geometries, they need to be specified by reference (ie you │ │ │ │ │ + * have to pass in the *exact* geometry to be removed). │ │ │ │ │ + * │ │ │ │ │ + * The and functions here merely iterate through │ │ │ │ │ + * the components, summing their respective areas and lengths. │ │ │ │ │ + * │ │ │ │ │ + * Create a new instance with the constructor. │ │ │ │ │ + * │ │ │ │ │ + * Inherits from: │ │ │ │ │ + * - │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Geometry.Collection = OpenLayers.Class(OpenLayers.Geometry, { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: components │ │ │ │ │ + * {Array()} The component parts of this geometry │ │ │ │ │ + */ │ │ │ │ │ + components: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: componentTypes │ │ │ │ │ + * {Array(String)} An array of class names representing the types of │ │ │ │ │ + * components that the collection can include. A null value means the │ │ │ │ │ + * component types are not restricted. │ │ │ │ │ + */ │ │ │ │ │ + componentTypes: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Geometry.Collection │ │ │ │ │ + * Creates a Geometry Collection -- a list of geoms. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * components - {Array()} Optional array of geometries │ │ │ │ │ + * │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(components) { │ │ │ │ │ + OpenLayers.Geometry.prototype.initialize.apply(this, arguments); │ │ │ │ │ + this.components = []; │ │ │ │ │ + if (components != null) { │ │ │ │ │ + this.addComponents(components); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: destroy │ │ │ │ │ + * Destroy this geometry. │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + this.components.length = 0; │ │ │ │ │ + this.components = null; │ │ │ │ │ + OpenLayers.Geometry.prototype.destroy.apply(this, arguments); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: clone │ │ │ │ │ + * Clone this geometry. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} An exact clone of this collection │ │ │ │ │ + */ │ │ │ │ │ + clone: function() { │ │ │ │ │ + var geometry = eval("new " + this.CLASS_NAME + "()"); │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ + geometry.addComponent(this.components[i].clone()); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + // catch any randomly tagged-on properties │ │ │ │ │ + OpenLayers.Util.applyDefaults(geometry, this); │ │ │ │ │ + │ │ │ │ │ + return geometry; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: getComponentsString │ │ │ │ │ + * Get a string representing the components for this collection │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {String} A string representation of the components of this geometry │ │ │ │ │ + */ │ │ │ │ │ + getComponentsString: function() { │ │ │ │ │ + var strings = []; │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ + strings.push(this.components[i].toShortString()); │ │ │ │ │ + } │ │ │ │ │ + return strings.join(","); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: calculateBounds │ │ │ │ │ + * Recalculate the bounds by iterating through the components and │ │ │ │ │ + * calling calling extendBounds() on each item. │ │ │ │ │ + */ │ │ │ │ │ + calculateBounds: function() { │ │ │ │ │ + this.bounds = null; │ │ │ │ │ + var bounds = new OpenLayers.Bounds(); │ │ │ │ │ + var components = this.components; │ │ │ │ │ + if (components) { │ │ │ │ │ + for (var i = 0, len = components.length; i < len; i++) { │ │ │ │ │ + bounds.extend(components[i].getBounds()); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + // to preserve old behavior, we only set bounds if non-null │ │ │ │ │ + // in the future, we could add bounds.isEmpty() │ │ │ │ │ + if (bounds.left != null && bounds.bottom != null && │ │ │ │ │ + bounds.right != null && bounds.top != null) { │ │ │ │ │ + this.setBounds(bounds); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: addComponents │ │ │ │ │ + * Add components to this geometry. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * components - {Array()} An array of geometries to add │ │ │ │ │ + */ │ │ │ │ │ + addComponents: function(components) { │ │ │ │ │ + if (!(OpenLayers.Util.isArray(components))) { │ │ │ │ │ + components = [components]; │ │ │ │ │ + } │ │ │ │ │ + for (var i = 0, len = components.length; i < len; i++) { │ │ │ │ │ + this.addComponent(components[i]); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: addComponent │ │ │ │ │ + * Add a new component (geometry) to the collection. If this.componentTypes │ │ │ │ │ + * is set, then the component class name must be in the componentTypes array. │ │ │ │ │ + * │ │ │ │ │ + * The bounds cache is reset. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * component - {} A geometry to add │ │ │ │ │ + * index - {int} Optional index into the array to insert the component │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The component geometry was successfully added │ │ │ │ │ + */ │ │ │ │ │ + addComponent: function(component, index) { │ │ │ │ │ + var added = false; │ │ │ │ │ + if (component) { │ │ │ │ │ + if (this.componentTypes == null || │ │ │ │ │ + (OpenLayers.Util.indexOf(this.componentTypes, │ │ │ │ │ + component.CLASS_NAME) > -1)) { │ │ │ │ │ + │ │ │ │ │ + if (index != null && (index < this.components.length)) { │ │ │ │ │ + var components1 = this.components.slice(0, index); │ │ │ │ │ + var components2 = this.components.slice(index, │ │ │ │ │ + this.components.length); │ │ │ │ │ + components1.push(component); │ │ │ │ │ + this.components = components1.concat(components2); │ │ │ │ │ + } else { │ │ │ │ │ + this.components.push(component); │ │ │ │ │ + } │ │ │ │ │ + component.parent = this; │ │ │ │ │ + this.clearBounds(); │ │ │ │ │ + added = true; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return added; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: removeComponents │ │ │ │ │ + * Remove components from this geometry. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * components - {Array()} The components to be removed │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} A component was removed. │ │ │ │ │ + */ │ │ │ │ │ + removeComponents: function(components) { │ │ │ │ │ + var removed = false; │ │ │ │ │ + │ │ │ │ │ + if (!(OpenLayers.Util.isArray(components))) { │ │ │ │ │ + components = [components]; │ │ │ │ │ + } │ │ │ │ │ + for (var i = components.length - 1; i >= 0; --i) { │ │ │ │ │ + removed = this.removeComponent(components[i]) || removed; │ │ │ │ │ + } │ │ │ │ │ + return removed; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: removeComponent │ │ │ │ │ + * Remove a component from this geometry. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * component - {} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The component was removed. │ │ │ │ │ + */ │ │ │ │ │ + removeComponent: function(component) { │ │ │ │ │ + │ │ │ │ │ + OpenLayers.Util.removeItem(this.components, component); │ │ │ │ │ + │ │ │ │ │ + // clearBounds() so that it gets recalculated on the next call │ │ │ │ │ + // to this.getBounds(); │ │ │ │ │ + this.clearBounds(); │ │ │ │ │ + return true; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getLength │ │ │ │ │ + * Calculate the length of this geometry │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Float} The length of the geometry │ │ │ │ │ + */ │ │ │ │ │ + getLength: function() { │ │ │ │ │ + var length = 0.0; │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ + length += this.components[i].getLength(); │ │ │ │ │ + } │ │ │ │ │ + return length; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getArea │ │ │ │ │ + * Calculate the area of this geometry. Note how this function is overridden │ │ │ │ │ + * in . │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Float} The area of the collection by summing its parts │ │ │ │ │ + */ │ │ │ │ │ + getArea: function() { │ │ │ │ │ + var area = 0.0; │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ + area += this.components[i].getArea(); │ │ │ │ │ + } │ │ │ │ │ + return area; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getGeodesicArea │ │ │ │ │ + * Calculate the approximate area of the polygon were it projected onto │ │ │ │ │ + * the earth. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * projection - {} The spatial reference system │ │ │ │ │ + * for the geometry coordinates. If not provided, Geographic/WGS84 is │ │ │ │ │ + * assumed. │ │ │ │ │ + * │ │ │ │ │ + * Reference: │ │ │ │ │ + * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for │ │ │ │ │ + * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion │ │ │ │ │ + * Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409 │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {float} The approximate geodesic area of the geometry in square meters. │ │ │ │ │ + */ │ │ │ │ │ + getGeodesicArea: function(projection) { │ │ │ │ │ + var area = 0.0; │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ + area += this.components[i].getGeodesicArea(projection); │ │ │ │ │ + } │ │ │ │ │ + return area; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getCentroid │ │ │ │ │ + * │ │ │ │ │ + * Compute the centroid for this geometry collection. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * weighted - {Boolean} Perform the getCentroid computation recursively, │ │ │ │ │ + * returning an area weighted average of all geometries in this collection. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} The centroid of the collection │ │ │ │ │ + */ │ │ │ │ │ + getCentroid: function(weighted) { │ │ │ │ │ + if (!weighted) { │ │ │ │ │ + return this.components.length && this.components[0].getCentroid(); │ │ │ │ │ + } │ │ │ │ │ + var len = this.components.length; │ │ │ │ │ + if (!len) { │ │ │ │ │ + return false; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + var areas = []; │ │ │ │ │ + var centroids = []; │ │ │ │ │ + var areaSum = 0; │ │ │ │ │ + var minArea = Number.MAX_VALUE; │ │ │ │ │ + var component; │ │ │ │ │ + for (var i = 0; i < len; ++i) { │ │ │ │ │ + component = this.components[i]; │ │ │ │ │ + var area = component.getArea(); │ │ │ │ │ + var centroid = component.getCentroid(true); │ │ │ │ │ + if (isNaN(area) || isNaN(centroid.x) || isNaN(centroid.y)) { │ │ │ │ │ + continue; │ │ │ │ │ + } │ │ │ │ │ + areas.push(area); │ │ │ │ │ + areaSum += area; │ │ │ │ │ + minArea = (area < minArea && area > 0) ? area : minArea; │ │ │ │ │ + centroids.push(centroid); │ │ │ │ │ + } │ │ │ │ │ + len = areas.length; │ │ │ │ │ + if (areaSum === 0) { │ │ │ │ │ + // all the components in this collection have 0 area │ │ │ │ │ + // probably a collection of points -- weight all the points the same │ │ │ │ │ + for (var i = 0; i < len; ++i) { │ │ │ │ │ + areas[i] = 1; │ │ │ │ │ + } │ │ │ │ │ + areaSum = areas.length; │ │ │ │ │ + } else { │ │ │ │ │ + // normalize all the areas where the smallest area will get │ │ │ │ │ + // a value of 1 │ │ │ │ │ + for (var i = 0; i < len; ++i) { │ │ │ │ │ + areas[i] /= minArea; │ │ │ │ │ + } │ │ │ │ │ + areaSum /= minArea; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + var xSum = 0, │ │ │ │ │ + ySum = 0, │ │ │ │ │ + centroid, area; │ │ │ │ │ + for (var i = 0; i < len; ++i) { │ │ │ │ │ + centroid = centroids[i]; │ │ │ │ │ + area = areas[i]; │ │ │ │ │ + xSum += centroid.x * area; │ │ │ │ │ + ySum += centroid.y * area; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + return new OpenLayers.Geometry.Point(xSum / areaSum, ySum / areaSum); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getGeodesicLength │ │ │ │ │ + * Calculate the approximate length of the geometry were it projected onto │ │ │ │ │ + * the earth. │ │ │ │ │ + * │ │ │ │ │ + * projection - {} The spatial reference system │ │ │ │ │ + * for the geometry coordinates. If not provided, Geographic/WGS84 is │ │ │ │ │ + * assumed. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Float} The appoximate geodesic length of the geometry in meters. │ │ │ │ │ + */ │ │ │ │ │ + getGeodesicLength: function(projection) { │ │ │ │ │ + var length = 0.0; │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ + length += this.components[i].getGeodesicLength(projection); │ │ │ │ │ + } │ │ │ │ │ + return length; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: move │ │ │ │ │ + * Moves a geometry by the given displacement along positive x and y axes. │ │ │ │ │ + * This modifies the position of the geometry and clears the cached │ │ │ │ │ + * bounds. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * x - {Float} Distance to move geometry in positive x direction. │ │ │ │ │ + * y - {Float} Distance to move geometry in positive y direction. │ │ │ │ │ + */ │ │ │ │ │ + move: function(x, y) { │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ + this.components[i].move(x, y); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: rotate │ │ │ │ │ + * Rotate a geometry around some origin │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * angle - {Float} Rotation angle in degrees (measured counterclockwise │ │ │ │ │ + * from the positive x-axis) │ │ │ │ │ + * origin - {} Center point for the rotation │ │ │ │ │ + */ │ │ │ │ │ + rotate: function(angle, origin) { │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) { │ │ │ │ │ + this.components[i].rotate(angle, origin); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: resize │ │ │ │ │ + * Resize a geometry relative to some origin. Use this method to apply │ │ │ │ │ + * a uniform scaling to a geometry. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * scale - {Float} Factor by which to scale the geometry. A scale of 2 │ │ │ │ │ + * doubles the size of the geometry in each dimension │ │ │ │ │ + * (lines, for example, will be twice as long, and polygons │ │ │ │ │ + * will have four times the area). │ │ │ │ │ + * origin - {} Point of origin for resizing │ │ │ │ │ + * ratio - {Float} Optional x:y ratio for resizing. Default ratio is 1. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} - The current geometry. │ │ │ │ │ + */ │ │ │ │ │ + resize: function(scale, origin, ratio) { │ │ │ │ │ + for (var i = 0; i < this.components.length; ++i) { │ │ │ │ │ + this.components[i].resize(scale, origin, ratio); │ │ │ │ │ + } │ │ │ │ │ + return this; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: distanceTo │ │ │ │ │ + * Calculate the closest distance between two geometries (on the x-y plane). │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * geometry - {} The target geometry. │ │ │ │ │ + * options - {Object} Optional properties for configuring the distance │ │ │ │ │ + * calculation. │ │ │ │ │ + * │ │ │ │ │ + * Valid options: │ │ │ │ │ + * details - {Boolean} Return details from the distance calculation. │ │ │ │ │ + * Default is false. │ │ │ │ │ + * edge - {Boolean} Calculate the distance from this geometry to the │ │ │ │ │ + * nearest edge of the target geometry. Default is true. If true, │ │ │ │ │ + * calling distanceTo from a geometry that is wholly contained within │ │ │ │ │ + * the target will result in a non-zero distance. If false, whenever │ │ │ │ │ + * geometries intersect, calling distanceTo will return 0. If false, │ │ │ │ │ + * details cannot be returned. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Number | Object} The distance between this geometry and the target. │ │ │ │ │ + * If details is true, the return will be an object with distance, │ │ │ │ │ + * x0, y0, x1, and y1 properties. The x0 and y0 properties represent │ │ │ │ │ + * the coordinates of the closest point on this geometry. The x1 and y1 │ │ │ │ │ + * properties represent the coordinates of the closest point on the │ │ │ │ │ + * target geometry. │ │ │ │ │ + */ │ │ │ │ │ + distanceTo: function(geometry, options) { │ │ │ │ │ + var edge = !(options && options.edge === false); │ │ │ │ │ + var details = edge && options && options.details; │ │ │ │ │ + var result, best, distance; │ │ │ │ │ + var min = Number.POSITIVE_INFINITY; │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) { │ │ │ │ │ + result = this.components[i].distanceTo(geometry, options); │ │ │ │ │ + distance = details ? result.distance : result; │ │ │ │ │ + if (distance < min) { │ │ │ │ │ + min = distance; │ │ │ │ │ + best = result; │ │ │ │ │ + if (min == 0) { │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return best; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: equals │ │ │ │ │ + * Determine whether another geometry is equivalent to this one. Geometries │ │ │ │ │ + * are considered equivalent if all components have the same coordinates. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * geometry - {} The geometry to test. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The supplied geometry is equivalent to this geometry. │ │ │ │ │ + */ │ │ │ │ │ + equals: function(geometry) { │ │ │ │ │ + var equivalent = true; │ │ │ │ │ + if (!geometry || !geometry.CLASS_NAME || │ │ │ │ │ + (this.CLASS_NAME != geometry.CLASS_NAME)) { │ │ │ │ │ + equivalent = false; │ │ │ │ │ + } else if (!(OpenLayers.Util.isArray(geometry.components)) || │ │ │ │ │ + (geometry.components.length != this.components.length)) { │ │ │ │ │ + equivalent = false; │ │ │ │ │ + } else { │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) { │ │ │ │ │ + if (!this.components[i].equals(geometry.components[i])) { │ │ │ │ │ + equivalent = false; │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return equivalent; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: transform │ │ │ │ │ + * Reproject the components geometry from source to dest. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * source - {} │ │ │ │ │ + * dest - {} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} │ │ │ │ │ + */ │ │ │ │ │ + transform: function(source, dest) { │ │ │ │ │ + if (source && dest) { │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; i++) { │ │ │ │ │ + var component = this.components[i]; │ │ │ │ │ + component.transform(source, dest); │ │ │ │ │ + } │ │ │ │ │ + this.bounds = null; │ │ │ │ │ + } │ │ │ │ │ + return this; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: intersects │ │ │ │ │ + * Determine if the input geometry intersects this one. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * geometry - {} Any type of geometry. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The input geometry intersects this one. │ │ │ │ │ + */ │ │ │ │ │ + intersects: function(geometry) { │ │ │ │ │ + var intersect = false; │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) { │ │ │ │ │ + intersect = geometry.intersects(this.components[i]); │ │ │ │ │ + if (intersect) { │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return intersect; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getVertices │ │ │ │ │ + * Return a list of all points in this geometry. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * nodes - {Boolean} For lines, only return vertices that are │ │ │ │ │ + * endpoints. If false, for lines, only vertices that are not │ │ │ │ │ + * endpoints will be returned. If not provided, all vertices will │ │ │ │ │ + * be returned. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Array} A list of all vertices in the geometry. │ │ │ │ │ + */ │ │ │ │ │ + getVertices: function(nodes) { │ │ │ │ │ + var vertices = []; │ │ │ │ │ + for (var i = 0, len = this.components.length; i < len; ++i) { │ │ │ │ │ + Array.prototype.push.apply( │ │ │ │ │ + vertices, this.components[i].getVertices(nodes) │ │ │ │ │ + ); │ │ │ │ │ + } │ │ │ │ │ + return vertices; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.Collection" │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Geometry/MultiPoint.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Geometry/Collection.js │ │ │ │ │ + * @requires OpenLayers/Geometry/Point.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Geometry.MultiPoint │ │ │ │ │ + * MultiPoint is a collection of Points. Create a new instance with the │ │ │ │ │ + * constructor. │ │ │ │ │ + * │ │ │ │ │ + * Inherits from: │ │ │ │ │ + * - │ │ │ │ │ + * - │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Geometry.MultiPoint = OpenLayers.Class( │ │ │ │ │ + OpenLayers.Geometry.Collection, { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: componentTypes │ │ │ │ │ + * {Array(String)} An array of class names representing the types of │ │ │ │ │ + * components that the collection can include. A null value means the │ │ │ │ │ + * component types are not restricted. │ │ │ │ │ + */ │ │ │ │ │ + componentTypes: ["OpenLayers.Geometry.Point"], │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Geometry.MultiPoint │ │ │ │ │ + * Create a new MultiPoint Geometry │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * components - {Array()} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: addPoint │ │ │ │ │ + * Wrapper for │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * point - {} Point to be added │ │ │ │ │ + * index - {Integer} Optional index │ │ │ │ │ + */ │ │ │ │ │ + addPoint: function(point, index) { │ │ │ │ │ + this.addComponent(point, index); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: removePoint │ │ │ │ │ + * Wrapper for │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * point - {} Point to be removed │ │ │ │ │ + */ │ │ │ │ │ + removePoint: function(point) { │ │ │ │ │ + this.removeComponent(point); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.MultiPoint" │ │ │ │ │ + }); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Geometry/Curve.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Geometry/MultiPoint.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Geometry.Curve │ │ │ │ │ + * A Curve is a MultiPoint, whose points are assumed to be connected. To │ │ │ │ │ + * this end, we provide a "getLength()" function, which iterates through │ │ │ │ │ + * the points, summing the distances between them. │ │ │ │ │ + * │ │ │ │ │ + * Inherits: │ │ │ │ │ + * - │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Geometry.Curve = OpenLayers.Class(OpenLayers.Geometry.MultiPoint, { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: componentTypes │ │ │ │ │ + * {Array(String)} An array of class names representing the types of │ │ │ │ │ + * components that the collection can include. A null │ │ │ │ │ + * value means the component types are not restricted. │ │ │ │ │ + */ │ │ │ │ │ + componentTypes: ["OpenLayers.Geometry.Point"], │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Geometry.Curve │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * point - {Array()} │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getLength │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Float} The length of the curve │ │ │ │ │ + */ │ │ │ │ │ + getLength: function() { │ │ │ │ │ + var length = 0.0; │ │ │ │ │ + if (this.components && (this.components.length > 1)) { │ │ │ │ │ + for (var i = 1, len = this.components.length; i < len; i++) { │ │ │ │ │ + length += this.components[i - 1].distanceTo(this.components[i]); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + return length; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getGeodesicLength │ │ │ │ │ + * Calculate the approximate length of the geometry were it projected onto │ │ │ │ │ + * the earth. │ │ │ │ │ + * │ │ │ │ │ + * projection - {} The spatial reference system │ │ │ │ │ + * for the geometry coordinates. If not provided, Geographic/WGS84 is │ │ │ │ │ + * assumed. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Float} The appoximate geodesic length of the geometry in meters. │ │ │ │ │ + */ │ │ │ │ │ + getGeodesicLength: function(projection) { │ │ │ │ │ + var geom = this; // so we can work with a clone if needed │ │ │ │ │ + if (projection) { │ │ │ │ │ + var gg = new OpenLayers.Projection("EPSG:4326"); │ │ │ │ │ + if (!gg.equals(projection)) { │ │ │ │ │ + geom = this.clone().transform(projection, gg); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + var length = 0.0; │ │ │ │ │ + if (geom.components && (geom.components.length > 1)) { │ │ │ │ │ + var p1, p2; │ │ │ │ │ + for (var i = 1, len = geom.components.length; i < len; i++) { │ │ │ │ │ + p1 = geom.components[i - 1]; │ │ │ │ │ + p2 = geom.components[i]; │ │ │ │ │ + // this returns km and requires lon/lat properties │ │ │ │ │ + length += OpenLayers.Util.distVincenty({ │ │ │ │ │ + lon: p1.x, │ │ │ │ │ + lat: p1.y │ │ │ │ │ + }, { │ │ │ │ │ + lon: p2.x, │ │ │ │ │ + lat: p2.y │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + // convert to m │ │ │ │ │ + return length * 1000; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Geometry.Curve" │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Geometry/LineString.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Geometry/Curve.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Geometry.LineString │ │ │ │ │ + * A LineString is a Curve which, once two points have been added to it, can │ │ │ │ │ + * never be less than two points long. │ │ │ │ │ + * │ │ │ │ │ + * Inherits from: │ │ │ │ │ + * - │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Geometry.LineString │ │ │ │ │ + * Create a new LineString geometry │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * points - {Array()} An array of points used to │ │ │ │ │ + * generate the linestring │ │ │ │ │ + * │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: removeComponent │ │ │ │ │ + * Only allows removal of a point if there are three or more points in │ │ │ │ │ + * the linestring. (otherwise the result would be just a single point) │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * point - {} The point to be removed │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The component was removed. │ │ │ │ │ + */ │ │ │ │ │ + removeComponent: function(point) { │ │ │ │ │ + var removed = this.components && (this.components.length > 2); │ │ │ │ │ + if (removed) { │ │ │ │ │ + OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this, │ │ │ │ │ + arguments); │ │ │ │ │ + } │ │ │ │ │ + return removed; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: intersects │ │ │ │ │ + * Test for instersection between two geometries. This is a cheapo │ │ │ │ │ + * implementation of the Bently-Ottmann algorigithm. It doesn't │ │ │ │ │ + * really keep track of a sweep line data structure. It is closer │ │ │ │ │ + * to the brute force method, except that segments are sorted and │ │ │ │ │ + * potential intersections are only calculated when bounding boxes │ │ │ │ │ + * intersect. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * geometry - {} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The input geometry intersects this geometry. │ │ │ │ │ + */ │ │ │ │ │ + intersects: function(geometry) { │ │ │ │ │ + var intersect = false; │ │ │ │ │ + var type = geometry.CLASS_NAME; │ │ │ │ │ + if (type == "OpenLayers.Geometry.LineString" || │ │ │ │ │ + type == "OpenLayers.Geometry.LinearRing" || │ │ │ │ │ + type == "OpenLayers.Geometry.Point") { │ │ │ │ │ + var segs1 = this.getSortedSegments(); │ │ │ │ │ + var segs2; │ │ │ │ │ + if (type == "OpenLayers.Geometry.Point") { │ │ │ │ │ + segs2 = [{ │ │ │ │ │ + x1: geometry.x, │ │ │ │ │ + y1: geometry.y, │ │ │ │ │ + x2: geometry.x, │ │ │ │ │ + y2: geometry.y │ │ │ │ │ + }]; │ │ │ │ │ + } else { │ │ │ │ │ + segs2 = geometry.getSortedSegments(); │ │ │ │ │ + } │ │ │ │ │ + var seg1, seg1x1, seg1x2, seg1y1, seg1y2, │ │ │ │ │ + seg2, seg2y1, seg2y2; │ │ │ │ │ + // sweep right │ │ │ │ │ + outer: for (var i = 0, len = segs1.length; i < len; ++i) { │ │ │ │ │ + seg1 = segs1[i]; │ │ │ │ │ + seg1x1 = seg1.x1; │ │ │ │ │ + seg1x2 = seg1.x2; │ │ │ │ │ + seg1y1 = seg1.y1; │ │ │ │ │ + seg1y2 = seg1.y2; │ │ │ │ │ + inner: for (var j = 0, jlen = segs2.length; j < jlen; ++j) { │ │ │ │ │ + seg2 = segs2[j]; │ │ │ │ │ + if (seg2.x1 > seg1x2) { │ │ │ │ │ + // seg1 still left of seg2 │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + if (seg2.x2 < seg1x1) { │ │ │ │ │ + // seg2 still left of seg1 │ │ │ │ │ + continue; │ │ │ │ │ + } │ │ │ │ │ + seg2y1 = seg2.y1; │ │ │ │ │ + seg2y2 = seg2.y2; │ │ │ │ │ + if (Math.min(seg2y1, seg2y2) > Math.max(seg1y1, seg1y2)) { │ │ │ │ │ + // seg2 above seg1 │ │ │ │ │ + continue; │ │ │ │ │ + } │ │ │ │ │ + if (Math.max(seg2y1, seg2y2) < Math.min(seg1y1, seg1y2)) { │ │ │ │ │ + // seg2 below seg1 │ │ │ │ │ + continue; │ │ │ │ │ + } │ │ │ │ │ + if (OpenLayers.Geometry.segmentsIntersect(seg1, seg2)) { │ │ │ │ │ + intersect = true; │ │ │ │ │ + break outer; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } else { │ │ │ │ │ + intersect = geometry.intersects(this); │ │ │ │ │ + } │ │ │ │ │ + return intersect; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: getSortedSegments │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Array} An array of segment objects. Segment objects have properties │ │ │ │ │ + * x1, y1, x2, and y2. The start point is represented by x1 and y1. │ │ │ │ │ + * The end point is represented by x2 and y2. Start and end are │ │ │ │ │ + * ordered so that x1 < x2. │ │ │ │ │ + */ │ │ │ │ │ + getSortedSegments: function() { │ │ │ │ │ + var numSeg = this.components.length - 1; │ │ │ │ │ + var segments = new Array(numSeg), │ │ │ │ │ + point1, point2; │ │ │ │ │ + for (var i = 0; i < numSeg; ++i) { │ │ │ │ │ + point1 = this.components[i]; │ │ │ │ │ + point2 = this.components[i + 1]; │ │ │ │ │ + if (point1.x < point2.x) { │ │ │ │ │ + segments[i] = { │ │ │ │ │ + x1: point1.x, │ │ │ │ │ + y1: point1.y, │ │ │ │ │ + x2: point2.x, │ │ │ │ │ + y2: point2.y │ │ │ │ │ + }; │ │ │ │ │ + } else { │ │ │ │ │ + segments[i] = { │ │ │ │ │ + x1: point2.x, │ │ │ │ │ + y1: point2.y, │ │ │ │ │ + x2: point1.x, │ │ │ │ │ + y2: point1.y │ │ │ │ │ + }; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + // more efficient to define this somewhere static │ │ │ │ │ + function byX1(seg1, seg2) { │ │ │ │ │ + return seg1.x1 - seg2.x1; │ │ │ │ │ + } │ │ │ │ │ + return segments.sort(byX1); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: splitWithSegment │ │ │ │ │ + * Split this geometry with the given segment. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * seg - {Object} An object with x1, y1, x2, and y2 properties referencing │ │ │ │ │ + * segment endpoint coordinates. │ │ │ │ │ + * options - {Object} Properties of this object will be used to determine │ │ │ │ │ + * how the split is conducted. │ │ │ │ │ + * │ │ │ │ │ + * Valid options: │ │ │ │ │ + * edge - {Boolean} Allow splitting when only edges intersect. Default is │ │ │ │ │ * true. If false, a vertex on the source segment must be within the │ │ │ │ │ * tolerance distance of the intersection to be considered a split. │ │ │ │ │ * tolerance - {Number} If a non-null value is provided, intersections │ │ │ │ │ * within the tolerance distance of one of the source segment's │ │ │ │ │ * endpoints will be assumed to occur at the endpoint. │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ @@ -12700,467 +15781,14 @@ │ │ │ │ │ * Constant: OpenLayers.Format.WFST.DEFAULTS │ │ │ │ │ * {Object} Default properties for the WFST format. │ │ │ │ │ */ │ │ │ │ │ OpenLayers.Format.WFST.DEFAULTS = { │ │ │ │ │ "version": "1.0.0" │ │ │ │ │ }; │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Style.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - * @requires OpenLayers/Util.js │ │ │ │ │ - * @requires OpenLayers/Feature/Vector.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Style │ │ │ │ │ - * This class represents a UserStyle obtained │ │ │ │ │ - * from a SLD, containing styling rules. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Style = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: id │ │ │ │ │ - * {String} A unique id for this session. │ │ │ │ │ - */ │ │ │ │ │ - id: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: name │ │ │ │ │ - * {String} │ │ │ │ │ - */ │ │ │ │ │ - name: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: title │ │ │ │ │ - * {String} Title of this style (set if included in SLD) │ │ │ │ │ - */ │ │ │ │ │ - title: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: description │ │ │ │ │ - * {String} Description of this style (set if abstract is included in SLD) │ │ │ │ │ - */ │ │ │ │ │ - description: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: layerName │ │ │ │ │ - * {} name of the layer that this style belongs to, usually │ │ │ │ │ - * according to the NamedLayer attribute of an SLD document. │ │ │ │ │ - */ │ │ │ │ │ - layerName: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: isDefault │ │ │ │ │ - * {Boolean} │ │ │ │ │ - */ │ │ │ │ │ - isDefault: false, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: rules │ │ │ │ │ - * {Array()} │ │ │ │ │ - */ │ │ │ │ │ - rules: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: context │ │ │ │ │ - * {Object} An optional object with properties that symbolizers' property │ │ │ │ │ - * values should be evaluated against. If no context is specified, │ │ │ │ │ - * feature.attributes will be used │ │ │ │ │ - */ │ │ │ │ │ - context: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: defaultStyle │ │ │ │ │ - * {Object} hash of style properties to use as default for merging │ │ │ │ │ - * rule-based style symbolizers onto. If no rules are defined, │ │ │ │ │ - * createSymbolizer will return this style. If is set to │ │ │ │ │ - * true, the defaultStyle will only be taken into account if there are │ │ │ │ │ - * rules defined. │ │ │ │ │ - */ │ │ │ │ │ - defaultStyle: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: defaultsPerSymbolizer │ │ │ │ │ - * {Boolean} If set to true, the will extend the symbolizer │ │ │ │ │ - * of every rule. Properties of the will also be used to set │ │ │ │ │ - * missing symbolizer properties if the symbolizer has stroke, fill or │ │ │ │ │ - * graphic set to true. Default is false. │ │ │ │ │ - */ │ │ │ │ │ - defaultsPerSymbolizer: false, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: propertyStyles │ │ │ │ │ - * {Hash of Boolean} cache of style properties that need to be parsed for │ │ │ │ │ - * propertyNames. Property names are keys, values won't be used. │ │ │ │ │ - */ │ │ │ │ │ - propertyStyles: null, │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Style │ │ │ │ │ - * Creates a UserStyle. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * style - {Object} Optional hash of style properties that will be │ │ │ │ │ - * used as default style for this style object. This style │ │ │ │ │ - * applies if no rules are specified. Symbolizers defined in │ │ │ │ │ - * rules will extend this default style. │ │ │ │ │ - * options - {Object} An optional object with properties to set on the │ │ │ │ │ - * style. │ │ │ │ │ - * │ │ │ │ │ - * Valid options: │ │ │ │ │ - * rules - {Array()} List of rules to be added to the │ │ │ │ │ - * style. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(style, options) { │ │ │ │ │ - │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - this.rules = []; │ │ │ │ │ - if (options && options.rules) { │ │ │ │ │ - this.addRules(options.rules); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // use the default style from OpenLayers.Feature.Vector if no style │ │ │ │ │ - // was given in the constructor │ │ │ │ │ - this.setDefaultStyle(style || │ │ │ │ │ - OpenLayers.Feature.Vector.style["default"]); │ │ │ │ │ - │ │ │ │ │ - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: destroy │ │ │ │ │ - * nullify references to prevent circular references and memory leaks │ │ │ │ │ - */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - for (var i = 0, len = this.rules.length; i < len; i++) { │ │ │ │ │ - this.rules[i].destroy(); │ │ │ │ │ - this.rules[i] = null; │ │ │ │ │ - } │ │ │ │ │ - this.rules = null; │ │ │ │ │ - this.defaultStyle = null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: createSymbolizer │ │ │ │ │ - * creates a style by applying all feature-dependent rules to the base │ │ │ │ │ - * style. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * feature - {} feature to evaluate rules for │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} symbolizer hash │ │ │ │ │ - */ │ │ │ │ │ - createSymbolizer: function(feature) { │ │ │ │ │ - var style = this.defaultsPerSymbolizer ? {} : this.createLiterals( │ │ │ │ │ - OpenLayers.Util.extend({}, this.defaultStyle), feature); │ │ │ │ │ - │ │ │ │ │ - var rules = this.rules; │ │ │ │ │ - │ │ │ │ │ - var rule, context; │ │ │ │ │ - var elseRules = []; │ │ │ │ │ - var appliedRules = false; │ │ │ │ │ - for (var i = 0, len = rules.length; i < len; i++) { │ │ │ │ │ - rule = rules[i]; │ │ │ │ │ - // does the rule apply? │ │ │ │ │ - var applies = rule.evaluate(feature); │ │ │ │ │ - │ │ │ │ │ - if (applies) { │ │ │ │ │ - if (rule instanceof OpenLayers.Rule && rule.elseFilter) { │ │ │ │ │ - elseRules.push(rule); │ │ │ │ │ - } else { │ │ │ │ │ - appliedRules = true; │ │ │ │ │ - this.applySymbolizer(rule, style, feature); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // if no other rules apply, apply the rules with else filters │ │ │ │ │ - if (appliedRules == false && elseRules.length > 0) { │ │ │ │ │ - appliedRules = true; │ │ │ │ │ - for (var i = 0, len = elseRules.length; i < len; i++) { │ │ │ │ │ - this.applySymbolizer(elseRules[i], style, feature); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // don't display if there were rules but none applied │ │ │ │ │ - if (rules.length > 0 && appliedRules == false) { │ │ │ │ │ - style.display = "none"; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (style.label != null && typeof style.label !== "string") { │ │ │ │ │ - style.label = String(style.label); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - return style; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: applySymbolizer │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * rule - {} │ │ │ │ │ - * style - {Object} │ │ │ │ │ - * feature - {} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} A style with new symbolizer applied. │ │ │ │ │ - */ │ │ │ │ │ - applySymbolizer: function(rule, style, feature) { │ │ │ │ │ - var symbolizerPrefix = feature.geometry ? │ │ │ │ │ - this.getSymbolizerPrefix(feature.geometry) : │ │ │ │ │ - OpenLayers.Style.SYMBOLIZER_PREFIXES[0]; │ │ │ │ │ - │ │ │ │ │ - var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer; │ │ │ │ │ - │ │ │ │ │ - if (this.defaultsPerSymbolizer === true) { │ │ │ │ │ - var defaults = this.defaultStyle; │ │ │ │ │ - OpenLayers.Util.applyDefaults(symbolizer, { │ │ │ │ │ - pointRadius: defaults.pointRadius │ │ │ │ │ - }); │ │ │ │ │ - if (symbolizer.stroke === true || symbolizer.graphic === true) { │ │ │ │ │ - OpenLayers.Util.applyDefaults(symbolizer, { │ │ │ │ │ - strokeWidth: defaults.strokeWidth, │ │ │ │ │ - strokeColor: defaults.strokeColor, │ │ │ │ │ - strokeOpacity: defaults.strokeOpacity, │ │ │ │ │ - strokeDashstyle: defaults.strokeDashstyle, │ │ │ │ │ - strokeLinecap: defaults.strokeLinecap │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - if (symbolizer.fill === true || symbolizer.graphic === true) { │ │ │ │ │ - OpenLayers.Util.applyDefaults(symbolizer, { │ │ │ │ │ - fillColor: defaults.fillColor, │ │ │ │ │ - fillOpacity: defaults.fillOpacity │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - if (symbolizer.graphic === true) { │ │ │ │ │ - OpenLayers.Util.applyDefaults(symbolizer, { │ │ │ │ │ - pointRadius: this.defaultStyle.pointRadius, │ │ │ │ │ - externalGraphic: this.defaultStyle.externalGraphic, │ │ │ │ │ - graphicName: this.defaultStyle.graphicName, │ │ │ │ │ - graphicOpacity: this.defaultStyle.graphicOpacity, │ │ │ │ │ - graphicWidth: this.defaultStyle.graphicWidth, │ │ │ │ │ - graphicHeight: this.defaultStyle.graphicHeight, │ │ │ │ │ - graphicXOffset: this.defaultStyle.graphicXOffset, │ │ │ │ │ - graphicYOffset: this.defaultStyle.graphicYOffset │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // merge the style with the current style │ │ │ │ │ - return this.createLiterals( │ │ │ │ │ - OpenLayers.Util.extend(style, symbolizer), feature); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: createLiterals │ │ │ │ │ - * creates literals for all style properties that have an entry in │ │ │ │ │ - * . │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * style - {Object} style to create literals for. Will be modified │ │ │ │ │ - * inline. │ │ │ │ │ - * feature - {Object} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} the modified style │ │ │ │ │ - */ │ │ │ │ │ - createLiterals: function(style, feature) { │ │ │ │ │ - var context = OpenLayers.Util.extend({}, feature.attributes || feature.data); │ │ │ │ │ - OpenLayers.Util.extend(context, this.context); │ │ │ │ │ - │ │ │ │ │ - for (var i in this.propertyStyles) { │ │ │ │ │ - style[i] = OpenLayers.Style.createLiteral(style[i], context, feature, i); │ │ │ │ │ - } │ │ │ │ │ - return style; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: findPropertyStyles │ │ │ │ │ - * Looks into all rules for this style and the defaultStyle to collect │ │ │ │ │ - * all the style hash property names containing ${...} strings that have │ │ │ │ │ - * to be replaced using the createLiteral method before returning them. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} hash of property names that need createLiteral parsing. The │ │ │ │ │ - * name of the property is the key, and the value is true; │ │ │ │ │ - */ │ │ │ │ │ - findPropertyStyles: function() { │ │ │ │ │ - var propertyStyles = {}; │ │ │ │ │ - │ │ │ │ │ - // check the default style │ │ │ │ │ - var style = this.defaultStyle; │ │ │ │ │ - this.addPropertyStyles(propertyStyles, style); │ │ │ │ │ - │ │ │ │ │ - // walk through all rules to check for properties in their symbolizer │ │ │ │ │ - var rules = this.rules; │ │ │ │ │ - var symbolizer, value; │ │ │ │ │ - for (var i = 0, len = rules.length; i < len; i++) { │ │ │ │ │ - symbolizer = rules[i].symbolizer; │ │ │ │ │ - for (var key in symbolizer) { │ │ │ │ │ - value = symbolizer[key]; │ │ │ │ │ - if (typeof value == "object") { │ │ │ │ │ - // symbolizer key is "Point", "Line" or "Polygon" │ │ │ │ │ - this.addPropertyStyles(propertyStyles, value); │ │ │ │ │ - } else { │ │ │ │ │ - // symbolizer is a hash of style properties │ │ │ │ │ - this.addPropertyStyles(propertyStyles, symbolizer); │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return propertyStyles; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: addPropertyStyles │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * propertyStyles - {Object} hash to add new property styles to. Will be │ │ │ │ │ - * modified inline │ │ │ │ │ - * symbolizer - {Object} search this symbolizer for property styles │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} propertyStyles hash │ │ │ │ │ - */ │ │ │ │ │ - addPropertyStyles: function(propertyStyles, symbolizer) { │ │ │ │ │ - var property; │ │ │ │ │ - for (var key in symbolizer) { │ │ │ │ │ - property = symbolizer[key]; │ │ │ │ │ - if (typeof property == "string" && │ │ │ │ │ - property.match(/\$\{\w+\}/)) { │ │ │ │ │ - propertyStyles[key] = true; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return propertyStyles; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: addRules │ │ │ │ │ - * Adds rules to this style. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * rules - {Array()} │ │ │ │ │ - */ │ │ │ │ │ - addRules: function(rules) { │ │ │ │ │ - Array.prototype.push.apply(this.rules, rules); │ │ │ │ │ - this.propertyStyles = this.findPropertyStyles(); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: setDefaultStyle │ │ │ │ │ - * Sets the default style for this style object. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * style - {Object} Hash of style properties │ │ │ │ │ - */ │ │ │ │ │ - setDefaultStyle: function(style) { │ │ │ │ │ - this.defaultStyle = style; │ │ │ │ │ - this.propertyStyles = this.findPropertyStyles(); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: getSymbolizerPrefix │ │ │ │ │ - * Returns the correct symbolizer prefix according to the │ │ │ │ │ - * geometry type of the passed geometry │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * geometry - {} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} key of the according symbolizer │ │ │ │ │ - */ │ │ │ │ │ - getSymbolizerPrefix: function(geometry) { │ │ │ │ │ - var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES; │ │ │ │ │ - for (var i = 0, len = prefixes.length; i < len; i++) { │ │ │ │ │ - if (geometry.CLASS_NAME.indexOf(prefixes[i]) != -1) { │ │ │ │ │ - return prefixes[i]; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: clone │ │ │ │ │ - * Clones this style. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} Clone of this style. │ │ │ │ │ - */ │ │ │ │ │ - clone: function() { │ │ │ │ │ - var options = OpenLayers.Util.extend({}, this); │ │ │ │ │ - // clone rules │ │ │ │ │ - if (this.rules) { │ │ │ │ │ - options.rules = []; │ │ │ │ │ - for (var i = 0, len = this.rules.length; i < len; ++i) { │ │ │ │ │ - options.rules.push(this.rules[i].clone()); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - // clone context │ │ │ │ │ - options.context = this.context && OpenLayers.Util.extend({}, this.context); │ │ │ │ │ - //clone default style │ │ │ │ │ - var defaultStyle = OpenLayers.Util.extend({}, this.defaultStyle); │ │ │ │ │ - return new OpenLayers.Style(defaultStyle, options); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Style" │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Function: createLiteral │ │ │ │ │ - * converts a style value holding a combination of PropertyName and Literal │ │ │ │ │ - * into a Literal, taking the property values from the passed features. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * value - {String} value to parse. If this string contains a construct like │ │ │ │ │ - * "foo ${bar}", then "foo " will be taken as literal, and "${bar}" │ │ │ │ │ - * will be replaced by the value of the "bar" attribute of the passed │ │ │ │ │ - * feature. │ │ │ │ │ - * context - {Object} context to take attribute values from │ │ │ │ │ - * feature - {} optional feature to pass to │ │ │ │ │ - * for evaluating functions in the │ │ │ │ │ - * context. │ │ │ │ │ - * property - {String} optional, name of the property for which the literal is │ │ │ │ │ - * being created for evaluating functions in the context. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} the parsed value. In the example of the value parameter above, the │ │ │ │ │ - * result would be "foo valueOfBar", assuming that the passed feature has an │ │ │ │ │ - * attribute named "bar" with the value "valueOfBar". │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Style.createLiteral = function(value, context, feature, property) { │ │ │ │ │ - if (typeof value == "string" && value.indexOf("${") != -1) { │ │ │ │ │ - value = OpenLayers.String.format(value, context, [feature, property]); │ │ │ │ │ - value = (isNaN(value) || !value) ? value : parseFloat(value); │ │ │ │ │ - } │ │ │ │ │ - return value; │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Style.SYMBOLIZER_PREFIXES │ │ │ │ │ - * {Array} prefixes of the sld symbolizers. These are the │ │ │ │ │ - * same as the main geometry types │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text', │ │ │ │ │ - 'Raster' │ │ │ │ │ -]; │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ OpenLayers/Filter.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ @@ -18049,2113 +20677,14 @@ │ │ │ │ │ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"] │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ CLASS_NAME: "OpenLayers.Format.WPSExecute" │ │ │ │ │ │ │ │ │ │ }); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Events.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Util.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Namespace: OpenLayers.Event │ │ │ │ │ - * Utility functions for event handling. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Event = { │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: observers │ │ │ │ │ - * {Object} A hashtable cache of the event observers. Keyed by │ │ │ │ │ - * element._eventCacheID │ │ │ │ │ - */ │ │ │ │ │ - observers: false, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: KEY_SPACE │ │ │ │ │ - * {int} │ │ │ │ │ - */ │ │ │ │ │ - KEY_SPACE: 32, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: KEY_BACKSPACE │ │ │ │ │ - * {int} │ │ │ │ │ - */ │ │ │ │ │ - KEY_BACKSPACE: 8, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: KEY_TAB │ │ │ │ │ - * {int} │ │ │ │ │ - */ │ │ │ │ │ - KEY_TAB: 9, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: KEY_RETURN │ │ │ │ │ - * {int} │ │ │ │ │ - */ │ │ │ │ │ - KEY_RETURN: 13, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: KEY_ESC │ │ │ │ │ - * {int} │ │ │ │ │ - */ │ │ │ │ │ - KEY_ESC: 27, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: KEY_LEFT │ │ │ │ │ - * {int} │ │ │ │ │ - */ │ │ │ │ │ - KEY_LEFT: 37, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: KEY_UP │ │ │ │ │ - * {int} │ │ │ │ │ - */ │ │ │ │ │ - KEY_UP: 38, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: KEY_RIGHT │ │ │ │ │ - * {int} │ │ │ │ │ - */ │ │ │ │ │ - KEY_RIGHT: 39, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: KEY_DOWN │ │ │ │ │ - * {int} │ │ │ │ │ - */ │ │ │ │ │ - KEY_DOWN: 40, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: KEY_DELETE │ │ │ │ │ - * {int} │ │ │ │ │ - */ │ │ │ │ │ - KEY_DELETE: 46, │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: element │ │ │ │ │ - * Cross browser event element detection. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * event - {Event} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {DOMElement} The element that caused the event │ │ │ │ │ - */ │ │ │ │ │ - element: function(event) { │ │ │ │ │ - return event.target || event.srcElement; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: isSingleTouch │ │ │ │ │ - * Determine whether event was caused by a single touch │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * event - {Event} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} │ │ │ │ │ - */ │ │ │ │ │ - isSingleTouch: function(event) { │ │ │ │ │ - return event.touches && event.touches.length == 1; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: isMultiTouch │ │ │ │ │ - * Determine whether event was caused by a multi touch │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * event - {Event} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} │ │ │ │ │ - */ │ │ │ │ │ - isMultiTouch: function(event) { │ │ │ │ │ - return event.touches && event.touches.length > 1; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: isLeftClick │ │ │ │ │ - * Determine whether event was caused by a left click. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * event - {Event} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} │ │ │ │ │ - */ │ │ │ │ │ - isLeftClick: function(event) { │ │ │ │ │ - return (((event.which) && (event.which == 1)) || │ │ │ │ │ - ((event.button) && (event.button == 1))); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: isRightClick │ │ │ │ │ - * Determine whether event was caused by a right mouse click. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * event - {Event} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} │ │ │ │ │ - */ │ │ │ │ │ - isRightClick: function(event) { │ │ │ │ │ - return (((event.which) && (event.which == 3)) || │ │ │ │ │ - ((event.button) && (event.button == 2))); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: stop │ │ │ │ │ - * Stops an event from propagating. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * event - {Event} │ │ │ │ │ - * allowDefault - {Boolean} If true, we stop the event chain but │ │ │ │ │ - * still allow the default browser behaviour (text selection, │ │ │ │ │ - * radio-button clicking, etc). Default is false. │ │ │ │ │ - */ │ │ │ │ │ - stop: function(event, allowDefault) { │ │ │ │ │ - │ │ │ │ │ - if (!allowDefault) { │ │ │ │ │ - OpenLayers.Event.preventDefault(event); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (event.stopPropagation) { │ │ │ │ │ - event.stopPropagation(); │ │ │ │ │ - } else { │ │ │ │ │ - event.cancelBubble = true; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: preventDefault │ │ │ │ │ - * Cancels the event if it is cancelable, without stopping further │ │ │ │ │ - * propagation of the event. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * event - {Event} │ │ │ │ │ - */ │ │ │ │ │ - preventDefault: function(event) { │ │ │ │ │ - if (event.preventDefault) { │ │ │ │ │ - event.preventDefault(); │ │ │ │ │ - } else { │ │ │ │ │ - event.returnValue = false; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: findElement │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * event - {Event} │ │ │ │ │ - * tagName - {String} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {DOMElement} The first node with the given tagName, starting from the │ │ │ │ │ - * node the event was triggered on and traversing the DOM upwards │ │ │ │ │ - */ │ │ │ │ │ - findElement: function(event, tagName) { │ │ │ │ │ - var element = OpenLayers.Event.element(event); │ │ │ │ │ - while (element.parentNode && (!element.tagName || │ │ │ │ │ - (element.tagName.toUpperCase() != tagName.toUpperCase()))) { │ │ │ │ │ - element = element.parentNode; │ │ │ │ │ - } │ │ │ │ │ - return element; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: observe │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * elementParam - {DOMElement || String} │ │ │ │ │ - * name - {String} │ │ │ │ │ - * observer - {function} │ │ │ │ │ - * useCapture - {Boolean} │ │ │ │ │ - */ │ │ │ │ │ - observe: function(elementParam, name, observer, useCapture) { │ │ │ │ │ - var element = OpenLayers.Util.getElement(elementParam); │ │ │ │ │ - useCapture = useCapture || false; │ │ │ │ │ - │ │ │ │ │ - if (name == 'keypress' && │ │ │ │ │ - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || │ │ │ │ │ - element.attachEvent)) { │ │ │ │ │ - name = 'keydown'; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - //if observers cache has not yet been created, create it │ │ │ │ │ - if (!this.observers) { │ │ │ │ │ - this.observers = {}; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - //if not already assigned, make a new unique cache ID │ │ │ │ │ - if (!element._eventCacheID) { │ │ │ │ │ - var idPrefix = "eventCacheID_"; │ │ │ │ │ - if (element.id) { │ │ │ │ │ - idPrefix = element.id + "_" + idPrefix; │ │ │ │ │ - } │ │ │ │ │ - element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - var cacheID = element._eventCacheID; │ │ │ │ │ - │ │ │ │ │ - //if there is not yet a hash entry for this element, add one │ │ │ │ │ - if (!this.observers[cacheID]) { │ │ │ │ │ - this.observers[cacheID] = []; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - //add a new observer to this element's list │ │ │ │ │ - this.observers[cacheID].push({ │ │ │ │ │ - 'element': element, │ │ │ │ │ - 'name': name, │ │ │ │ │ - 'observer': observer, │ │ │ │ │ - 'useCapture': useCapture │ │ │ │ │ - }); │ │ │ │ │ - │ │ │ │ │ - //add the actual browser event listener │ │ │ │ │ - if (element.addEventListener) { │ │ │ │ │ - element.addEventListener(name, observer, useCapture); │ │ │ │ │ - } else if (element.attachEvent) { │ │ │ │ │ - element.attachEvent('on' + name, observer); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: stopObservingElement │ │ │ │ │ - * Given the id of an element to stop observing, cycle through the │ │ │ │ │ - * element's cached observers, calling stopObserving on each one, │ │ │ │ │ - * skipping those entries which can no longer be removed. │ │ │ │ │ - * │ │ │ │ │ - * parameters: │ │ │ │ │ - * elementParam - {DOMElement || String} │ │ │ │ │ - */ │ │ │ │ │ - stopObservingElement: function(elementParam) { │ │ │ │ │ - var element = OpenLayers.Util.getElement(elementParam); │ │ │ │ │ - var cacheID = element._eventCacheID; │ │ │ │ │ - │ │ │ │ │ - this._removeElementObservers(OpenLayers.Event.observers[cacheID]); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: _removeElementObservers │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * elementObservers - {Array(Object)} Array of (element, name, │ │ │ │ │ - * observer, usecapture) objects, │ │ │ │ │ - * taken directly from hashtable │ │ │ │ │ - */ │ │ │ │ │ - _removeElementObservers: function(elementObservers) { │ │ │ │ │ - if (elementObservers) { │ │ │ │ │ - for (var i = elementObservers.length - 1; i >= 0; i--) { │ │ │ │ │ - var entry = elementObservers[i]; │ │ │ │ │ - OpenLayers.Event.stopObserving.apply(this, [ │ │ │ │ │ - entry.element, entry.name, entry.observer, entry.useCapture │ │ │ │ │ - ]); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: stopObserving │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * elementParam - {DOMElement || String} │ │ │ │ │ - * name - {String} │ │ │ │ │ - * observer - {function} │ │ │ │ │ - * useCapture - {Boolean} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} Whether or not the event observer was removed │ │ │ │ │ - */ │ │ │ │ │ - stopObserving: function(elementParam, name, observer, useCapture) { │ │ │ │ │ - useCapture = useCapture || false; │ │ │ │ │ - │ │ │ │ │ - var element = OpenLayers.Util.getElement(elementParam); │ │ │ │ │ - var cacheID = element._eventCacheID; │ │ │ │ │ - │ │ │ │ │ - if (name == 'keypress') { │ │ │ │ │ - if (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || │ │ │ │ │ - element.detachEvent) { │ │ │ │ │ - name = 'keydown'; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // find element's entry in this.observers cache and remove it │ │ │ │ │ - var foundEntry = false; │ │ │ │ │ - var elementObservers = OpenLayers.Event.observers[cacheID]; │ │ │ │ │ - if (elementObservers) { │ │ │ │ │ - │ │ │ │ │ - // find the specific event type in the element's list │ │ │ │ │ - var i = 0; │ │ │ │ │ - while (!foundEntry && i < elementObservers.length) { │ │ │ │ │ - var cacheEntry = elementObservers[i]; │ │ │ │ │ - │ │ │ │ │ - if ((cacheEntry.name == name) && │ │ │ │ │ - (cacheEntry.observer == observer) && │ │ │ │ │ - (cacheEntry.useCapture == useCapture)) { │ │ │ │ │ - │ │ │ │ │ - elementObservers.splice(i, 1); │ │ │ │ │ - if (elementObservers.length == 0) { │ │ │ │ │ - delete OpenLayers.Event.observers[cacheID]; │ │ │ │ │ - } │ │ │ │ │ - foundEntry = true; │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - i++; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - //actually remove the event listener from browser │ │ │ │ │ - if (foundEntry) { │ │ │ │ │ - if (element.removeEventListener) { │ │ │ │ │ - element.removeEventListener(name, observer, useCapture); │ │ │ │ │ - } else if (element && element.detachEvent) { │ │ │ │ │ - element.detachEvent('on' + name, observer); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return foundEntry; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: unloadCache │ │ │ │ │ - * Cycle through all the element entries in the events cache and call │ │ │ │ │ - * stopObservingElement on each. │ │ │ │ │ - */ │ │ │ │ │ - unloadCache: function() { │ │ │ │ │ - // check for OpenLayers.Event before checking for observers, because │ │ │ │ │ - // OpenLayers.Event may be undefined in IE if no map instance was │ │ │ │ │ - // created │ │ │ │ │ - if (OpenLayers.Event && OpenLayers.Event.observers) { │ │ │ │ │ - for (var cacheID in OpenLayers.Event.observers) { │ │ │ │ │ - var elementObservers = OpenLayers.Event.observers[cacheID]; │ │ │ │ │ - OpenLayers.Event._removeElementObservers.apply(this, │ │ │ │ │ - [elementObservers]); │ │ │ │ │ - } │ │ │ │ │ - OpenLayers.Event.observers = false; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Event" │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/* prevent memory leaks in IE */ │ │ │ │ │ -OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false); │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Events │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Events = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: BROWSER_EVENTS │ │ │ │ │ - * {Array(String)} supported events │ │ │ │ │ - */ │ │ │ │ │ - BROWSER_EVENTS: [ │ │ │ │ │ - "mouseover", "mouseout", │ │ │ │ │ - "mousedown", "mouseup", "mousemove", │ │ │ │ │ - "click", "dblclick", "rightclick", "dblrightclick", │ │ │ │ │ - "resize", "focus", "blur", │ │ │ │ │ - "touchstart", "touchmove", "touchend", │ │ │ │ │ - "keydown" │ │ │ │ │ - ], │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: listeners │ │ │ │ │ - * {Object} Hashtable of Array(Function): events listener functions │ │ │ │ │ - */ │ │ │ │ │ - listeners: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: object │ │ │ │ │ - * {Object} the code object issuing application events │ │ │ │ │ - */ │ │ │ │ │ - object: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: element │ │ │ │ │ - * {DOMElement} the DOM element receiving browser events │ │ │ │ │ - */ │ │ │ │ │ - element: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: eventHandler │ │ │ │ │ - * {Function} bound event handler attached to elements │ │ │ │ │ - */ │ │ │ │ │ - eventHandler: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: fallThrough │ │ │ │ │ - * {Boolean} │ │ │ │ │ - */ │ │ │ │ │ - fallThrough: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: includeXY │ │ │ │ │ - * {Boolean} Should the .xy property automatically be created for browser │ │ │ │ │ - * mouse events? In general, this should be false. If it is true, then │ │ │ │ │ - * mouse events will automatically generate a '.xy' property on the │ │ │ │ │ - * event object that is passed. (Prior to OpenLayers 2.7, this was true │ │ │ │ │ - * by default.) Otherwise, you can call the getMousePosition on the │ │ │ │ │ - * relevant events handler on the object available via the 'evt.object' │ │ │ │ │ - * property of the evt object. So, for most events, you can call: │ │ │ │ │ - * function named(evt) { │ │ │ │ │ - * this.xy = this.object.events.getMousePosition(evt) │ │ │ │ │ - * } │ │ │ │ │ - * │ │ │ │ │ - * This option typically defaults to false for performance reasons: │ │ │ │ │ - * when creating an events object whose primary purpose is to manage │ │ │ │ │ - * relatively positioned mouse events within a div, it may make │ │ │ │ │ - * sense to set it to true. │ │ │ │ │ - * │ │ │ │ │ - * This option is also used to control whether the events object caches │ │ │ │ │ - * offsets. If this is false, it will not: the reason for this is that │ │ │ │ │ - * it is only expected to be called many times if the includeXY property │ │ │ │ │ - * is set to true. If you set this to true, you are expected to clear │ │ │ │ │ - * the offset cache manually (using this.clearMouseCache()) if: │ │ │ │ │ - * the border of the element changes │ │ │ │ │ - * the location of the element in the page changes │ │ │ │ │ - */ │ │ │ │ │ - includeXY: false, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: extensions │ │ │ │ │ - * {Object} Event extensions registered with this instance. Keys are │ │ │ │ │ - * event types, values are {OpenLayers.Events.*} extension instances or │ │ │ │ │ - * {Boolean} for events that an instantiated extension provides in │ │ │ │ │ - * addition to the one it was created for. │ │ │ │ │ - * │ │ │ │ │ - * Extensions create an event in addition to browser events, which usually │ │ │ │ │ - * fires when a sequence of browser events is completed. Extensions are │ │ │ │ │ - * automatically instantiated when a listener is registered for an event │ │ │ │ │ - * provided by an extension. │ │ │ │ │ - * │ │ │ │ │ - * Extensions are created in the namespace using │ │ │ │ │ - * , and named after the event they provide. │ │ │ │ │ - * The constructor receives the target instance as │ │ │ │ │ - * argument. Extensions that need to capture browser events before they │ │ │ │ │ - * propagate can register their listeners events using , with │ │ │ │ │ - * {extension: true} as 4th argument. │ │ │ │ │ - * │ │ │ │ │ - * If an extension creates more than one event, an alias for each event │ │ │ │ │ - * type should be created and reference the same class. The constructor │ │ │ │ │ - * should set a reference in the target's extensions registry to itself. │ │ │ │ │ - * │ │ │ │ │ - * Below is a minimal extension that provides the "foostart" and "fooend" │ │ │ │ │ - * event types, which replace the native "click" event type if clicked on │ │ │ │ │ - * an element with the css class "foo": │ │ │ │ │ - * │ │ │ │ │ - * (code) │ │ │ │ │ - * OpenLayers.Events.foostart = OpenLayers.Class({ │ │ │ │ │ - * initialize: function(target) { │ │ │ │ │ - * this.target = target; │ │ │ │ │ - * this.target.register("click", this, this.doStuff, {extension: true}); │ │ │ │ │ - * // only required if extension provides more than one event type │ │ │ │ │ - * this.target.extensions["foostart"] = true; │ │ │ │ │ - * this.target.extensions["fooend"] = true; │ │ │ │ │ - * }, │ │ │ │ │ - * destroy: function() { │ │ │ │ │ - * var target = this.target; │ │ │ │ │ - * target.unregister("click", this, this.doStuff); │ │ │ │ │ - * delete this.target; │ │ │ │ │ - * // only required if extension provides more than one event type │ │ │ │ │ - * delete target.extensions["foostart"]; │ │ │ │ │ - * delete target.extensions["fooend"]; │ │ │ │ │ - * }, │ │ │ │ │ - * doStuff: function(evt) { │ │ │ │ │ - * var propagate = true; │ │ │ │ │ - * if (OpenLayers.Event.element(evt).className === "foo") { │ │ │ │ │ - * propagate = false; │ │ │ │ │ - * var target = this.target; │ │ │ │ │ - * target.triggerEvent("foostart"); │ │ │ │ │ - * window.setTimeout(function() { │ │ │ │ │ - * target.triggerEvent("fooend"); │ │ │ │ │ - * }, 1000); │ │ │ │ │ - * } │ │ │ │ │ - * return propagate; │ │ │ │ │ - * } │ │ │ │ │ - * }); │ │ │ │ │ - * // only required if extension provides more than one event type │ │ │ │ │ - * OpenLayers.Events.fooend = OpenLayers.Events.foostart; │ │ │ │ │ - * (end) │ │ │ │ │ - * │ │ │ │ │ - */ │ │ │ │ │ - extensions: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: extensionCount │ │ │ │ │ - * {Object} Keys are event types (like in ), values are the │ │ │ │ │ - * number of extension listeners for each event type. │ │ │ │ │ - */ │ │ │ │ │ - extensionCount: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: clearMouseListener │ │ │ │ │ - * A version of that is bound to this instance so that │ │ │ │ │ - * it can be used with and │ │ │ │ │ - * . │ │ │ │ │ - */ │ │ │ │ │ - clearMouseListener: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Events │ │ │ │ │ - * Construct an OpenLayers.Events object. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} The js object to which this Events object is being added │ │ │ │ │ - * element - {DOMElement} A dom element to respond to browser events │ │ │ │ │ - * eventTypes - {Array(String)} Deprecated. Array of custom application │ │ │ │ │ - * events. A listener may be registered for any named event, regardless │ │ │ │ │ - * of the values provided here. │ │ │ │ │ - * fallThrough - {Boolean} Allow events to fall through after these have │ │ │ │ │ - * been handled? │ │ │ │ │ - * options - {Object} Options for the events object. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(object, element, eventTypes, fallThrough, options) { │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - this.object = object; │ │ │ │ │ - this.fallThrough = fallThrough; │ │ │ │ │ - this.listeners = {}; │ │ │ │ │ - this.extensions = {}; │ │ │ │ │ - this.extensionCount = {}; │ │ │ │ │ - this._msTouches = []; │ │ │ │ │ - │ │ │ │ │ - // if a dom element is specified, add a listeners list │ │ │ │ │ - // for browser events on the element and register them │ │ │ │ │ - if (element != null) { │ │ │ │ │ - this.attachToElement(element); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: destroy │ │ │ │ │ - */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - for (var e in this.extensions) { │ │ │ │ │ - if (typeof this.extensions[e] !== "boolean") { │ │ │ │ │ - this.extensions[e].destroy(); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - this.extensions = null; │ │ │ │ │ - if (this.element) { │ │ │ │ │ - OpenLayers.Event.stopObservingElement(this.element); │ │ │ │ │ - if (this.element.hasScrollEvent) { │ │ │ │ │ - OpenLayers.Event.stopObserving( │ │ │ │ │ - window, "scroll", this.clearMouseListener │ │ │ │ │ - ); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - this.element = null; │ │ │ │ │ - │ │ │ │ │ - this.listeners = null; │ │ │ │ │ - this.object = null; │ │ │ │ │ - this.fallThrough = null; │ │ │ │ │ - this.eventHandler = null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: addEventType │ │ │ │ │ - * Deprecated. Any event can be triggered without adding it first. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * eventName - {String} │ │ │ │ │ - */ │ │ │ │ │ - addEventType: function(eventName) {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: attachToElement │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {HTMLDOMElement} a DOM element to attach browser events to │ │ │ │ │ - */ │ │ │ │ │ - attachToElement: function(element) { │ │ │ │ │ - if (this.element) { │ │ │ │ │ - OpenLayers.Event.stopObservingElement(this.element); │ │ │ │ │ - } else { │ │ │ │ │ - // keep a bound copy of handleBrowserEvent() so that we can │ │ │ │ │ - // pass the same function to both Event.observe() and .stopObserving() │ │ │ │ │ - this.eventHandler = OpenLayers.Function.bindAsEventListener( │ │ │ │ │ - this.handleBrowserEvent, this │ │ │ │ │ - ); │ │ │ │ │ - │ │ │ │ │ - // to be used with observe and stopObserving │ │ │ │ │ - this.clearMouseListener = OpenLayers.Function.bind( │ │ │ │ │ - this.clearMouseCache, this │ │ │ │ │ - ); │ │ │ │ │ - } │ │ │ │ │ - this.element = element; │ │ │ │ │ - var msTouch = !!window.navigator.msMaxTouchPoints; │ │ │ │ │ - var type; │ │ │ │ │ - for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) { │ │ │ │ │ - type = this.BROWSER_EVENTS[i]; │ │ │ │ │ - // register the event cross-browser │ │ │ │ │ - OpenLayers.Event.observe(element, type, this.eventHandler); │ │ │ │ │ - if (msTouch && type.indexOf('touch') === 0) { │ │ │ │ │ - this.addMsTouchListener(element, type, this.eventHandler); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - // disable dragstart in IE so that mousedown/move/up works normally │ │ │ │ │ - OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: on │ │ │ │ │ - * Convenience method for registering listeners with a common scope. │ │ │ │ │ - * Internally, this method calls as shown in the examples │ │ │ │ │ - * below. │ │ │ │ │ - * │ │ │ │ │ - * Example use: │ │ │ │ │ - * (code) │ │ │ │ │ - * // register a single listener for the "loadstart" event │ │ │ │ │ - * events.on({"loadstart": loadStartListener}); │ │ │ │ │ - * │ │ │ │ │ - * // this is equivalent to the following │ │ │ │ │ - * events.register("loadstart", undefined, loadStartListener); │ │ │ │ │ - * │ │ │ │ │ - * // register multiple listeners to be called with the same `this` object │ │ │ │ │ - * events.on({ │ │ │ │ │ - * "loadstart": loadStartListener, │ │ │ │ │ - * "loadend": loadEndListener, │ │ │ │ │ - * scope: object │ │ │ │ │ - * }); │ │ │ │ │ - * │ │ │ │ │ - * // this is equivalent to the following │ │ │ │ │ - * events.register("loadstart", object, loadStartListener); │ │ │ │ │ - * events.register("loadend", object, loadEndListener); │ │ │ │ │ - * (end) │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * object - {Object} │ │ │ │ │ - */ │ │ │ │ │ - on: function(object) { │ │ │ │ │ - for (var type in object) { │ │ │ │ │ - if (type != "scope" && object.hasOwnProperty(type)) { │ │ │ │ │ - this.register(type, object.scope, object[type]); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: register │ │ │ │ │ - * Register an event on the events object. │ │ │ │ │ - * │ │ │ │ │ - * When the event is triggered, the 'func' function will be called, in the │ │ │ │ │ - * context of 'obj'. Imagine we were to register an event, specifying an │ │ │ │ │ - * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the │ │ │ │ │ - * context in the callback function will be our Bounds object. This means │ │ │ │ │ - * that within our callback function, we can access the properties and │ │ │ │ │ - * methods of the Bounds object through the "this" variable. So our │ │ │ │ │ - * callback could execute something like: │ │ │ │ │ - * : leftStr = "Left: " + this.left; │ │ │ │ │ - * │ │ │ │ │ - * or │ │ │ │ │ - * │ │ │ │ │ - * : centerStr = "Center: " + this.getCenterLonLat(); │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * type - {String} Name of the event to register │ │ │ │ │ - * obj - {Object} The object to bind the context to for the callback#. │ │ │ │ │ - * If no object is specified, default is the Events's 'object' property. │ │ │ │ │ - * func - {Function} The callback function. If no callback is │ │ │ │ │ - * specified, this function does nothing. │ │ │ │ │ - * priority - {Boolean|Object} If true, adds the new listener to the │ │ │ │ │ - * *front* of the events queue instead of to the end. │ │ │ │ │ - * │ │ │ │ │ - * Valid options for priority: │ │ │ │ │ - * extension - {Boolean} If true, then the event will be registered as │ │ │ │ │ - * extension event. Extension events are handled before all other │ │ │ │ │ - * events. │ │ │ │ │ - */ │ │ │ │ │ - register: function(type, obj, func, priority) { │ │ │ │ │ - if (type in OpenLayers.Events && !this.extensions[type]) { │ │ │ │ │ - this.extensions[type] = new OpenLayers.Events[type](this); │ │ │ │ │ - } │ │ │ │ │ - if (func != null) { │ │ │ │ │ - if (obj == null) { │ │ │ │ │ - obj = this.object; │ │ │ │ │ - } │ │ │ │ │ - var listeners = this.listeners[type]; │ │ │ │ │ - if (!listeners) { │ │ │ │ │ - listeners = []; │ │ │ │ │ - this.listeners[type] = listeners; │ │ │ │ │ - this.extensionCount[type] = 0; │ │ │ │ │ - } │ │ │ │ │ - var listener = { │ │ │ │ │ - obj: obj, │ │ │ │ │ - func: func │ │ │ │ │ - }; │ │ │ │ │ - if (priority) { │ │ │ │ │ - listeners.splice(this.extensionCount[type], 0, listener); │ │ │ │ │ - if (typeof priority === "object" && priority.extension) { │ │ │ │ │ - this.extensionCount[type]++; │ │ │ │ │ - } │ │ │ │ │ - } else { │ │ │ │ │ - listeners.push(listener); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: registerPriority │ │ │ │ │ - * Same as register() but adds the new listener to the *front* of the │ │ │ │ │ - * events queue instead of to the end. │ │ │ │ │ - * │ │ │ │ │ - * TODO: get rid of this in 3.0 - Decide whether listeners should be │ │ │ │ │ - * called in the order they were registered or in reverse order. │ │ │ │ │ - * │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * type - {String} Name of the event to register │ │ │ │ │ - * obj - {Object} The object to bind the context to for the callback#. │ │ │ │ │ - * If no object is specified, default is the Events's │ │ │ │ │ - * 'object' property. │ │ │ │ │ - * func - {Function} The callback function. If no callback is │ │ │ │ │ - * specified, this function does nothing. │ │ │ │ │ - */ │ │ │ │ │ - registerPriority: function(type, obj, func) { │ │ │ │ │ - this.register(type, obj, func, true); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: un │ │ │ │ │ - * Convenience method for unregistering listeners with a common scope. │ │ │ │ │ - * Internally, this method calls as shown in the examples │ │ │ │ │ - * below. │ │ │ │ │ - * │ │ │ │ │ - * Example use: │ │ │ │ │ - * (code) │ │ │ │ │ - * // unregister a single listener for the "loadstart" event │ │ │ │ │ - * events.un({"loadstart": loadStartListener}); │ │ │ │ │ - * │ │ │ │ │ - * // this is equivalent to the following │ │ │ │ │ - * events.unregister("loadstart", undefined, loadStartListener); │ │ │ │ │ - * │ │ │ │ │ - * // unregister multiple listeners with the same `this` object │ │ │ │ │ - * events.un({ │ │ │ │ │ - * "loadstart": loadStartListener, │ │ │ │ │ - * "loadend": loadEndListener, │ │ │ │ │ - * scope: object │ │ │ │ │ - * }); │ │ │ │ │ - * │ │ │ │ │ - * // this is equivalent to the following │ │ │ │ │ - * events.unregister("loadstart", object, loadStartListener); │ │ │ │ │ - * events.unregister("loadend", object, loadEndListener); │ │ │ │ │ - * (end) │ │ │ │ │ - */ │ │ │ │ │ - un: function(object) { │ │ │ │ │ - for (var type in object) { │ │ │ │ │ - if (type != "scope" && object.hasOwnProperty(type)) { │ │ │ │ │ - this.unregister(type, object.scope, object[type]); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: unregister │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * type - {String} │ │ │ │ │ - * obj - {Object} If none specified, defaults to this.object │ │ │ │ │ - * func - {Function} │ │ │ │ │ - */ │ │ │ │ │ - unregister: function(type, obj, func) { │ │ │ │ │ - if (obj == null) { │ │ │ │ │ - obj = this.object; │ │ │ │ │ - } │ │ │ │ │ - var listeners = this.listeners[type]; │ │ │ │ │ - if (listeners != null) { │ │ │ │ │ - for (var i = 0, len = listeners.length; i < len; i++) { │ │ │ │ │ - if (listeners[i].obj == obj && listeners[i].func == func) { │ │ │ │ │ - listeners.splice(i, 1); │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: remove │ │ │ │ │ - * Remove all listeners for a given event type. If type is not registered, │ │ │ │ │ - * does nothing. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * type - {String} │ │ │ │ │ - */ │ │ │ │ │ - remove: function(type) { │ │ │ │ │ - if (this.listeners[type] != null) { │ │ │ │ │ - this.listeners[type] = []; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: triggerEvent │ │ │ │ │ - * Trigger a specified registered event. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * type - {String} │ │ │ │ │ - * evt - {Event || Object} will be passed to the listeners. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} The last listener return. If a listener returns false, the │ │ │ │ │ - * chain of listeners will stop getting called. │ │ │ │ │ - */ │ │ │ │ │ - triggerEvent: function(type, evt) { │ │ │ │ │ - var listeners = this.listeners[type]; │ │ │ │ │ - │ │ │ │ │ - // fast path │ │ │ │ │ - if (!listeners || listeners.length == 0) { │ │ │ │ │ - return undefined; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // prep evt object with object & div references │ │ │ │ │ - if (evt == null) { │ │ │ │ │ - evt = {}; │ │ │ │ │ - } │ │ │ │ │ - evt.object = this.object; │ │ │ │ │ - evt.element = this.element; │ │ │ │ │ - if (!evt.type) { │ │ │ │ │ - evt.type = type; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // execute all callbacks registered for specified type │ │ │ │ │ - // get a clone of the listeners array to │ │ │ │ │ - // allow for splicing during callbacks │ │ │ │ │ - listeners = listeners.slice(); │ │ │ │ │ - var continueChain; │ │ │ │ │ - for (var i = 0, len = listeners.length; i < len; i++) { │ │ │ │ │ - var callback = listeners[i]; │ │ │ │ │ - // bind the context to callback.obj │ │ │ │ │ - continueChain = callback.func.apply(callback.obj, [evt]); │ │ │ │ │ - │ │ │ │ │ - if ((continueChain != undefined) && (continueChain == false)) { │ │ │ │ │ - // if callback returns false, execute no more callbacks. │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - // don't fall through to other DOM elements │ │ │ │ │ - if (!this.fallThrough) { │ │ │ │ │ - OpenLayers.Event.stop(evt, true); │ │ │ │ │ - } │ │ │ │ │ - return continueChain; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: handleBrowserEvent │ │ │ │ │ - * Basically just a wrapper to the triggerEvent() function, but takes │ │ │ │ │ - * care to set a property 'xy' on the event with the current mouse │ │ │ │ │ - * position. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {Event} │ │ │ │ │ - */ │ │ │ │ │ - handleBrowserEvent: function(evt) { │ │ │ │ │ - var type = evt.type, │ │ │ │ │ - listeners = this.listeners[type]; │ │ │ │ │ - if (!listeners || listeners.length == 0) { │ │ │ │ │ - // noone's listening, bail out │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - // add clientX & clientY to all events - corresponds to average x, y │ │ │ │ │ - var touches = evt.touches; │ │ │ │ │ - if (touches && touches[0]) { │ │ │ │ │ - var x = 0; │ │ │ │ │ - var y = 0; │ │ │ │ │ - var num = touches.length; │ │ │ │ │ - var touch; │ │ │ │ │ - for (var i = 0; i < num; ++i) { │ │ │ │ │ - touch = this.getTouchClientXY(touches[i]); │ │ │ │ │ - x += touch.clientX; │ │ │ │ │ - y += touch.clientY; │ │ │ │ │ - } │ │ │ │ │ - evt.clientX = x / num; │ │ │ │ │ - evt.clientY = y / num; │ │ │ │ │ - } │ │ │ │ │ - if (this.includeXY) { │ │ │ │ │ - evt.xy = this.getMousePosition(evt); │ │ │ │ │ - } │ │ │ │ │ - this.triggerEvent(type, evt); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: getTouchClientXY │ │ │ │ │ - * WebKit has a few bugs for clientX/clientY. This method detects them │ │ │ │ │ - * and calculate the correct values. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {Touch} a Touch object from a TouchEvent │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} An object with only clientX and clientY properties with the │ │ │ │ │ - * calculated values. │ │ │ │ │ - */ │ │ │ │ │ - getTouchClientXY: function(evt) { │ │ │ │ │ - // olMochWin is to override window, used for testing │ │ │ │ │ - var win = window.olMockWin || window, │ │ │ │ │ - winPageX = win.pageXOffset, │ │ │ │ │ - winPageY = win.pageYOffset, │ │ │ │ │ - x = evt.clientX, │ │ │ │ │ - y = evt.clientY; │ │ │ │ │ - │ │ │ │ │ - if (evt.pageY === 0 && Math.floor(y) > Math.floor(evt.pageY) || │ │ │ │ │ - evt.pageX === 0 && Math.floor(x) > Math.floor(evt.pageX)) { │ │ │ │ │ - // iOS4 include scroll offset in clientX/Y │ │ │ │ │ - x = x - winPageX; │ │ │ │ │ - y = y - winPageY; │ │ │ │ │ - } else if (y < (evt.pageY - winPageY) || x < (evt.pageX - winPageX)) { │ │ │ │ │ - // Some Android browsers have totally bogus values for clientX/Y │ │ │ │ │ - // when scrolling/zooming a page │ │ │ │ │ - x = evt.pageX - winPageX; │ │ │ │ │ - y = evt.pageY - winPageY; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - evt.olClientX = x; │ │ │ │ │ - evt.olClientY = y; │ │ │ │ │ - │ │ │ │ │ - return { │ │ │ │ │ - clientX: x, │ │ │ │ │ - clientY: y │ │ │ │ │ - }; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: clearMouseCache │ │ │ │ │ - * Clear cached data about the mouse position. This should be called any │ │ │ │ │ - * time the element that events are registered on changes position │ │ │ │ │ - * within the page. │ │ │ │ │ - */ │ │ │ │ │ - clearMouseCache: function() { │ │ │ │ │ - this.element.scrolls = null; │ │ │ │ │ - this.element.lefttop = null; │ │ │ │ │ - this.element.offsets = null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: getMousePosition │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {Event} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} The current xy coordinate of the mouse, adjusted │ │ │ │ │ - * for offsets │ │ │ │ │ - */ │ │ │ │ │ - getMousePosition: function(evt) { │ │ │ │ │ - if (!this.includeXY) { │ │ │ │ │ - this.clearMouseCache(); │ │ │ │ │ - } else if (!this.element.hasScrollEvent) { │ │ │ │ │ - OpenLayers.Event.observe(window, "scroll", this.clearMouseListener); │ │ │ │ │ - this.element.hasScrollEvent = true; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (!this.element.scrolls) { │ │ │ │ │ - var viewportElement = OpenLayers.Util.getViewportElement(); │ │ │ │ │ - this.element.scrolls = [ │ │ │ │ │ - window.pageXOffset || viewportElement.scrollLeft, │ │ │ │ │ - window.pageYOffset || viewportElement.scrollTop │ │ │ │ │ - ]; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (!this.element.lefttop) { │ │ │ │ │ - this.element.lefttop = [ │ │ │ │ │ - (document.documentElement.clientLeft || 0), │ │ │ │ │ - (document.documentElement.clientTop || 0) │ │ │ │ │ - ]; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (!this.element.offsets) { │ │ │ │ │ - this.element.offsets = OpenLayers.Util.pagePosition(this.element); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - return new OpenLayers.Pixel( │ │ │ │ │ - (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0] - │ │ │ │ │ - this.element.lefttop[0], │ │ │ │ │ - (evt.clientY + this.element.scrolls[1]) - this.element.offsets[1] - │ │ │ │ │ - this.element.lefttop[1] │ │ │ │ │ - ); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: addMsTouchListener │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} The DOM element to register the listener on │ │ │ │ │ - * type - {String} The event type │ │ │ │ │ - * handler - {Function} the handler │ │ │ │ │ - */ │ │ │ │ │ - addMsTouchListener: function(element, type, handler) { │ │ │ │ │ - var eventHandler = this.eventHandler; │ │ │ │ │ - var touches = this._msTouches; │ │ │ │ │ - │ │ │ │ │ - function msHandler(evt) { │ │ │ │ │ - handler(OpenLayers.Util.applyDefaults({ │ │ │ │ │ - stopPropagation: function() { │ │ │ │ │ - for (var i = touches.length - 1; i >= 0; --i) { │ │ │ │ │ - touches[i].stopPropagation(); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - preventDefault: function() { │ │ │ │ │ - for (var i = touches.length - 1; i >= 0; --i) { │ │ │ │ │ - touches[i].preventDefault(); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - type: type │ │ │ │ │ - }, evt)); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - switch (type) { │ │ │ │ │ - case 'touchstart': │ │ │ │ │ - return this.addMsTouchListenerStart(element, type, msHandler); │ │ │ │ │ - case 'touchend': │ │ │ │ │ - return this.addMsTouchListenerEnd(element, type, msHandler); │ │ │ │ │ - case 'touchmove': │ │ │ │ │ - return this.addMsTouchListenerMove(element, type, msHandler); │ │ │ │ │ - default: │ │ │ │ │ - throw 'Unknown touch event type'; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: addMsTouchListenerStart │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} The DOM element to register the listener on │ │ │ │ │ - * type - {String} The event type │ │ │ │ │ - * handler - {Function} the handler │ │ │ │ │ - */ │ │ │ │ │ - addMsTouchListenerStart: function(element, type, handler) { │ │ │ │ │ - var touches = this._msTouches; │ │ │ │ │ - │ │ │ │ │ - var cb = function(e) { │ │ │ │ │ - │ │ │ │ │ - var alreadyInArray = false; │ │ │ │ │ - for (var i = 0, ii = touches.length; i < ii; ++i) { │ │ │ │ │ - if (touches[i].pointerId == e.pointerId) { │ │ │ │ │ - alreadyInArray = true; │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - if (!alreadyInArray) { │ │ │ │ │ - touches.push(e); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - e.touches = touches.slice(); │ │ │ │ │ - handler(e); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - OpenLayers.Event.observe(element, 'MSPointerDown', cb); │ │ │ │ │ - │ │ │ │ │ - // Need to also listen for end events to keep the _msTouches list │ │ │ │ │ - // accurate │ │ │ │ │ - var internalCb = function(e) { │ │ │ │ │ - for (var i = 0, ii = touches.length; i < ii; ++i) { │ │ │ │ │ - if (touches[i].pointerId == e.pointerId) { │ │ │ │ │ - touches.splice(i, 1); │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }; │ │ │ │ │ - OpenLayers.Event.observe(element, 'MSPointerUp', internalCb); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: addMsTouchListenerMove │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} The DOM element to register the listener on │ │ │ │ │ - * type - {String} The event type │ │ │ │ │ - * handler - {Function} the handler │ │ │ │ │ - */ │ │ │ │ │ - addMsTouchListenerMove: function(element, type, handler) { │ │ │ │ │ - var touches = this._msTouches; │ │ │ │ │ - var cb = function(e) { │ │ │ │ │ - │ │ │ │ │ - //Don't fire touch moves when mouse isn't down │ │ │ │ │ - if (e.pointerType == e.MSPOINTER_TYPE_MOUSE && e.buttons == 0) { │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (touches.length == 1 && touches[0].pageX == e.pageX && │ │ │ │ │ - touches[0].pageY == e.pageY) { │ │ │ │ │ - // don't trigger event when pointer has not moved │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - for (var i = 0, ii = touches.length; i < ii; ++i) { │ │ │ │ │ - if (touches[i].pointerId == e.pointerId) { │ │ │ │ │ - touches[i] = e; │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - e.touches = touches.slice(); │ │ │ │ │ - handler(e); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - OpenLayers.Event.observe(element, 'MSPointerMove', cb); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: addMsTouchListenerEnd │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * element - {DOMElement} The DOM element to register the listener on │ │ │ │ │ - * type - {String} The event type │ │ │ │ │ - * handler - {Function} the handler │ │ │ │ │ - */ │ │ │ │ │ - addMsTouchListenerEnd: function(element, type, handler) { │ │ │ │ │ - var touches = this._msTouches; │ │ │ │ │ - │ │ │ │ │ - var cb = function(e) { │ │ │ │ │ - │ │ │ │ │ - for (var i = 0, ii = touches.length; i < ii; ++i) { │ │ │ │ │ - if (touches[i].pointerId == e.pointerId) { │ │ │ │ │ - touches.splice(i, 1); │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - e.touches = touches.slice(); │ │ │ │ │ - handler(e); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - OpenLayers.Event.observe(element, 'MSPointerUp', cb); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Events" │ │ │ │ │ -}); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Request/XMLHttpRequest.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -// XMLHttpRequest.js Copyright (C) 2010 Sergey Ilinsky (http://www.ilinsky.com) │ │ │ │ │ -// │ │ │ │ │ -// Licensed under the Apache License, Version 2.0 (the "License"); │ │ │ │ │ -// you may not use this file except in compliance with the License. │ │ │ │ │ -// You may obtain a copy of the License at │ │ │ │ │ -// │ │ │ │ │ -// http://www.apache.org/licenses/LICENSE-2.0 │ │ │ │ │ -// │ │ │ │ │ -// Unless required by applicable law or agreed to in writing, software │ │ │ │ │ -// distributed under the License is distributed on an "AS IS" BASIS, │ │ │ │ │ -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ │ │ │ │ -// See the License for the specific language governing permissions and │ │ │ │ │ -// limitations under the License. │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Request.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -(function() { │ │ │ │ │ - │ │ │ │ │ - // Save reference to earlier defined object implementation (if any) │ │ │ │ │ - var oXMLHttpRequest = window.XMLHttpRequest; │ │ │ │ │ - │ │ │ │ │ - // Define on browser type │ │ │ │ │ - var bGecko = !!window.controllers, │ │ │ │ │ - bIE = window.document.all && !window.opera, │ │ │ │ │ - bIE7 = bIE && window.navigator.userAgent.match(/MSIE 7.0/); │ │ │ │ │ - │ │ │ │ │ - // Enables "XMLHttpRequest()" call next to "new XMLHttpReques()" │ │ │ │ │ - function fXMLHttpRequest() { │ │ │ │ │ - this._object = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP"); │ │ │ │ │ - this._listeners = []; │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - // Constructor │ │ │ │ │ - function cXMLHttpRequest() { │ │ │ │ │ - return new fXMLHttpRequest; │ │ │ │ │ - }; │ │ │ │ │ - cXMLHttpRequest.prototype = fXMLHttpRequest.prototype; │ │ │ │ │ - │ │ │ │ │ - // BUGFIX: Firefox with Firebug installed would break pages if not executed │ │ │ │ │ - if (bGecko && oXMLHttpRequest.wrapped) │ │ │ │ │ - cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped; │ │ │ │ │ - │ │ │ │ │ - // Constants │ │ │ │ │ - cXMLHttpRequest.UNSENT = 0; │ │ │ │ │ - cXMLHttpRequest.OPENED = 1; │ │ │ │ │ - cXMLHttpRequest.HEADERS_RECEIVED = 2; │ │ │ │ │ - cXMLHttpRequest.LOADING = 3; │ │ │ │ │ - cXMLHttpRequest.DONE = 4; │ │ │ │ │ - │ │ │ │ │ - // Public Properties │ │ │ │ │ - cXMLHttpRequest.prototype.readyState = cXMLHttpRequest.UNSENT; │ │ │ │ │ - cXMLHttpRequest.prototype.responseText = ''; │ │ │ │ │ - cXMLHttpRequest.prototype.responseXML = null; │ │ │ │ │ - cXMLHttpRequest.prototype.status = 0; │ │ │ │ │ - cXMLHttpRequest.prototype.statusText = ''; │ │ │ │ │ - │ │ │ │ │ - // Priority proposal │ │ │ │ │ - cXMLHttpRequest.prototype.priority = "NORMAL"; │ │ │ │ │ - │ │ │ │ │ - // Instance-level Events Handlers │ │ │ │ │ - cXMLHttpRequest.prototype.onreadystatechange = null; │ │ │ │ │ - │ │ │ │ │ - // Class-level Events Handlers │ │ │ │ │ - cXMLHttpRequest.onreadystatechange = null; │ │ │ │ │ - cXMLHttpRequest.onopen = null; │ │ │ │ │ - cXMLHttpRequest.onsend = null; │ │ │ │ │ - cXMLHttpRequest.onabort = null; │ │ │ │ │ - │ │ │ │ │ - // Public Methods │ │ │ │ │ - cXMLHttpRequest.prototype.open = function(sMethod, sUrl, bAsync, sUser, sPassword) { │ │ │ │ │ - // Delete headers, required when object is reused │ │ │ │ │ - delete this._headers; │ │ │ │ │ - │ │ │ │ │ - // When bAsync parameter value is omitted, use true as default │ │ │ │ │ - if (arguments.length < 3) │ │ │ │ │ - bAsync = true; │ │ │ │ │ - │ │ │ │ │ - // Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests │ │ │ │ │ - this._async = bAsync; │ │ │ │ │ - │ │ │ │ │ - // Set the onreadystatechange handler │ │ │ │ │ - var oRequest = this, │ │ │ │ │ - nState = this.readyState, │ │ │ │ │ - fOnUnload; │ │ │ │ │ - │ │ │ │ │ - // BUGFIX: IE - memory leak on page unload (inter-page leak) │ │ │ │ │ - if (bIE && bAsync) { │ │ │ │ │ - fOnUnload = function() { │ │ │ │ │ - if (nState != cXMLHttpRequest.DONE) { │ │ │ │ │ - fCleanTransport(oRequest); │ │ │ │ │ - // Safe to abort here since onreadystatechange handler removed │ │ │ │ │ - oRequest.abort(); │ │ │ │ │ - } │ │ │ │ │ - }; │ │ │ │ │ - window.attachEvent("onunload", fOnUnload); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // Add method sniffer │ │ │ │ │ - if (cXMLHttpRequest.onopen) │ │ │ │ │ - cXMLHttpRequest.onopen.apply(this, arguments); │ │ │ │ │ - │ │ │ │ │ - if (arguments.length > 4) │ │ │ │ │ - this._object.open(sMethod, sUrl, bAsync, sUser, sPassword); │ │ │ │ │ - else │ │ │ │ │ - if (arguments.length > 3) │ │ │ │ │ - this._object.open(sMethod, sUrl, bAsync, sUser); │ │ │ │ │ - else │ │ │ │ │ - this._object.open(sMethod, sUrl, bAsync); │ │ │ │ │ - │ │ │ │ │ - this.readyState = cXMLHttpRequest.OPENED; │ │ │ │ │ - fReadyStateChange(this); │ │ │ │ │ - │ │ │ │ │ - this._object.onreadystatechange = function() { │ │ │ │ │ - if (bGecko && !bAsync) │ │ │ │ │ - return; │ │ │ │ │ - │ │ │ │ │ - // Synchronize state │ │ │ │ │ - oRequest.readyState = oRequest._object.readyState; │ │ │ │ │ - │ │ │ │ │ - // │ │ │ │ │ - fSynchronizeValues(oRequest); │ │ │ │ │ - │ │ │ │ │ - // BUGFIX: Firefox fires unnecessary DONE when aborting │ │ │ │ │ - if (oRequest._aborted) { │ │ │ │ │ - // Reset readyState to UNSENT │ │ │ │ │ - oRequest.readyState = cXMLHttpRequest.UNSENT; │ │ │ │ │ - │ │ │ │ │ - // Return now │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (oRequest.readyState == cXMLHttpRequest.DONE) { │ │ │ │ │ - // Free up queue │ │ │ │ │ - delete oRequest._data; │ │ │ │ │ - /* if (bAsync) │ │ │ │ │ - fQueue_remove(oRequest);*/ │ │ │ │ │ - // │ │ │ │ │ - fCleanTransport(oRequest); │ │ │ │ │ - // Uncomment this block if you need a fix for IE cache │ │ │ │ │ - /* │ │ │ │ │ - // BUGFIX: IE - cache issue │ │ │ │ │ - if (!oRequest._object.getResponseHeader("Date")) { │ │ │ │ │ - // Save object to cache │ │ │ │ │ - oRequest._cached = oRequest._object; │ │ │ │ │ - │ │ │ │ │ - // Instantiate a new transport object │ │ │ │ │ - cXMLHttpRequest.call(oRequest); │ │ │ │ │ - │ │ │ │ │ - // Re-send request │ │ │ │ │ - if (sUser) { │ │ │ │ │ - if (sPassword) │ │ │ │ │ - oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword); │ │ │ │ │ - else │ │ │ │ │ - oRequest._object.open(sMethod, sUrl, bAsync, sUser); │ │ │ │ │ - } │ │ │ │ │ - else │ │ │ │ │ - oRequest._object.open(sMethod, sUrl, bAsync); │ │ │ │ │ - oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified") || new window.Date(0)); │ │ │ │ │ - // Copy headers set │ │ │ │ │ - if (oRequest._headers) │ │ │ │ │ - for (var sHeader in oRequest._headers) │ │ │ │ │ - if (typeof oRequest._headers[sHeader] == "string") // Some frameworks prototype objects with functions │ │ │ │ │ - oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]); │ │ │ │ │ - │ │ │ │ │ - oRequest._object.onreadystatechange = function() { │ │ │ │ │ - // Synchronize state │ │ │ │ │ - oRequest.readyState = oRequest._object.readyState; │ │ │ │ │ - │ │ │ │ │ - if (oRequest._aborted) { │ │ │ │ │ - // │ │ │ │ │ - oRequest.readyState = cXMLHttpRequest.UNSENT; │ │ │ │ │ - │ │ │ │ │ - // Return │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (oRequest.readyState == cXMLHttpRequest.DONE) { │ │ │ │ │ - // Clean Object │ │ │ │ │ - fCleanTransport(oRequest); │ │ │ │ │ - │ │ │ │ │ - // get cached request │ │ │ │ │ - if (oRequest.status == 304) │ │ │ │ │ - oRequest._object = oRequest._cached; │ │ │ │ │ - │ │ │ │ │ - // │ │ │ │ │ - delete oRequest._cached; │ │ │ │ │ - │ │ │ │ │ - // │ │ │ │ │ - fSynchronizeValues(oRequest); │ │ │ │ │ - │ │ │ │ │ - // │ │ │ │ │ - fReadyStateChange(oRequest); │ │ │ │ │ - │ │ │ │ │ - // BUGFIX: IE - memory leak in interrupted │ │ │ │ │ - if (bIE && bAsync) │ │ │ │ │ - window.detachEvent("onunload", fOnUnload); │ │ │ │ │ - } │ │ │ │ │ - }; │ │ │ │ │ - oRequest._object.send(null); │ │ │ │ │ - │ │ │ │ │ - // Return now - wait until re-sent request is finished │ │ │ │ │ - return; │ │ │ │ │ - }; │ │ │ │ │ - */ │ │ │ │ │ - // BUGFIX: IE - memory leak in interrupted │ │ │ │ │ - if (bIE && bAsync) │ │ │ │ │ - window.detachEvent("onunload", fOnUnload); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice │ │ │ │ │ - if (nState != oRequest.readyState) │ │ │ │ │ - fReadyStateChange(oRequest); │ │ │ │ │ - │ │ │ │ │ - nState = oRequest.readyState; │ │ │ │ │ - } │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - function fXMLHttpRequest_send(oRequest) { │ │ │ │ │ - oRequest._object.send(oRequest._data); │ │ │ │ │ - │ │ │ │ │ - // BUGFIX: Gecko - missing readystatechange calls in synchronous requests │ │ │ │ │ - if (bGecko && !oRequest._async) { │ │ │ │ │ - oRequest.readyState = cXMLHttpRequest.OPENED; │ │ │ │ │ - │ │ │ │ │ - // Synchronize state │ │ │ │ │ - fSynchronizeValues(oRequest); │ │ │ │ │ - │ │ │ │ │ - // Simulate missing states │ │ │ │ │ - while (oRequest.readyState < cXMLHttpRequest.DONE) { │ │ │ │ │ - oRequest.readyState++; │ │ │ │ │ - fReadyStateChange(oRequest); │ │ │ │ │ - // Check if we are aborted │ │ │ │ │ - if (oRequest._aborted) │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }; │ │ │ │ │ - cXMLHttpRequest.prototype.send = function(vData) { │ │ │ │ │ - // Add method sniffer │ │ │ │ │ - if (cXMLHttpRequest.onsend) │ │ │ │ │ - cXMLHttpRequest.onsend.apply(this, arguments); │ │ │ │ │ - │ │ │ │ │ - if (!arguments.length) │ │ │ │ │ - vData = null; │ │ │ │ │ - │ │ │ │ │ - // BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required │ │ │ │ │ - // BUGFIX: IE - rewrites any custom mime-type to "text/xml" in case an XMLNode is sent │ │ │ │ │ - // BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard) │ │ │ │ │ - if (vData && vData.nodeType) { │ │ │ │ │ - vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml; │ │ │ │ │ - if (!this._headers["Content-Type"]) │ │ │ │ │ - this._object.setRequestHeader("Content-Type", "application/xml"); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - this._data = vData; │ │ │ │ │ - /* │ │ │ │ │ - // Add to queue │ │ │ │ │ - if (this._async) │ │ │ │ │ - fQueue_add(this); │ │ │ │ │ - else*/ │ │ │ │ │ - fXMLHttpRequest_send(this); │ │ │ │ │ - }; │ │ │ │ │ - cXMLHttpRequest.prototype.abort = function() { │ │ │ │ │ - // Add method sniffer │ │ │ │ │ - if (cXMLHttpRequest.onabort) │ │ │ │ │ - cXMLHttpRequest.onabort.apply(this, arguments); │ │ │ │ │ - │ │ │ │ │ - // BUGFIX: Gecko - unnecessary DONE when aborting │ │ │ │ │ - if (this.readyState > cXMLHttpRequest.UNSENT) │ │ │ │ │ - this._aborted = true; │ │ │ │ │ - │ │ │ │ │ - this._object.abort(); │ │ │ │ │ - │ │ │ │ │ - // BUGFIX: IE - memory leak │ │ │ │ │ - fCleanTransport(this); │ │ │ │ │ - │ │ │ │ │ - this.readyState = cXMLHttpRequest.UNSENT; │ │ │ │ │ - │ │ │ │ │ - delete this._data; │ │ │ │ │ - /* if (this._async) │ │ │ │ │ - fQueue_remove(this);*/ │ │ │ │ │ - }; │ │ │ │ │ - cXMLHttpRequest.prototype.getAllResponseHeaders = function() { │ │ │ │ │ - return this._object.getAllResponseHeaders(); │ │ │ │ │ - }; │ │ │ │ │ - cXMLHttpRequest.prototype.getResponseHeader = function(sName) { │ │ │ │ │ - return this._object.getResponseHeader(sName); │ │ │ │ │ - }; │ │ │ │ │ - cXMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) { │ │ │ │ │ - // BUGFIX: IE - cache issue │ │ │ │ │ - if (!this._headers) │ │ │ │ │ - this._headers = {}; │ │ │ │ │ - this._headers[sName] = sValue; │ │ │ │ │ - │ │ │ │ │ - return this._object.setRequestHeader(sName, sValue); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - // EventTarget interface implementation │ │ │ │ │ - cXMLHttpRequest.prototype.addEventListener = function(sName, fHandler, bUseCapture) { │ │ │ │ │ - for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) │ │ │ │ │ - if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture) │ │ │ │ │ - return; │ │ │ │ │ - // Add listener │ │ │ │ │ - this._listeners.push([sName, fHandler, bUseCapture]); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - cXMLHttpRequest.prototype.removeEventListener = function(sName, fHandler, bUseCapture) { │ │ │ │ │ - for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) │ │ │ │ │ - if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture) │ │ │ │ │ - break; │ │ │ │ │ - // Remove listener │ │ │ │ │ - if (oListener) │ │ │ │ │ - this._listeners.splice(nIndex, 1); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - cXMLHttpRequest.prototype.dispatchEvent = function(oEvent) { │ │ │ │ │ - var oEventPseudo = { │ │ │ │ │ - 'type': oEvent.type, │ │ │ │ │ - 'target': this, │ │ │ │ │ - 'currentTarget': this, │ │ │ │ │ - 'eventPhase': 2, │ │ │ │ │ - 'bubbles': oEvent.bubbles, │ │ │ │ │ - 'cancelable': oEvent.cancelable, │ │ │ │ │ - 'timeStamp': oEvent.timeStamp, │ │ │ │ │ - 'stopPropagation': function() {}, // There is no flow │ │ │ │ │ - 'preventDefault': function() {}, // There is no default action │ │ │ │ │ - 'initEvent': function() {} // Original event object should be initialized │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - // Execute onreadystatechange │ │ │ │ │ - if (oEventPseudo.type == "readystatechange" && this.onreadystatechange) │ │ │ │ │ - (this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]); │ │ │ │ │ - │ │ │ │ │ - // Execute listeners │ │ │ │ │ - for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) │ │ │ │ │ - if (oListener[0] == oEventPseudo.type && !oListener[2]) │ │ │ │ │ - (oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - // │ │ │ │ │ - cXMLHttpRequest.prototype.toString = function() { │ │ │ │ │ - return '[' + "object" + ' ' + "XMLHttpRequest" + ']'; │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - cXMLHttpRequest.toString = function() { │ │ │ │ │ - return '[' + "XMLHttpRequest" + ']'; │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - // Helper function │ │ │ │ │ - function fReadyStateChange(oRequest) { │ │ │ │ │ - // Sniffing code │ │ │ │ │ - if (cXMLHttpRequest.onreadystatechange) │ │ │ │ │ - cXMLHttpRequest.onreadystatechange.apply(oRequest); │ │ │ │ │ - │ │ │ │ │ - // Fake event │ │ │ │ │ - oRequest.dispatchEvent({ │ │ │ │ │ - 'type': "readystatechange", │ │ │ │ │ - 'bubbles': false, │ │ │ │ │ - 'cancelable': false, │ │ │ │ │ - 'timeStamp': new Date + 0 │ │ │ │ │ - }); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - function fGetDocument(oRequest) { │ │ │ │ │ - var oDocument = oRequest.responseXML, │ │ │ │ │ - sResponse = oRequest.responseText; │ │ │ │ │ - // Try parsing responseText │ │ │ │ │ - if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) { │ │ │ │ │ - oDocument = new window.ActiveXObject("Microsoft.XMLDOM"); │ │ │ │ │ - oDocument.async = false; │ │ │ │ │ - oDocument.validateOnParse = false; │ │ │ │ │ - oDocument.loadXML(sResponse); │ │ │ │ │ - } │ │ │ │ │ - // Check if there is no error in document │ │ │ │ │ - if (oDocument) │ │ │ │ │ - if ((bIE && oDocument.parseError != 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror")) │ │ │ │ │ - return null; │ │ │ │ │ - return oDocument; │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - function fSynchronizeValues(oRequest) { │ │ │ │ │ - try { │ │ │ │ │ - oRequest.responseText = oRequest._object.responseText; │ │ │ │ │ - } catch (e) {} │ │ │ │ │ - try { │ │ │ │ │ - oRequest.responseXML = fGetDocument(oRequest._object); │ │ │ │ │ - } catch (e) {} │ │ │ │ │ - try { │ │ │ │ │ - oRequest.status = oRequest._object.status; │ │ │ │ │ - } catch (e) {} │ │ │ │ │ - try { │ │ │ │ │ - oRequest.statusText = oRequest._object.statusText; │ │ │ │ │ - } catch (e) {} │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - function fCleanTransport(oRequest) { │ │ │ │ │ - // BUGFIX: IE - memory leak (on-page leak) │ │ │ │ │ - oRequest._object.onreadystatechange = new window.Function; │ │ │ │ │ - }; │ │ │ │ │ - /* │ │ │ │ │ - // Queue manager │ │ │ │ │ - var oQueuePending = {"CRITICAL":[],"HIGH":[],"NORMAL":[],"LOW":[],"LOWEST":[]}, │ │ │ │ │ - aQueueRunning = []; │ │ │ │ │ - function fQueue_add(oRequest) { │ │ │ │ │ - oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : "NORMAL"].push(oRequest); │ │ │ │ │ - // │ │ │ │ │ - setTimeout(fQueue_process); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - function fQueue_remove(oRequest) { │ │ │ │ │ - for (var nIndex = 0, bFound = false; nIndex < aQueueRunning.length; nIndex++) │ │ │ │ │ - if (bFound) │ │ │ │ │ - aQueueRunning[nIndex - 1] = aQueueRunning[nIndex]; │ │ │ │ │ - else │ │ │ │ │ - if (aQueueRunning[nIndex] == oRequest) │ │ │ │ │ - bFound = true; │ │ │ │ │ - if (bFound) │ │ │ │ │ - aQueueRunning.length--; │ │ │ │ │ - // │ │ │ │ │ - setTimeout(fQueue_process); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - function fQueue_process() { │ │ │ │ │ - if (aQueueRunning.length < 6) { │ │ │ │ │ - for (var sPriority in oQueuePending) { │ │ │ │ │ - if (oQueuePending[sPriority].length) { │ │ │ │ │ - var oRequest = oQueuePending[sPriority][0]; │ │ │ │ │ - oQueuePending[sPriority] = oQueuePending[sPriority].slice(1); │ │ │ │ │ - // │ │ │ │ │ - aQueueRunning.push(oRequest); │ │ │ │ │ - // Send request │ │ │ │ │ - fXMLHttpRequest_send(oRequest); │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }; │ │ │ │ │ - */ │ │ │ │ │ - // Internet Explorer 5.0 (missing apply) │ │ │ │ │ - if (!window.Function.prototype.apply) { │ │ │ │ │ - window.Function.prototype.apply = function(oRequest, oArguments) { │ │ │ │ │ - if (!oArguments) │ │ │ │ │ - oArguments = []; │ │ │ │ │ - oRequest.__func = this; │ │ │ │ │ - oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]); │ │ │ │ │ - delete oRequest.__func; │ │ │ │ │ - }; │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - // Register new object with window │ │ │ │ │ - /** │ │ │ │ │ - * Class: OpenLayers.Request.XMLHttpRequest │ │ │ │ │ - * Standard-compliant (W3C) cross-browser implementation of the │ │ │ │ │ - * XMLHttpRequest object. From │ │ │ │ │ - * http://code.google.com/p/xmlhttprequest/. │ │ │ │ │ - */ │ │ │ │ │ - if (!OpenLayers.Request) { │ │ │ │ │ - /** │ │ │ │ │ - * This allows for OpenLayers/Request.js to be included │ │ │ │ │ - * before or after this script. │ │ │ │ │ - */ │ │ │ │ │ - OpenLayers.Request = {}; │ │ │ │ │ - } │ │ │ │ │ - OpenLayers.Request.XMLHttpRequest = cXMLHttpRequest; │ │ │ │ │ -})(); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Request.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Events.js │ │ │ │ │ - * @requires OpenLayers/Request/XMLHttpRequest.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * TODO: deprecate me │ │ │ │ │ - * Use OpenLayers.Request.proxy instead. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.ProxyHost = ""; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Namespace: OpenLayers.Request │ │ │ │ │ - * The OpenLayers.Request namespace contains convenience methods for working │ │ │ │ │ - * with XMLHttpRequests. These methods work with a cross-browser │ │ │ │ │ - * W3C compliant class. │ │ │ │ │ - */ │ │ │ │ │ -if (!OpenLayers.Request) { │ │ │ │ │ - /** │ │ │ │ │ - * This allows for OpenLayers/Request/XMLHttpRequest.js to be included │ │ │ │ │ - * before or after this script. │ │ │ │ │ - */ │ │ │ │ │ - OpenLayers.Request = {}; │ │ │ │ │ -} │ │ │ │ │ -OpenLayers.Util.extend(OpenLayers.Request, { │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: DEFAULT_CONFIG │ │ │ │ │ - * {Object} Default configuration for all requests. │ │ │ │ │ - */ │ │ │ │ │ - DEFAULT_CONFIG: { │ │ │ │ │ - method: "GET", │ │ │ │ │ - url: window.location.href, │ │ │ │ │ - async: true, │ │ │ │ │ - user: undefined, │ │ │ │ │ - password: undefined, │ │ │ │ │ - params: null, │ │ │ │ │ - proxy: OpenLayers.ProxyHost, │ │ │ │ │ - headers: {}, │ │ │ │ │ - data: null, │ │ │ │ │ - callback: function() {}, │ │ │ │ │ - success: null, │ │ │ │ │ - failure: null, │ │ │ │ │ - scope: null │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constant: URL_SPLIT_REGEX │ │ │ │ │ - */ │ │ │ │ │ - URL_SPLIT_REGEX: /([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: events │ │ │ │ │ - * {} An events object that handles all │ │ │ │ │ - * events on the {} object. │ │ │ │ │ - * │ │ │ │ │ - * All event listeners will receive an event object with three properties: │ │ │ │ │ - * request - {} The request object. │ │ │ │ │ - * config - {Object} The config object sent to the specific request method. │ │ │ │ │ - * requestUrl - {String} The request url. │ │ │ │ │ - * │ │ │ │ │ - * Supported event types: │ │ │ │ │ - * complete - Triggered when we have a response from the request, if a │ │ │ │ │ - * listener returns false, no further response processing will take │ │ │ │ │ - * place. │ │ │ │ │ - * success - Triggered when the HTTP response has a success code (200-299). │ │ │ │ │ - * failure - Triggered when the HTTP response does not have a success code. │ │ │ │ │ - */ │ │ │ │ │ - events: new OpenLayers.Events(this), │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: makeSameOrigin │ │ │ │ │ - * Using the specified proxy, returns a same origin url of the provided url. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * url - {String} An arbitrary url │ │ │ │ │ - * proxy {String|Function} The proxy to use to make the provided url a │ │ │ │ │ - * same origin url. │ │ │ │ │ - * │ │ │ │ │ - * Returns │ │ │ │ │ - * {String} the same origin url. If no proxy is provided, the returned url │ │ │ │ │ - * will be the same as the provided url. │ │ │ │ │ - */ │ │ │ │ │ - makeSameOrigin: function(url, proxy) { │ │ │ │ │ - var sameOrigin = url.indexOf("http") !== 0; │ │ │ │ │ - var urlParts = !sameOrigin && url.match(this.URL_SPLIT_REGEX); │ │ │ │ │ - if (urlParts) { │ │ │ │ │ - var location = window.location; │ │ │ │ │ - sameOrigin = │ │ │ │ │ - urlParts[1] == location.protocol && │ │ │ │ │ - urlParts[3] == location.hostname; │ │ │ │ │ - var uPort = urlParts[4], │ │ │ │ │ - lPort = location.port; │ │ │ │ │ - if (uPort != 80 && uPort != "" || lPort != "80" && lPort != "") { │ │ │ │ │ - sameOrigin = sameOrigin && uPort == lPort; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - if (!sameOrigin) { │ │ │ │ │ - if (proxy) { │ │ │ │ │ - if (typeof proxy == "function") { │ │ │ │ │ - url = proxy(url); │ │ │ │ │ - } else { │ │ │ │ │ - url = proxy + encodeURIComponent(url); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return url; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: issue │ │ │ │ │ - * Create a new XMLHttpRequest object, open it, set any headers, bind │ │ │ │ │ - * a callback to done state, and send any data. It is recommended that │ │ │ │ │ - * you use one , , , , , or . │ │ │ │ │ - * This method is only documented to provide detail on the configuration │ │ │ │ │ - * options available to all request methods. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} Object containing properties for configuring the │ │ │ │ │ - * request. Allowed configuration properties are described below. │ │ │ │ │ - * This object is modified and should not be reused. │ │ │ │ │ - * │ │ │ │ │ - * Allowed config properties: │ │ │ │ │ - * method - {String} One of GET, POST, PUT, DELETE, HEAD, or │ │ │ │ │ - * OPTIONS. Default is GET. │ │ │ │ │ - * url - {String} URL for the request. │ │ │ │ │ - * async - {Boolean} Open an asynchronous request. Default is true. │ │ │ │ │ - * user - {String} User for relevant authentication scheme. Set │ │ │ │ │ - * to null to clear current user. │ │ │ │ │ - * password - {String} Password for relevant authentication scheme. │ │ │ │ │ - * Set to null to clear current password. │ │ │ │ │ - * proxy - {String} Optional proxy. Defaults to │ │ │ │ │ - * . │ │ │ │ │ - * params - {Object} Any key:value pairs to be appended to the │ │ │ │ │ - * url as a query string. Assumes url doesn't already include a query │ │ │ │ │ - * string or hash. Typically, this is only appropriate for │ │ │ │ │ - * requests where the query string will be appended to the url. │ │ │ │ │ - * Parameter values that are arrays will be │ │ │ │ │ - * concatenated with a comma (note that this goes against form-encoding) │ │ │ │ │ - * as is done with . │ │ │ │ │ - * headers - {Object} Object with header:value pairs to be set on │ │ │ │ │ - * the request. │ │ │ │ │ - * data - {String | Document} Optional data to send with the request. │ │ │ │ │ - * Typically, this is only used with and requests. │ │ │ │ │ - * Make sure to provide the appropriate "Content-Type" header for your │ │ │ │ │ - * data. For and requests, the content type defaults to │ │ │ │ │ - * "application-xml". If your data is a different content type, or │ │ │ │ │ - * if you are using a different HTTP method, set the "Content-Type" │ │ │ │ │ - * header to match your data type. │ │ │ │ │ - * callback - {Function} Function to call when request is done. │ │ │ │ │ - * To determine if the request failed, check request.status (200 │ │ │ │ │ - * indicates success). │ │ │ │ │ - * success - {Function} Optional function to call if request status is in │ │ │ │ │ - * the 200s. This will be called in addition to callback above and │ │ │ │ │ - * would typically only be used as an alternative. │ │ │ │ │ - * failure - {Function} Optional function to call if request status is not │ │ │ │ │ - * in the 200s. This will be called in addition to callback above and │ │ │ │ │ - * would typically only be used as an alternative. │ │ │ │ │ - * scope - {Object} If callback is a public method on some object, │ │ │ │ │ - * set the scope to that object. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {XMLHttpRequest} Request object. To abort the request before a response │ │ │ │ │ - * is received, call abort() on the request object. │ │ │ │ │ - */ │ │ │ │ │ - issue: function(config) { │ │ │ │ │ - // apply default config - proxy host may have changed │ │ │ │ │ - var defaultConfig = OpenLayers.Util.extend( │ │ │ │ │ - this.DEFAULT_CONFIG, { │ │ │ │ │ - proxy: OpenLayers.ProxyHost │ │ │ │ │ - } │ │ │ │ │ - ); │ │ │ │ │ - config = config || {}; │ │ │ │ │ - config.headers = config.headers || {}; │ │ │ │ │ - config = OpenLayers.Util.applyDefaults(config, defaultConfig); │ │ │ │ │ - config.headers = OpenLayers.Util.applyDefaults(config.headers, defaultConfig.headers); │ │ │ │ │ - // Always set the "X-Requested-With" header to signal that this request │ │ │ │ │ - // was issued through the XHR-object. Since header keys are case │ │ │ │ │ - // insensitive and we want to allow overriding of the "X-Requested-With" │ │ │ │ │ - // header through the user we cannot use applyDefaults, but have to │ │ │ │ │ - // check manually whether we were called with a "X-Requested-With" │ │ │ │ │ - // header. │ │ │ │ │ - var customRequestedWithHeader = false, │ │ │ │ │ - headerKey; │ │ │ │ │ - for (headerKey in config.headers) { │ │ │ │ │ - if (config.headers.hasOwnProperty(headerKey)) { │ │ │ │ │ - if (headerKey.toLowerCase() === 'x-requested-with') { │ │ │ │ │ - customRequestedWithHeader = true; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - if (customRequestedWithHeader === false) { │ │ │ │ │ - // we did not have a custom "X-Requested-With" header │ │ │ │ │ - config.headers['X-Requested-With'] = 'XMLHttpRequest'; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // create request, open, and set headers │ │ │ │ │ - var request = new OpenLayers.Request.XMLHttpRequest(); │ │ │ │ │ - var url = OpenLayers.Util.urlAppend(config.url, │ │ │ │ │ - OpenLayers.Util.getParameterString(config.params || {})); │ │ │ │ │ - url = OpenLayers.Request.makeSameOrigin(url, config.proxy); │ │ │ │ │ - request.open( │ │ │ │ │ - config.method, url, config.async, config.user, config.password │ │ │ │ │ - ); │ │ │ │ │ - for (var header in config.headers) { │ │ │ │ │ - request.setRequestHeader(header, config.headers[header]); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - var events = this.events; │ │ │ │ │ - │ │ │ │ │ - // we want to execute runCallbacks with "this" as the │ │ │ │ │ - // execution scope │ │ │ │ │ - var self = this; │ │ │ │ │ - │ │ │ │ │ - request.onreadystatechange = function() { │ │ │ │ │ - if (request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) { │ │ │ │ │ - var proceed = events.triggerEvent( │ │ │ │ │ - "complete", { │ │ │ │ │ - request: request, │ │ │ │ │ - config: config, │ │ │ │ │ - requestUrl: url │ │ │ │ │ - } │ │ │ │ │ - ); │ │ │ │ │ - if (proceed !== false) { │ │ │ │ │ - self.runCallbacks({ │ │ │ │ │ - request: request, │ │ │ │ │ - config: config, │ │ │ │ │ - requestUrl: url │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - // send request (optionally with data) and return │ │ │ │ │ - // call in a timeout for asynchronous requests so the return is │ │ │ │ │ - // available before readyState == 4 for cached docs │ │ │ │ │ - if (config.async === false) { │ │ │ │ │ - request.send(config.data); │ │ │ │ │ - } else { │ │ │ │ │ - window.setTimeout(function() { │ │ │ │ │ - if (request.readyState !== 0) { // W3C: 0-UNSENT │ │ │ │ │ - request.send(config.data); │ │ │ │ │ - } │ │ │ │ │ - }, 0); │ │ │ │ │ - } │ │ │ │ │ - return request; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: runCallbacks │ │ │ │ │ - * Calls the complete, success and failure callbacks. Application │ │ │ │ │ - * can listen to the "complete" event, have the listener │ │ │ │ │ - * display a confirm window and always return false, and │ │ │ │ │ - * execute OpenLayers.Request.runCallbacks if the user │ │ │ │ │ - * hits "yes" in the confirm window. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} Hash containing request, config and requestUrl keys │ │ │ │ │ - */ │ │ │ │ │ - runCallbacks: function(options) { │ │ │ │ │ - var request = options.request; │ │ │ │ │ - var config = options.config; │ │ │ │ │ - │ │ │ │ │ - // bind callbacks to readyState 4 (done) │ │ │ │ │ - var complete = (config.scope) ? │ │ │ │ │ - OpenLayers.Function.bind(config.callback, config.scope) : │ │ │ │ │ - config.callback; │ │ │ │ │ - │ │ │ │ │ - // optional success callback │ │ │ │ │ - var success; │ │ │ │ │ - if (config.success) { │ │ │ │ │ - success = (config.scope) ? │ │ │ │ │ - OpenLayers.Function.bind(config.success, config.scope) : │ │ │ │ │ - config.success; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // optional failure callback │ │ │ │ │ - var failure; │ │ │ │ │ - if (config.failure) { │ │ │ │ │ - failure = (config.scope) ? │ │ │ │ │ - OpenLayers.Function.bind(config.failure, config.scope) : │ │ │ │ │ - config.failure; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (OpenLayers.Util.createUrlObject(config.url).protocol == "file:" && │ │ │ │ │ - request.responseText) { │ │ │ │ │ - request.status = 200; │ │ │ │ │ - } │ │ │ │ │ - complete(request); │ │ │ │ │ - │ │ │ │ │ - if (!request.status || (request.status >= 200 && request.status < 300)) { │ │ │ │ │ - this.events.triggerEvent("success", options); │ │ │ │ │ - if (success) { │ │ │ │ │ - success(request); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - if (request.status && (request.status < 200 || request.status >= 300)) { │ │ │ │ │ - this.events.triggerEvent("failure", options); │ │ │ │ │ - if (failure) { │ │ │ │ │ - failure(request); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: GET │ │ │ │ │ - * Send an HTTP GET request. Additional configuration properties are │ │ │ │ │ - * documented in the method, with the method property set │ │ │ │ │ - * to GET. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} Object with properties for configuring the request. │ │ │ │ │ - * See the method for documentation of allowed properties. │ │ │ │ │ - * This object is modified and should not be reused. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {XMLHttpRequest} Request object. │ │ │ │ │ - */ │ │ │ │ │ - GET: function(config) { │ │ │ │ │ - config = OpenLayers.Util.extend(config, { │ │ │ │ │ - method: "GET" │ │ │ │ │ - }); │ │ │ │ │ - return OpenLayers.Request.issue(config); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: POST │ │ │ │ │ - * Send a POST request. Additional configuration properties are │ │ │ │ │ - * documented in the method, with the method property set │ │ │ │ │ - * to POST and "Content-Type" header set to "application/xml". │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} Object with properties for configuring the request. │ │ │ │ │ - * See the method for documentation of allowed properties. The │ │ │ │ │ - * default "Content-Type" header will be set to "application-xml" if │ │ │ │ │ - * none is provided. This object is modified and should not be reused. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {XMLHttpRequest} Request object. │ │ │ │ │ - */ │ │ │ │ │ - POST: function(config) { │ │ │ │ │ - config = OpenLayers.Util.extend(config, { │ │ │ │ │ - method: "POST" │ │ │ │ │ - }); │ │ │ │ │ - // set content type to application/xml if it isn't already set │ │ │ │ │ - config.headers = config.headers ? config.headers : {}; │ │ │ │ │ - if (!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) { │ │ │ │ │ - config.headers["Content-Type"] = "application/xml"; │ │ │ │ │ - } │ │ │ │ │ - return OpenLayers.Request.issue(config); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: PUT │ │ │ │ │ - * Send an HTTP PUT request. Additional configuration properties are │ │ │ │ │ - * documented in the method, with the method property set │ │ │ │ │ - * to PUT and "Content-Type" header set to "application/xml". │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} Object with properties for configuring the request. │ │ │ │ │ - * See the method for documentation of allowed properties. The │ │ │ │ │ - * default "Content-Type" header will be set to "application-xml" if │ │ │ │ │ - * none is provided. This object is modified and should not be reused. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {XMLHttpRequest} Request object. │ │ │ │ │ - */ │ │ │ │ │ - PUT: function(config) { │ │ │ │ │ - config = OpenLayers.Util.extend(config, { │ │ │ │ │ - method: "PUT" │ │ │ │ │ - }); │ │ │ │ │ - // set content type to application/xml if it isn't already set │ │ │ │ │ - config.headers = config.headers ? config.headers : {}; │ │ │ │ │ - if (!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) { │ │ │ │ │ - config.headers["Content-Type"] = "application/xml"; │ │ │ │ │ - } │ │ │ │ │ - return OpenLayers.Request.issue(config); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: DELETE │ │ │ │ │ - * Send an HTTP DELETE request. Additional configuration properties are │ │ │ │ │ - * documented in the method, with the method property set │ │ │ │ │ - * to DELETE. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} Object with properties for configuring the request. │ │ │ │ │ - * See the method for documentation of allowed properties. │ │ │ │ │ - * This object is modified and should not be reused. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {XMLHttpRequest} Request object. │ │ │ │ │ - */ │ │ │ │ │ - DELETE: function(config) { │ │ │ │ │ - config = OpenLayers.Util.extend(config, { │ │ │ │ │ - method: "DELETE" │ │ │ │ │ - }); │ │ │ │ │ - return OpenLayers.Request.issue(config); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: HEAD │ │ │ │ │ - * Send an HTTP HEAD request. Additional configuration properties are │ │ │ │ │ - * documented in the method, with the method property set │ │ │ │ │ - * to HEAD. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} Object with properties for configuring the request. │ │ │ │ │ - * See the method for documentation of allowed properties. │ │ │ │ │ - * This object is modified and should not be reused. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {XMLHttpRequest} Request object. │ │ │ │ │ - */ │ │ │ │ │ - HEAD: function(config) { │ │ │ │ │ - config = OpenLayers.Util.extend(config, { │ │ │ │ │ - method: "HEAD" │ │ │ │ │ - }); │ │ │ │ │ - return OpenLayers.Request.issue(config); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: OPTIONS │ │ │ │ │ - * Send an HTTP OPTIONS request. Additional configuration properties are │ │ │ │ │ - * documented in the method, with the method property set │ │ │ │ │ - * to OPTIONS. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} Object with properties for configuring the request. │ │ │ │ │ - * See the method for documentation of allowed properties. │ │ │ │ │ - * This object is modified and should not be reused. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {XMLHttpRequest} Request object. │ │ │ │ │ - */ │ │ │ │ │ - OPTIONS: function(config) { │ │ │ │ │ - config = OpenLayers.Util.extend(config, { │ │ │ │ │ - method: "OPTIONS" │ │ │ │ │ - }); │ │ │ │ │ - return OpenLayers.Request.issue(config); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ -}); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ OpenLayers/WPSProcess.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ @@ -20655,400 +21184,178 @@ │ │ │ │ │ OpenLayers.Util.extend(this, options); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ CLASS_NAME: "OpenLayers.WPSProcess.ChainLink" │ │ │ │ │ │ │ │ │ │ }); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Symbolizer.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Symbolizer │ │ │ │ │ - * Base class representing a symbolizer used for feature rendering. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Symbolizer = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: zIndex │ │ │ │ │ - * {Number} The zIndex determines the rendering order for a symbolizer. │ │ │ │ │ - * Symbolizers with larger zIndex values are rendered over symbolizers │ │ │ │ │ - * with smaller zIndex values. Default is 0. │ │ │ │ │ - */ │ │ │ │ │ - zIndex: 0, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Symbolizer │ │ │ │ │ - * Instances of this class are not useful. See one of the subclasses. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} An object containing properties to be set on the │ │ │ │ │ - * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ - * construction. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * A new symbolizer. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(config) { │ │ │ │ │ - OpenLayers.Util.extend(this, config); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: clone │ │ │ │ │ - * Create a copy of this symbolizer. │ │ │ │ │ - * │ │ │ │ │ - * Returns a symbolizer of the same type with the same properties. │ │ │ │ │ - */ │ │ │ │ │ - clone: function() { │ │ │ │ │ - var Type = eval(this.CLASS_NAME); │ │ │ │ │ - return new Type(OpenLayers.Util.extend({}, this)); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Symbolizer" │ │ │ │ │ - │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Projection.js │ │ │ │ │ + OpenLayers/StyleMap.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - * @requires OpenLayers/Util.js │ │ │ │ │ + * @requires OpenLayers/Style.js │ │ │ │ │ + * @requires OpenLayers/Feature/Vector.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Namespace: OpenLayers.Projection │ │ │ │ │ - * Methods for coordinate transforms between coordinate systems. By default, │ │ │ │ │ - * OpenLayers ships with the ability to transform coordinates between │ │ │ │ │ - * geographic (EPSG:4326) and web or spherical mercator (EPSG:900913 et al.) │ │ │ │ │ - * coordinate reference systems. See the method for details │ │ │ │ │ - * on usage. │ │ │ │ │ - * │ │ │ │ │ - * Additional transforms may be added by using the │ │ │ │ │ - * library. If the proj4js library is included, the method │ │ │ │ │ - * will work between any two coordinate reference systems with proj4js │ │ │ │ │ - * definitions. │ │ │ │ │ - * │ │ │ │ │ - * If the proj4js library is not included, or if you wish to allow transforms │ │ │ │ │ - * between arbitrary coordinate reference systems, use the │ │ │ │ │ - * method to register a custom transform method. │ │ │ │ │ + * Class: OpenLayers.StyleMap │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Projection = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: proj │ │ │ │ │ - * {Object} Proj4js.Proj instance. │ │ │ │ │ - */ │ │ │ │ │ - proj: null, │ │ │ │ │ +OpenLayers.StyleMap = OpenLayers.Class({ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: projCode │ │ │ │ │ - * {String} │ │ │ │ │ + * Property: styles │ │ │ │ │ + * {Object} Hash of {}, keyed by names of well known │ │ │ │ │ + * rendering intents (e.g. "default", "temporary", "select", "delete"). │ │ │ │ │ */ │ │ │ │ │ - projCode: null, │ │ │ │ │ + styles: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: titleRegEx │ │ │ │ │ - * {RegExp} regular expression to strip the title from a proj4js definition │ │ │ │ │ + * Property: extendDefault │ │ │ │ │ + * {Boolean} if true, every render intent will extend the symbolizers │ │ │ │ │ + * specified for the "default" intent at rendering time. Otherwise, every │ │ │ │ │ + * rendering intent will be treated as a completely independent style. │ │ │ │ │ */ │ │ │ │ │ - titleRegEx: /\+title=[^\+]*/, │ │ │ │ │ + extendDefault: true, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Projection │ │ │ │ │ - * This class offers several methods for interacting with a wrapped │ │ │ │ │ - * pro4js projection object. │ │ │ │ │ - * │ │ │ │ │ + * Constructor: OpenLayers.StyleMap │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * projCode - {String} A string identifying the Well Known Identifier for │ │ │ │ │ - * the projection. │ │ │ │ │ - * options - {Object} An optional object to set additional properties │ │ │ │ │ - * on the projection. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} A projection object. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(projCode, options) { │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - this.projCode = projCode; │ │ │ │ │ - if (typeof Proj4js == "object") { │ │ │ │ │ - this.proj = new Proj4js.Proj(projCode); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: getCode │ │ │ │ │ - * Get the string SRS code. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} The SRS code. │ │ │ │ │ + * style - {Object} Optional. Either a style hash, or a style object, or │ │ │ │ │ + * a hash of style objects (style hashes) keyed by rendering │ │ │ │ │ + * intent. If just one style hash or style object is passed, │ │ │ │ │ + * this will be used for all known render intents (default, │ │ │ │ │ + * select, temporary) │ │ │ │ │ + * options - {Object} optional hash of additional options for this │ │ │ │ │ + * instance │ │ │ │ │ */ │ │ │ │ │ - getCode: function() { │ │ │ │ │ - return this.proj ? this.proj.srsCode : this.projCode; │ │ │ │ │ - }, │ │ │ │ │ + initialize: function(style, options) { │ │ │ │ │ + this.styles = { │ │ │ │ │ + "default": new OpenLayers.Style( │ │ │ │ │ + OpenLayers.Feature.Vector.style["default"]), │ │ │ │ │ + "select": new OpenLayers.Style( │ │ │ │ │ + OpenLayers.Feature.Vector.style["select"]), │ │ │ │ │ + "temporary": new OpenLayers.Style( │ │ │ │ │ + OpenLayers.Feature.Vector.style["temporary"]), │ │ │ │ │ + "delete": new OpenLayers.Style( │ │ │ │ │ + OpenLayers.Feature.Vector.style["delete"]) │ │ │ │ │ + }; │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: getUnits │ │ │ │ │ - * Get the units string for the projection -- returns null if │ │ │ │ │ - * proj4js is not available. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} The units abbreviation. │ │ │ │ │ - */ │ │ │ │ │ - getUnits: function() { │ │ │ │ │ - return this.proj ? this.proj.units : null; │ │ │ │ │ + // take whatever the user passed as style parameter and convert it │ │ │ │ │ + // into parts of stylemap. │ │ │ │ │ + if (style instanceof OpenLayers.Style) { │ │ │ │ │ + // user passed a style object │ │ │ │ │ + this.styles["default"] = style; │ │ │ │ │ + this.styles["select"] = style; │ │ │ │ │ + this.styles["temporary"] = style; │ │ │ │ │ + this.styles["delete"] = style; │ │ │ │ │ + } else if (typeof style == "object") { │ │ │ │ │ + for (var key in style) { │ │ │ │ │ + if (style[key] instanceof OpenLayers.Style) { │ │ │ │ │ + // user passed a hash of style objects │ │ │ │ │ + this.styles[key] = style[key]; │ │ │ │ │ + } else if (typeof style[key] == "object") { │ │ │ │ │ + // user passsed a hash of style hashes │ │ │ │ │ + this.styles[key] = new OpenLayers.Style(style[key]); │ │ │ │ │ + } else { │ │ │ │ │ + // user passed a style hash (i.e. symbolizer) │ │ │ │ │ + this.styles["default"] = new OpenLayers.Style(style); │ │ │ │ │ + this.styles["select"] = new OpenLayers.Style(style); │ │ │ │ │ + this.styles["temporary"] = new OpenLayers.Style(style); │ │ │ │ │ + this.styles["delete"] = new OpenLayers.Style(style); │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: toString │ │ │ │ │ - * Convert projection to string (getCode wrapper). │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} The projection code. │ │ │ │ │ + * Method: destroy │ │ │ │ │ */ │ │ │ │ │ - toString: function() { │ │ │ │ │ - return this.getCode(); │ │ │ │ │ + destroy: function() { │ │ │ │ │ + for (var key in this.styles) { │ │ │ │ │ + this.styles[key].destroy(); │ │ │ │ │ + } │ │ │ │ │ + this.styles = null; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: equals │ │ │ │ │ - * Test equality of two projection instances. Determines equality based │ │ │ │ │ - * soley on the projection code. │ │ │ │ │ - * │ │ │ │ │ + * Method: createSymbolizer │ │ │ │ │ + * Creates the symbolizer for a feature for a render intent. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * feature - {} The feature to evaluate the rules │ │ │ │ │ + * of the intended style against. │ │ │ │ │ + * intent - {String} The intent determines the symbolizer that will be │ │ │ │ │ + * used to draw the feature. Well known intents are "default" │ │ │ │ │ + * (for just drawing the features), "select" (for selected │ │ │ │ │ + * features) and "temporary" (for drawing features). │ │ │ │ │ + * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Boolean} The two projections are equivalent. │ │ │ │ │ - */ │ │ │ │ │ - equals: function(projection) { │ │ │ │ │ - var p = projection, │ │ │ │ │ - equals = false; │ │ │ │ │ - if (p) { │ │ │ │ │ - if (!(p instanceof OpenLayers.Projection)) { │ │ │ │ │ - p = new OpenLayers.Projection(p); │ │ │ │ │ - } │ │ │ │ │ - if ((typeof Proj4js == "object") && this.proj.defData && p.proj.defData) { │ │ │ │ │ - equals = this.proj.defData.replace(this.titleRegEx, "") == │ │ │ │ │ - p.proj.defData.replace(this.titleRegEx, ""); │ │ │ │ │ - } else if (p.getCode) { │ │ │ │ │ - var source = this.getCode(), │ │ │ │ │ - target = p.getCode(); │ │ │ │ │ - equals = source == target || │ │ │ │ │ - !!OpenLayers.Projection.transforms[source] && │ │ │ │ │ - OpenLayers.Projection.transforms[source][target] === │ │ │ │ │ - OpenLayers.Projection.nullTransform; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return equals; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /* Method: destroy │ │ │ │ │ - * Destroy projection object. │ │ │ │ │ + * {Object} symbolizer hash │ │ │ │ │ */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - delete this.proj; │ │ │ │ │ - delete this.projCode; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Projection" │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Property: transforms │ │ │ │ │ - * {Object} Transforms is an object, with from properties, each of which may │ │ │ │ │ - * have a to property. This allows you to define projections without │ │ │ │ │ - * requiring support for proj4js to be included. │ │ │ │ │ - * │ │ │ │ │ - * This object has keys which correspond to a 'source' projection object. The │ │ │ │ │ - * keys should be strings, corresponding to the projection.getCode() value. │ │ │ │ │ - * Each source projection object should have a set of destination projection │ │ │ │ │ - * keys included in the object. │ │ │ │ │ - * │ │ │ │ │ - * Each value in the destination object should be a transformation function, │ │ │ │ │ - * where the function is expected to be passed an object with a .x and a .y │ │ │ │ │ - * property. The function should return the object, with the .x and .y │ │ │ │ │ - * transformed according to the transformation function. │ │ │ │ │ - * │ │ │ │ │ - * Note - Properties on this object should not be set directly. To add a │ │ │ │ │ - * transform method to this object, use the method. For an │ │ │ │ │ - * example of usage, see the OpenLayers.Layer.SphericalMercator file. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Projection.transforms = {}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * APIProperty: defaults │ │ │ │ │ - * {Object} Defaults for the SRS codes known to OpenLayers (currently │ │ │ │ │ - * EPSG:4326, CRS:84, urn:ogc:def:crs:EPSG:6.6:4326, EPSG:900913, EPSG:3857, │ │ │ │ │ - * EPSG:102113 and EPSG:102100). Keys are the SRS code, values are units, │ │ │ │ │ - * maxExtent (the validity extent for the SRS) and yx (true if this SRS is │ │ │ │ │ - * known to have a reverse axis order). │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Projection.defaults = { │ │ │ │ │ - "EPSG:4326": { │ │ │ │ │ - units: "degrees", │ │ │ │ │ - maxExtent: [-180, -90, 180, 90], │ │ │ │ │ - yx: true │ │ │ │ │ - }, │ │ │ │ │ - "CRS:84": { │ │ │ │ │ - units: "degrees", │ │ │ │ │ - maxExtent: [-180, -90, 180, 90] │ │ │ │ │ - }, │ │ │ │ │ - "EPSG:900913": { │ │ │ │ │ - units: "m", │ │ │ │ │ - maxExtent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34] │ │ │ │ │ - } │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * APIMethod: addTransform │ │ │ │ │ - * Set a custom transform method between two projections. Use this method in │ │ │ │ │ - * cases where the proj4js lib is not available or where custom projections │ │ │ │ │ - * need to be handled. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * from - {String} The code for the source projection │ │ │ │ │ - * to - {String} the code for the destination projection │ │ │ │ │ - * method - {Function} A function that takes a point as an argument and │ │ │ │ │ - * transforms that point from the source to the destination projection │ │ │ │ │ - * in place. The original point should be modified. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Projection.addTransform = function(from, to, method) { │ │ │ │ │ - if (method === OpenLayers.Projection.nullTransform) { │ │ │ │ │ - var defaults = OpenLayers.Projection.defaults[from]; │ │ │ │ │ - if (defaults && !OpenLayers.Projection.defaults[to]) { │ │ │ │ │ - OpenLayers.Projection.defaults[to] = defaults; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - if (!OpenLayers.Projection.transforms[from]) { │ │ │ │ │ - OpenLayers.Projection.transforms[from] = {}; │ │ │ │ │ - } │ │ │ │ │ - OpenLayers.Projection.transforms[from][to] = method; │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * APIMethod: transform │ │ │ │ │ - * Transform a point coordinate from one projection to another. Note that │ │ │ │ │ - * the input point is transformed in place. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * point - { | Object} An object with x and y │ │ │ │ │ - * properties representing coordinates in those dimensions. │ │ │ │ │ - * source - {OpenLayers.Projection} Source map coordinate system │ │ │ │ │ - * dest - {OpenLayers.Projection} Destination map coordinate system │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * point - {object} A transformed coordinate. The original point is modified. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Projection.transform = function(point, source, dest) { │ │ │ │ │ - if (source && dest) { │ │ │ │ │ - if (!(source instanceof OpenLayers.Projection)) { │ │ │ │ │ - source = new OpenLayers.Projection(source); │ │ │ │ │ - } │ │ │ │ │ - if (!(dest instanceof OpenLayers.Projection)) { │ │ │ │ │ - dest = new OpenLayers.Projection(dest); │ │ │ │ │ - } │ │ │ │ │ - if (source.proj && dest.proj) { │ │ │ │ │ - point = Proj4js.transform(source.proj, dest.proj, point); │ │ │ │ │ - } else { │ │ │ │ │ - var sourceCode = source.getCode(); │ │ │ │ │ - var destCode = dest.getCode(); │ │ │ │ │ - var transforms = OpenLayers.Projection.transforms; │ │ │ │ │ - if (transforms[sourceCode] && transforms[sourceCode][destCode]) { │ │ │ │ │ - transforms[sourceCode][destCode](point); │ │ │ │ │ - } │ │ │ │ │ + createSymbolizer: function(feature, intent) { │ │ │ │ │ + if (!feature) { │ │ │ │ │ + feature = new OpenLayers.Feature.Vector(); │ │ │ │ │ } │ │ │ │ │ - } │ │ │ │ │ - return point; │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * APIFunction: nullTransform │ │ │ │ │ - * A null transformation - useful for defining projection aliases when │ │ │ │ │ - * proj4js is not available: │ │ │ │ │ - * │ │ │ │ │ - * (code) │ │ │ │ │ - * OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:900913", │ │ │ │ │ - * OpenLayers.Projection.nullTransform); │ │ │ │ │ - * OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:3857", │ │ │ │ │ - * OpenLayers.Projection.nullTransform); │ │ │ │ │ - * (end) │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Projection.nullTransform = function(point) { │ │ │ │ │ - return point; │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Note: Transforms for web mercator <-> geographic │ │ │ │ │ - * OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113 and EPSG:102100. │ │ │ │ │ - * OpenLayers originally started referring to EPSG:900913 as web mercator. │ │ │ │ │ - * The EPSG has declared EPSG:3857 to be web mercator. │ │ │ │ │ - * ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as │ │ │ │ │ - * 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. │ │ │ │ │ - * For geographic, OpenLayers recognizes EPSG:4326, CRS:84 and │ │ │ │ │ - * urn:ogc:def:crs:EPSG:6.6:4326. OpenLayers also knows about the reverse axis │ │ │ │ │ - * order for EPSG:4326. │ │ │ │ │ - */ │ │ │ │ │ -(function() { │ │ │ │ │ - │ │ │ │ │ - var pole = 20037508.34; │ │ │ │ │ - │ │ │ │ │ - function inverseMercator(xy) { │ │ │ │ │ - xy.x = 180 * xy.x / pole; │ │ │ │ │ - xy.y = 180 / Math.PI * (2 * Math.atan(Math.exp((xy.y / pole) * Math.PI)) - Math.PI / 2); │ │ │ │ │ - return xy; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - function forwardMercator(xy) { │ │ │ │ │ - xy.x = xy.x * pole / 180; │ │ │ │ │ - var y = Math.log(Math.tan((90 + xy.y) * Math.PI / 360)) / Math.PI * pole; │ │ │ │ │ - xy.y = Math.max(-20037508.34, Math.min(y, 20037508.34)); │ │ │ │ │ - return xy; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - function map(base, codes) { │ │ │ │ │ - var add = OpenLayers.Projection.addTransform; │ │ │ │ │ - var same = OpenLayers.Projection.nullTransform; │ │ │ │ │ - var i, len, code, other, j; │ │ │ │ │ - for (i = 0, len = codes.length; i < len; ++i) { │ │ │ │ │ - code = codes[i]; │ │ │ │ │ - add(base, code, forwardMercator); │ │ │ │ │ - add(code, base, inverseMercator); │ │ │ │ │ - for (j = i + 1; j < len; ++j) { │ │ │ │ │ - other = codes[j]; │ │ │ │ │ - add(code, other, same); │ │ │ │ │ - add(other, code, same); │ │ │ │ │ - } │ │ │ │ │ + if (!this.styles[intent]) { │ │ │ │ │ + intent = "default"; │ │ │ │ │ } │ │ │ │ │ - } │ │ │ │ │ + feature.renderIntent = intent; │ │ │ │ │ + var defaultSymbolizer = {}; │ │ │ │ │ + if (this.extendDefault && intent != "default") { │ │ │ │ │ + defaultSymbolizer = this.styles["default"].createSymbolizer(feature); │ │ │ │ │ + } │ │ │ │ │ + return OpenLayers.Util.extend(defaultSymbolizer, │ │ │ │ │ + this.styles[intent].createSymbolizer(feature)); │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - // list of equivalent codes for web mercator │ │ │ │ │ - var mercator = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"], │ │ │ │ │ - geographic = ["CRS:84", "urn:ogc:def:crs:EPSG:6.6:4326", "EPSG:4326"], │ │ │ │ │ - i; │ │ │ │ │ - for (i = mercator.length - 1; i >= 0; --i) { │ │ │ │ │ - map(mercator[i], geographic); │ │ │ │ │ - } │ │ │ │ │ - for (i = geographic.length - 1; i >= 0; --i) { │ │ │ │ │ - map(geographic[i], mercator); │ │ │ │ │ - } │ │ │ │ │ + /** │ │ │ │ │ + * Method: addUniqueValueRules │ │ │ │ │ + * Convenience method to create comparison rules for unique values of a │ │ │ │ │ + * property. The rules will be added to the style object for a specified │ │ │ │ │ + * rendering intent. This method is a shortcut for creating something like │ │ │ │ │ + * the "unique value legends" familiar from well known desktop GIS systems │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * renderIntent - {String} rendering intent to add the rules to │ │ │ │ │ + * property - {String} values of feature attributes to create the │ │ │ │ │ + * rules for │ │ │ │ │ + * symbolizers - {Object} Hash of symbolizers, keyed by the desired │ │ │ │ │ + * property values │ │ │ │ │ + * context - {Object} An optional object with properties that │ │ │ │ │ + * symbolizers' property values should be evaluated │ │ │ │ │ + * against. If no context is specified, feature.attributes │ │ │ │ │ + * will be used │ │ │ │ │ + */ │ │ │ │ │ + addUniqueValueRules: function(renderIntent, property, symbolizers, context) { │ │ │ │ │ + var rules = []; │ │ │ │ │ + for (var value in symbolizers) { │ │ │ │ │ + rules.push(new OpenLayers.Rule({ │ │ │ │ │ + symbolizer: symbolizers[value], │ │ │ │ │ + context: context, │ │ │ │ │ + filter: new OpenLayers.Filter.Comparison({ │ │ │ │ │ + type: OpenLayers.Filter.Comparison.EQUAL_TO, │ │ │ │ │ + property: property, │ │ │ │ │ + value: value │ │ │ │ │ + }) │ │ │ │ │ + })); │ │ │ │ │ + } │ │ │ │ │ + this.styles[renderIntent].addRules(rules); │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ -})(); │ │ │ │ │ + CLASS_NAME: "OpenLayers.StyleMap" │ │ │ │ │ +}); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ OpenLayers/Util/vendorPrefix.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ @@ -21289,14 +21596,202 @@ │ │ │ │ │ requestFrame: requestFrame, │ │ │ │ │ start: start, │ │ │ │ │ stop: stop │ │ │ │ │ }; │ │ │ │ │ │ │ │ │ │ })(window); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ + OpenLayers/Kinetic.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + * @requires OpenLayers/Animation.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +OpenLayers.Kinetic = OpenLayers.Class({ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: threshold │ │ │ │ │ + * In most cases changing the threshold isn't needed. │ │ │ │ │ + * In px/ms, default to 0. │ │ │ │ │ + */ │ │ │ │ │ + threshold: 0, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: deceleration │ │ │ │ │ + * {Float} the deseleration in px/ms², default to 0.0035. │ │ │ │ │ + */ │ │ │ │ │ + deceleration: 0.0035, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: nbPoints │ │ │ │ │ + * {Integer} the number of points we use to calculate the kinetic │ │ │ │ │ + * initial values. │ │ │ │ │ + */ │ │ │ │ │ + nbPoints: 100, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: delay │ │ │ │ │ + * {Float} time to consider to calculate the kinetic initial values. │ │ │ │ │ + * In ms, default to 200. │ │ │ │ │ + */ │ │ │ │ │ + delay: 200, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: points │ │ │ │ │ + * List of points use to calculate the kinetic initial values. │ │ │ │ │ + */ │ │ │ │ │ + points: undefined, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: timerId │ │ │ │ │ + * ID of the timer. │ │ │ │ │ + */ │ │ │ │ │ + timerId: undefined, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Kinetic │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * options - {Object} │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(options) { │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: begin │ │ │ │ │ + * Begins the dragging. │ │ │ │ │ + */ │ │ │ │ │ + begin: function() { │ │ │ │ │ + OpenLayers.Animation.stop(this.timerId); │ │ │ │ │ + this.timerId = undefined; │ │ │ │ │ + this.points = []; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: update │ │ │ │ │ + * Updates during the dragging. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * xy - {} The new position. │ │ │ │ │ + */ │ │ │ │ │ + update: function(xy) { │ │ │ │ │ + this.points.unshift({ │ │ │ │ │ + xy: xy, │ │ │ │ │ + tick: new Date().getTime() │ │ │ │ │ + }); │ │ │ │ │ + if (this.points.length > this.nbPoints) { │ │ │ │ │ + this.points.pop(); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: end │ │ │ │ │ + * Ends the dragging, start the kinetic. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * xy - {} The last position. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Object} An object with two properties: "speed", and "theta". The │ │ │ │ │ + * "speed" and "theta" values are to be passed to the move │ │ │ │ │ + * function when starting the animation. │ │ │ │ │ + */ │ │ │ │ │ + end: function(xy) { │ │ │ │ │ + var last, now = new Date().getTime(); │ │ │ │ │ + for (var i = 0, l = this.points.length, point; i < l; i++) { │ │ │ │ │ + point = this.points[i]; │ │ │ │ │ + if (now - point.tick > this.delay) { │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ + last = point; │ │ │ │ │ + } │ │ │ │ │ + if (!last) { │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + var time = new Date().getTime() - last.tick; │ │ │ │ │ + var dist = Math.sqrt(Math.pow(xy.x - last.xy.x, 2) + │ │ │ │ │ + Math.pow(xy.y - last.xy.y, 2)); │ │ │ │ │ + var speed = dist / time; │ │ │ │ │ + if (speed == 0 || speed < this.threshold) { │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + var theta = Math.asin((xy.y - last.xy.y) / dist); │ │ │ │ │ + if (last.xy.x <= xy.x) { │ │ │ │ │ + theta = Math.PI - theta; │ │ │ │ │ + } │ │ │ │ │ + return { │ │ │ │ │ + speed: speed, │ │ │ │ │ + theta: theta │ │ │ │ │ + }; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: move │ │ │ │ │ + * Launch the kinetic move pan. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * info - {Object} An object with two properties, "speed", and "theta". │ │ │ │ │ + * These values are those returned from the "end" call. │ │ │ │ │ + * callback - {Function} Function called on every step of the animation, │ │ │ │ │ + * receives x, y (values to pan), end (is the last point). │ │ │ │ │ + */ │ │ │ │ │ + move: function(info, callback) { │ │ │ │ │ + var v0 = info.speed; │ │ │ │ │ + var fx = Math.cos(info.theta); │ │ │ │ │ + var fy = -Math.sin(info.theta); │ │ │ │ │ + │ │ │ │ │ + var initialTime = new Date().getTime(); │ │ │ │ │ + │ │ │ │ │ + var lastX = 0; │ │ │ │ │ + var lastY = 0; │ │ │ │ │ + │ │ │ │ │ + var timerCallback = function() { │ │ │ │ │ + if (this.timerId == null) { │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + var t = new Date().getTime() - initialTime; │ │ │ │ │ + │ │ │ │ │ + var p = (-this.deceleration * Math.pow(t, 2)) / 2.0 + v0 * t; │ │ │ │ │ + var x = p * fx; │ │ │ │ │ + var y = p * fy; │ │ │ │ │ + │ │ │ │ │ + var args = {}; │ │ │ │ │ + args.end = false; │ │ │ │ │ + var v = -this.deceleration * t + v0; │ │ │ │ │ + │ │ │ │ │ + if (v <= 0) { │ │ │ │ │ + OpenLayers.Animation.stop(this.timerId); │ │ │ │ │ + this.timerId = null; │ │ │ │ │ + args.end = true; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + args.x = x - lastX; │ │ │ │ │ + args.y = y - lastY; │ │ │ │ │ + lastX = x; │ │ │ │ │ + lastY = y; │ │ │ │ │ + callback(args.x, args.y, args.end); │ │ │ │ │ + }; │ │ │ │ │ + │ │ │ │ │ + this.timerId = OpenLayers.Animation.start( │ │ │ │ │ + OpenLayers.Function.bind(timerCallback, this) │ │ │ │ │ + ); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Kinetic" │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ OpenLayers/Tween.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ @@ -25952,1260 +26447,1421 @@ │ │ │ │ │ } │ │ │ │ │ return bounds; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ CLASS_NAME: "OpenLayers.Layer" │ │ │ │ │ }); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Icon.js │ │ │ │ │ + OpenLayers/Protocol.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Icon │ │ │ │ │ - * │ │ │ │ │ - * The icon represents a graphical icon on the screen. Typically used in │ │ │ │ │ - * conjunction with a to represent markers on a screen. │ │ │ │ │ - * │ │ │ │ │ - * An icon has a url, size and position. It also contains an offset which │ │ │ │ │ - * allows the center point to be represented correctly. This can be │ │ │ │ │ - * provided either as a fixed offset or a function provided to calculate │ │ │ │ │ - * the desired offset. │ │ │ │ │ - * │ │ │ │ │ + * Class: OpenLayers.Protocol │ │ │ │ │ + * Abstract vector layer protocol class. Not to be instantiated directly. Use │ │ │ │ │ + * one of the protocol subclasses instead. │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Icon = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: url │ │ │ │ │ - * {String} image url │ │ │ │ │ - */ │ │ │ │ │ - url: null, │ │ │ │ │ +OpenLayers.Protocol = OpenLayers.Class({ │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: size │ │ │ │ │ - * {|Object} An OpenLayers.Size or │ │ │ │ │ - * an object with a 'w' and 'h' properties. │ │ │ │ │ + /** │ │ │ │ │ + * Property: format │ │ │ │ │ + * {} The format used by this protocol. │ │ │ │ │ */ │ │ │ │ │ - size: null, │ │ │ │ │ + format: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: offset │ │ │ │ │ - * {|Object} distance in pixels to offset the │ │ │ │ │ - * image when being rendered. An OpenLayers.Pixel or an object │ │ │ │ │ - * with a 'x' and 'y' properties. │ │ │ │ │ + /** │ │ │ │ │ + * Property: options │ │ │ │ │ + * {Object} Any options sent to the constructor. │ │ │ │ │ */ │ │ │ │ │ - offset: null, │ │ │ │ │ + options: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: calculateOffset │ │ │ │ │ - * {Function} Function to calculate the offset (based on the size) │ │ │ │ │ + /** │ │ │ │ │ + * Property: autoDestroy │ │ │ │ │ + * {Boolean} The creator of the protocol can set autoDestroy to false │ │ │ │ │ + * to fully control when the protocol is destroyed. Defaults to │ │ │ │ │ + * true. │ │ │ │ │ */ │ │ │ │ │ - calculateOffset: null, │ │ │ │ │ + autoDestroy: true, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: imageDiv │ │ │ │ │ - * {DOMElement} │ │ │ │ │ + /** │ │ │ │ │ + * Property: defaultFilter │ │ │ │ │ + * {} Optional default filter to read requests │ │ │ │ │ */ │ │ │ │ │ - imageDiv: null, │ │ │ │ │ + defaultFilter: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: px │ │ │ │ │ - * {|Object} An OpenLayers.Pixel or an object │ │ │ │ │ - * with a 'x' and 'y' properties. │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Protocol │ │ │ │ │ + * Abstract class for vector protocols. Create instances of a subclass. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * options - {Object} Optional object whose properties will be set on the │ │ │ │ │ + * instance. │ │ │ │ │ */ │ │ │ │ │ - px: null, │ │ │ │ │ + initialize: function(options) { │ │ │ │ │ + options = options || {}; │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ + this.options = options; │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Icon │ │ │ │ │ - * Creates an icon, which is an image tag in a div. │ │ │ │ │ + /** │ │ │ │ │ + * Method: mergeWithDefaultFilter │ │ │ │ │ + * Merge filter passed to the read method with the default one │ │ │ │ │ * │ │ │ │ │ - * url - {String} │ │ │ │ │ - * size - {|Object} An OpenLayers.Size or an │ │ │ │ │ - * object with a 'w' and 'h' │ │ │ │ │ - * properties. │ │ │ │ │ - * offset - {|Object} An OpenLayers.Pixel or an │ │ │ │ │ - * object with a 'x' and 'y' │ │ │ │ │ - * properties. │ │ │ │ │ - * calculateOffset - {Function} │ │ │ │ │ + * Parameters: │ │ │ │ │ + * filter - {} │ │ │ │ │ */ │ │ │ │ │ - initialize: function(url, size, offset, calculateOffset) { │ │ │ │ │ - this.url = url; │ │ │ │ │ - this.size = size || { │ │ │ │ │ - w: 20, │ │ │ │ │ - h: 20 │ │ │ │ │ - }; │ │ │ │ │ - this.offset = offset || { │ │ │ │ │ - x: -(this.size.w / 2), │ │ │ │ │ - y: -(this.size.h / 2) │ │ │ │ │ - }; │ │ │ │ │ - this.calculateOffset = calculateOffset; │ │ │ │ │ - │ │ │ │ │ - var id = OpenLayers.Util.createUniqueID("OL_Icon_"); │ │ │ │ │ - this.imageDiv = OpenLayers.Util.createAlphaImageDiv(id); │ │ │ │ │ + mergeWithDefaultFilter: function(filter) { │ │ │ │ │ + var merged; │ │ │ │ │ + if (filter && this.defaultFilter) { │ │ │ │ │ + merged = new OpenLayers.Filter.Logical({ │ │ │ │ │ + type: OpenLayers.Filter.Logical.AND, │ │ │ │ │ + filters: [this.defaultFilter, filter] │ │ │ │ │ + }); │ │ │ │ │ + } else { │ │ │ │ │ + merged = filter || this.defaultFilter || undefined; │ │ │ │ │ + } │ │ │ │ │ + return merged; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: destroy │ │ │ │ │ - * Nullify references and remove event listeners to prevent circular │ │ │ │ │ - * references and memory leaks │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: destroy │ │ │ │ │ + * Clean up the protocol. │ │ │ │ │ */ │ │ │ │ │ destroy: function() { │ │ │ │ │ - // erase any drawn elements │ │ │ │ │ - this.erase(); │ │ │ │ │ - │ │ │ │ │ - OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild); │ │ │ │ │ - this.imageDiv.innerHTML = ""; │ │ │ │ │ - this.imageDiv = null; │ │ │ │ │ + this.options = null; │ │ │ │ │ + this.format = null; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: clone │ │ │ │ │ - * │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: read │ │ │ │ │ + * Construct a request for reading new features. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * options - {Object} Optional object for configuring the request. │ │ │ │ │ + * │ │ │ │ │ * Returns: │ │ │ │ │ - * {} A fresh copy of the icon. │ │ │ │ │ + * {} An │ │ │ │ │ + * object, the same object will be passed to the callback function passed │ │ │ │ │ + * if one exists in the options object. │ │ │ │ │ */ │ │ │ │ │ - clone: function() { │ │ │ │ │ - return new OpenLayers.Icon(this.url, │ │ │ │ │ - this.size, │ │ │ │ │ - this.offset, │ │ │ │ │ - this.calculateOffset); │ │ │ │ │ + read: function(options) { │ │ │ │ │ + options = options || {}; │ │ │ │ │ + options.filter = this.mergeWithDefaultFilter(options.filter); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ + │ │ │ │ │ /** │ │ │ │ │ - * Method: setSize │ │ │ │ │ - * │ │ │ │ │ + * APIMethod: create │ │ │ │ │ + * Construct a request for writing newly created features. │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * size - {|Object} An OpenLayers.Size or │ │ │ │ │ - * an object with a 'w' and 'h' properties. │ │ │ │ │ + * features - {Array({})} or │ │ │ │ │ + * {} │ │ │ │ │ + * options - {Object} Optional object for configuring the request. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} An │ │ │ │ │ + * object, the same object will be passed to the callback function passed │ │ │ │ │ + * if one exists in the options object. │ │ │ │ │ */ │ │ │ │ │ - setSize: function(size) { │ │ │ │ │ - if (size != null) { │ │ │ │ │ - this.size = size; │ │ │ │ │ - } │ │ │ │ │ - this.draw(); │ │ │ │ │ - }, │ │ │ │ │ + create: function() {}, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: setUrl │ │ │ │ │ - * │ │ │ │ │ + * APIMethod: update │ │ │ │ │ + * Construct a request updating modified features. │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * url - {String} │ │ │ │ │ + * features - {Array({})} or │ │ │ │ │ + * {} │ │ │ │ │ + * options - {Object} Optional object for configuring the request. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} An │ │ │ │ │ + * object, the same object will be passed to the callback function passed │ │ │ │ │ + * if one exists in the options object. │ │ │ │ │ */ │ │ │ │ │ - setUrl: function(url) { │ │ │ │ │ - if (url != null) { │ │ │ │ │ - this.url = url; │ │ │ │ │ - } │ │ │ │ │ - this.draw(); │ │ │ │ │ - }, │ │ │ │ │ + update: function() {}, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: draw │ │ │ │ │ - * Move the div to the given pixel. │ │ │ │ │ - * │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: delete │ │ │ │ │ + * Construct a request deleting a removed feature. │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * px - {|Object} An OpenLayers.Pixel or an │ │ │ │ │ - * object with a 'x' and 'y' properties. │ │ │ │ │ - * │ │ │ │ │ + * feature - {} │ │ │ │ │ + * options - {Object} Optional object for configuring the request. │ │ │ │ │ + * │ │ │ │ │ * Returns: │ │ │ │ │ - * {DOMElement} A new DOM Image of this icon set at the location passed-in │ │ │ │ │ + * {} An │ │ │ │ │ + * object, the same object will be passed to the callback function passed │ │ │ │ │ + * if one exists in the options object. │ │ │ │ │ */ │ │ │ │ │ - draw: function(px) { │ │ │ │ │ - OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, │ │ │ │ │ - null, │ │ │ │ │ - null, │ │ │ │ │ - this.size, │ │ │ │ │ - this.url, │ │ │ │ │ - "absolute"); │ │ │ │ │ - this.moveTo(px); │ │ │ │ │ - return this.imageDiv; │ │ │ │ │ - }, │ │ │ │ │ + "delete": function() {}, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: erase │ │ │ │ │ - * Erase the underlying image element. │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: commit │ │ │ │ │ + * Go over the features and for each take action │ │ │ │ │ + * based on the feature state. Possible actions are create, │ │ │ │ │ + * update and delete. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * features - {Array({})} │ │ │ │ │ + * options - {Object} Object whose possible keys are "create", "update", │ │ │ │ │ + * "delete", "callback" and "scope", the values referenced by the │ │ │ │ │ + * first three are objects as passed to the "create", "update", and │ │ │ │ │ + * "delete" methods, the value referenced by the "callback" key is │ │ │ │ │ + * a function which is called when the commit operation is complete │ │ │ │ │ + * using the scope referenced by the "scope" key. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Array({})} An array of │ │ │ │ │ + * objects. │ │ │ │ │ */ │ │ │ │ │ - erase: function() { │ │ │ │ │ - if (this.imageDiv != null && this.imageDiv.parentNode != null) { │ │ │ │ │ - OpenLayers.Element.remove(this.imageDiv); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ + commit: function() {}, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: setOpacity │ │ │ │ │ - * Change the icon's opacity │ │ │ │ │ + /** │ │ │ │ │ + * Method: abort │ │ │ │ │ + * Abort an ongoing request. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * opacity - {float} │ │ │ │ │ + * response - {} │ │ │ │ │ */ │ │ │ │ │ - setOpacity: function(opacity) { │ │ │ │ │ - OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null, │ │ │ │ │ - null, null, null, null, opacity); │ │ │ │ │ - │ │ │ │ │ - }, │ │ │ │ │ + abort: function(response) {}, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: moveTo │ │ │ │ │ - * move icon to passed in px. │ │ │ │ │ + * Method: createCallback │ │ │ │ │ + * Returns a function that applies the given public method with resp and │ │ │ │ │ + * options arguments. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * px - {|Object} the pixel position to move to. │ │ │ │ │ - * An OpenLayers.Pixel or an object with a 'x' and 'y' properties. │ │ │ │ │ + * method - {Function} The method to be applied by the callback. │ │ │ │ │ + * response - {} The protocol response object. │ │ │ │ │ + * options - {Object} Options sent to the protocol method │ │ │ │ │ */ │ │ │ │ │ - moveTo: function(px) { │ │ │ │ │ - //if no px passed in, use stored location │ │ │ │ │ - if (px != null) { │ │ │ │ │ - this.px = px; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - if (this.imageDiv != null) { │ │ │ │ │ - if (this.px == null) { │ │ │ │ │ - this.display(false); │ │ │ │ │ - } else { │ │ │ │ │ - if (this.calculateOffset) { │ │ │ │ │ - this.offset = this.calculateOffset(this.size); │ │ │ │ │ - } │ │ │ │ │ - OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, { │ │ │ │ │ - x: this.px.x + this.offset.x, │ │ │ │ │ - y: this.px.y + this.offset.y │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ + createCallback: function(method, response, options) { │ │ │ │ │ + return OpenLayers.Function.bind(function() { │ │ │ │ │ + method.apply(this, [response, options]); │ │ │ │ │ + }, this); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: display │ │ │ │ │ - * Hide or show the icon │ │ │ │ │ + CLASS_NAME: "OpenLayers.Protocol" │ │ │ │ │ +}); │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Protocol.Response │ │ │ │ │ + * Protocols return Response objects to their users. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Protocol.Response = OpenLayers.Class({ │ │ │ │ │ + /** │ │ │ │ │ + * Property: code │ │ │ │ │ + * {Number} - OpenLayers.Protocol.Response.SUCCESS or │ │ │ │ │ + * OpenLayers.Protocol.Response.FAILURE │ │ │ │ │ + */ │ │ │ │ │ + code: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: requestType │ │ │ │ │ + * {String} The type of request this response corresponds to. Either │ │ │ │ │ + * "create", "read", "update" or "delete". │ │ │ │ │ + */ │ │ │ │ │ + requestType: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: last │ │ │ │ │ + * {Boolean} - true if this is the last response expected in a commit, │ │ │ │ │ + * false otherwise, defaults to true. │ │ │ │ │ + */ │ │ │ │ │ + last: true, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: features │ │ │ │ │ + * {Array({})} or {} │ │ │ │ │ + * The features returned in the response by the server. Depending on the │ │ │ │ │ + * protocol's read payload, either features or data will be populated. │ │ │ │ │ + */ │ │ │ │ │ + features: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: data │ │ │ │ │ + * {Object} │ │ │ │ │ + * The data returned in the response by the server. Depending on the │ │ │ │ │ + * protocol's read payload, either features or data will be populated. │ │ │ │ │ + */ │ │ │ │ │ + data: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: reqFeatures │ │ │ │ │ + * {Array({})} or {} │ │ │ │ │ + * The features provided by the user and placed in the request by the │ │ │ │ │ + * protocol. │ │ │ │ │ + */ │ │ │ │ │ + reqFeatures: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: priv │ │ │ │ │ + */ │ │ │ │ │ + priv: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: error │ │ │ │ │ + * {Object} The error object in case a service exception was encountered. │ │ │ │ │ + */ │ │ │ │ │ + error: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Protocol.Response │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * display - {Boolean} │ │ │ │ │ + * options - {Object} Optional object whose properties will be set on the │ │ │ │ │ + * instance. │ │ │ │ │ */ │ │ │ │ │ - display: function(display) { │ │ │ │ │ - this.imageDiv.style.display = (display) ? "" : "none"; │ │ │ │ │ + initialize: function(options) { │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: isDrawn │ │ │ │ │ - * │ │ │ │ │ + * Method: success │ │ │ │ │ + * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Boolean} Whether or not the icon is drawn. │ │ │ │ │ + * {Boolean} - true on success, false otherwise │ │ │ │ │ */ │ │ │ │ │ - isDrawn: function() { │ │ │ │ │ - // nodeType 11 for ie, whose nodes *always* have a parentNode │ │ │ │ │ - // (of type document fragment) │ │ │ │ │ - var isDrawn = (this.imageDiv && this.imageDiv.parentNode && │ │ │ │ │ - (this.imageDiv.parentNode.nodeType != 11)); │ │ │ │ │ - │ │ │ │ │ - return isDrawn; │ │ │ │ │ + success: function() { │ │ │ │ │ + return this.code > 0; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Icon" │ │ │ │ │ + CLASS_NAME: "OpenLayers.Protocol.Response" │ │ │ │ │ }); │ │ │ │ │ + │ │ │ │ │ +OpenLayers.Protocol.Response.SUCCESS = 1; │ │ │ │ │ +OpenLayers.Protocol.Response.FAILURE = 0; │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Marker.js │ │ │ │ │ + OpenLayers/Renderer.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ - │ │ │ │ │ /** │ │ │ │ │ * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - * @requires OpenLayers/Events.js │ │ │ │ │ - * @requires OpenLayers/Icon.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Marker │ │ │ │ │ - * Instances of OpenLayers.Marker are a combination of a │ │ │ │ │ - * and an . │ │ │ │ │ - * │ │ │ │ │ - * Markers are generally added to a special layer called │ │ │ │ │ - * . │ │ │ │ │ - * │ │ │ │ │ - * Example: │ │ │ │ │ - * (code) │ │ │ │ │ - * var markers = new OpenLayers.Layer.Markers( "Markers" ); │ │ │ │ │ - * map.addLayer(markers); │ │ │ │ │ - * │ │ │ │ │ - * var size = new OpenLayers.Size(21,25); │ │ │ │ │ - * var offset = new OpenLayers.Pixel(-(size.w/2), -size.h); │ │ │ │ │ - * var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset); │ │ │ │ │ - * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon)); │ │ │ │ │ - * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon.clone())); │ │ │ │ │ + * Class: OpenLayers.Renderer │ │ │ │ │ + * This is the base class for all renderers. │ │ │ │ │ * │ │ │ │ │ - * (end) │ │ │ │ │ + * This is based on a merger code written by Paul Spencer and Bertil Chapuis. │ │ │ │ │ + * It is largely composed of virtual functions that are to be implemented │ │ │ │ │ + * in technology-specific subclasses, but there is some generic code too. │ │ │ │ │ + * │ │ │ │ │ + * The functions that *are* implemented here merely deal with the maintenance │ │ │ │ │ + * of the size and extent variables, as well as the cached 'resolution' │ │ │ │ │ + * value. │ │ │ │ │ + * │ │ │ │ │ + * A note to the user that all subclasses should use getResolution() instead │ │ │ │ │ + * of directly accessing this.resolution in order to correctly use the │ │ │ │ │ + * cacheing system. │ │ │ │ │ * │ │ │ │ │ - * Note that if you pass an icon into the Marker constructor, it will take │ │ │ │ │ - * that icon and use it. This means that you should not share icons between │ │ │ │ │ - * markers -- you use them once, but you should clone() for any additional │ │ │ │ │ - * markers using that same icon. │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Marker = OpenLayers.Class({ │ │ │ │ │ +OpenLayers.Renderer = OpenLayers.Class({ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: icon │ │ │ │ │ - * {} The icon used by this marker. │ │ │ │ │ + * Property: container │ │ │ │ │ + * {DOMElement} │ │ │ │ │ */ │ │ │ │ │ - icon: null, │ │ │ │ │ + container: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: lonlat │ │ │ │ │ - * {} location of object │ │ │ │ │ + /** │ │ │ │ │ + * Property: root │ │ │ │ │ + * {DOMElement} │ │ │ │ │ */ │ │ │ │ │ - lonlat: null, │ │ │ │ │ + root: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: events │ │ │ │ │ - * {} the event handler. │ │ │ │ │ + * Property: extent │ │ │ │ │ + * {} │ │ │ │ │ */ │ │ │ │ │ - events: null, │ │ │ │ │ + extent: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: locked │ │ │ │ │ + * {Boolean} If the renderer is currently in a state where many things │ │ │ │ │ + * are changing, the 'locked' property is set to true. This means │ │ │ │ │ + * that renderers can expect at least one more drawFeature event to be │ │ │ │ │ + * called with the 'locked' property set to 'true': In some renderers, │ │ │ │ │ + * this might make sense to use as a 'only update local information' │ │ │ │ │ + * flag. │ │ │ │ │ + */ │ │ │ │ │ + locked: false, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: map │ │ │ │ │ - * {} the map this marker is attached to │ │ │ │ │ + * Property: size │ │ │ │ │ + * {} │ │ │ │ │ + */ │ │ │ │ │ + size: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: resolution │ │ │ │ │ + * {Float} cache of current map resolution │ │ │ │ │ + */ │ │ │ │ │ + resolution: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: map │ │ │ │ │ + * {} Reference to the map -- this is set in Vector's setMap() │ │ │ │ │ */ │ │ │ │ │ map: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Marker │ │ │ │ │ + /** │ │ │ │ │ + * Property: featureDx │ │ │ │ │ + * {Number} Feature offset in x direction. Will be calculated for and │ │ │ │ │ + * applied to the current feature while rendering (see │ │ │ │ │ + * ). │ │ │ │ │ + */ │ │ │ │ │ + featureDx: 0, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Renderer │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * lonlat - {} the position of this marker │ │ │ │ │ - * icon - {} the icon for this marker │ │ │ │ │ + * containerID - {} │ │ │ │ │ + * options - {Object} options for this renderer. See sublcasses for │ │ │ │ │ + * supported options. │ │ │ │ │ */ │ │ │ │ │ - initialize: function(lonlat, icon) { │ │ │ │ │ - this.lonlat = lonlat; │ │ │ │ │ - │ │ │ │ │ - var newIcon = (icon) ? icon : OpenLayers.Marker.defaultIcon(); │ │ │ │ │ - if (this.icon == null) { │ │ │ │ │ - this.icon = newIcon; │ │ │ │ │ - } else { │ │ │ │ │ - this.icon.url = newIcon.url; │ │ │ │ │ - this.icon.size = newIcon.size; │ │ │ │ │ - this.icon.offset = newIcon.offset; │ │ │ │ │ - this.icon.calculateOffset = newIcon.calculateOffset; │ │ │ │ │ - } │ │ │ │ │ - this.events = new OpenLayers.Events(this, this.icon.imageDiv); │ │ │ │ │ + initialize: function(containerID, options) { │ │ │ │ │ + this.container = OpenLayers.Util.getElement(containerID); │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ * APIMethod: destroy │ │ │ │ │ - * Destroy the marker. You must first remove the marker from any │ │ │ │ │ - * layer which it has been added to, or you will get buggy behavior. │ │ │ │ │ - * (This can not be done within the marker since the marker does not │ │ │ │ │ - * know which layer it is attached to.) │ │ │ │ │ */ │ │ │ │ │ destroy: function() { │ │ │ │ │ - // erase any drawn features │ │ │ │ │ - this.erase(); │ │ │ │ │ - │ │ │ │ │ + this.container = null; │ │ │ │ │ + this.extent = null; │ │ │ │ │ + this.size = null; │ │ │ │ │ + this.resolution = null; │ │ │ │ │ this.map = null; │ │ │ │ │ - │ │ │ │ │ - this.events.destroy(); │ │ │ │ │ - this.events = null; │ │ │ │ │ - │ │ │ │ │ - if (this.icon != null) { │ │ │ │ │ - this.icon.destroy(); │ │ │ │ │ - this.icon = null; │ │ │ │ │ - } │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: draw │ │ │ │ │ - * Calls draw on the icon, and returns that output. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * px - {} │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: supported │ │ │ │ │ + * This should be overridden by specific subclasses │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {DOMElement} A new DOM Image with this marker's icon set at the │ │ │ │ │ - * location passed-in │ │ │ │ │ + * {Boolean} Whether or not the browser supports the renderer class │ │ │ │ │ */ │ │ │ │ │ - draw: function(px) { │ │ │ │ │ - return this.icon.draw(px); │ │ │ │ │ + supported: function() { │ │ │ │ │ + return false; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: erase │ │ │ │ │ - * Erases any drawn elements for this marker. │ │ │ │ │ + /** │ │ │ │ │ + * Method: setExtent │ │ │ │ │ + * Set the visible part of the layer. │ │ │ │ │ + * │ │ │ │ │ + * Resolution has probably changed, so we nullify the resolution │ │ │ │ │ + * cache (this.resolution) -- this way it will be re-computed when │ │ │ │ │ + * next it is needed. │ │ │ │ │ + * We nullify the resolution cache (this.resolution) if resolutionChanged │ │ │ │ │ + * is set to true - this way it will be re-computed on the next │ │ │ │ │ + * getResolution() request. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * extent - {} │ │ │ │ │ + * resolutionChanged - {Boolean} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} true to notify the layer that the new extent does not exceed │ │ │ │ │ + * the coordinate range, and the features will not need to be redrawn. │ │ │ │ │ + * False otherwise. │ │ │ │ │ */ │ │ │ │ │ - erase: function() { │ │ │ │ │ - if (this.icon != null) { │ │ │ │ │ - this.icon.erase(); │ │ │ │ │ + setExtent: function(extent, resolutionChanged) { │ │ │ │ │ + this.extent = extent.clone(); │ │ │ │ │ + if (this.map.baseLayer && this.map.baseLayer.wrapDateLine) { │ │ │ │ │ + var ratio = extent.getWidth() / this.map.getExtent().getWidth(), │ │ │ │ │ + extent = extent.scale(1 / ratio); │ │ │ │ │ + this.extent = extent.wrapDateLine(this.map.getMaxExtent()).scale(ratio); │ │ │ │ │ + } │ │ │ │ │ + if (resolutionChanged) { │ │ │ │ │ + this.resolution = null; │ │ │ │ │ } │ │ │ │ │ + return true; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: moveTo │ │ │ │ │ - * Move the marker to the new location. │ │ │ │ │ + * Method: setSize │ │ │ │ │ + * Sets the size of the drawing surface. │ │ │ │ │ + * │ │ │ │ │ + * Resolution has probably changed, so we nullify the resolution │ │ │ │ │ + * cache (this.resolution) -- this way it will be re-computed when │ │ │ │ │ + * next it is needed. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * px - {|Object} the pixel position to move to. │ │ │ │ │ - * An OpenLayers.Pixel or an object with a 'x' and 'y' properties. │ │ │ │ │ + * size - {} │ │ │ │ │ */ │ │ │ │ │ - moveTo: function(px) { │ │ │ │ │ - if ((px != null) && (this.icon != null)) { │ │ │ │ │ - this.icon.moveTo(px); │ │ │ │ │ - } │ │ │ │ │ - this.lonlat = this.map.getLonLatFromLayerPx(px); │ │ │ │ │ + setSize: function(size) { │ │ │ │ │ + this.size = size.clone(); │ │ │ │ │ + this.resolution = null; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: isDrawn │ │ │ │ │ + /** │ │ │ │ │ + * Method: getResolution │ │ │ │ │ + * Uses cached copy of resolution if available to minimize computing │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Boolean} Whether or not the marker is drawn. │ │ │ │ │ + * {Float} The current map's resolution │ │ │ │ │ */ │ │ │ │ │ - isDrawn: function() { │ │ │ │ │ - var isDrawn = (this.icon && this.icon.isDrawn()); │ │ │ │ │ - return isDrawn; │ │ │ │ │ + getResolution: function() { │ │ │ │ │ + this.resolution = this.resolution || this.map.getResolution(); │ │ │ │ │ + return this.resolution; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: onScreen │ │ │ │ │ + * Method: drawFeature │ │ │ │ │ + * Draw the feature. The optional style argument can be used │ │ │ │ │ + * to override the feature's own style. This method should only │ │ │ │ │ + * be called from layer.drawFeature(). │ │ │ │ │ * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * feature - {} │ │ │ │ │ + * style - {} │ │ │ │ │ + * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Boolean} Whether or not the marker is currently visible on screen. │ │ │ │ │ + * {Boolean} true if the feature has been drawn completely, false if not, │ │ │ │ │ + * undefined if the feature had no geometry │ │ │ │ │ */ │ │ │ │ │ - onScreen: function() { │ │ │ │ │ + drawFeature: function(feature, style) { │ │ │ │ │ + if (style == null) { │ │ │ │ │ + style = feature.style; │ │ │ │ │ + } │ │ │ │ │ + if (feature.geometry) { │ │ │ │ │ + var bounds = feature.geometry.getBounds(); │ │ │ │ │ + if (bounds) { │ │ │ │ │ + var worldBounds; │ │ │ │ │ + if (this.map.baseLayer && this.map.baseLayer.wrapDateLine) { │ │ │ │ │ + worldBounds = this.map.getMaxExtent(); │ │ │ │ │ + } │ │ │ │ │ + if (!bounds.intersectsBounds(this.extent, { │ │ │ │ │ + worldBounds: worldBounds │ │ │ │ │ + })) { │ │ │ │ │ + style = { │ │ │ │ │ + display: "none" │ │ │ │ │ + }; │ │ │ │ │ + } else { │ │ │ │ │ + this.calculateFeatureDx(bounds, worldBounds); │ │ │ │ │ + } │ │ │ │ │ + var rendered = this.drawGeometry(feature.geometry, style, feature.id); │ │ │ │ │ + if (style.display != "none" && style.label && rendered !== false) { │ │ │ │ │ │ │ │ │ │ - var onScreen = false; │ │ │ │ │ - if (this.map) { │ │ │ │ │ - var screenBounds = this.map.getExtent(); │ │ │ │ │ - onScreen = screenBounds.containsLonLat(this.lonlat); │ │ │ │ │ + var location = feature.geometry.getCentroid(); │ │ │ │ │ + if (style.labelXOffset || style.labelYOffset) { │ │ │ │ │ + var xOffset = isNaN(style.labelXOffset) ? 0 : style.labelXOffset; │ │ │ │ │ + var yOffset = isNaN(style.labelYOffset) ? 0 : style.labelYOffset; │ │ │ │ │ + var res = this.getResolution(); │ │ │ │ │ + location.move(xOffset * res, yOffset * res); │ │ │ │ │ + } │ │ │ │ │ + this.drawText(feature.id, style, location); │ │ │ │ │ + } else { │ │ │ │ │ + this.removeText(feature.id); │ │ │ │ │ + } │ │ │ │ │ + return rendered; │ │ │ │ │ + } │ │ │ │ │ } │ │ │ │ │ - return onScreen; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: inflate │ │ │ │ │ - * Englarges the markers icon by the specified ratio. │ │ │ │ │ + * Method: calculateFeatureDx │ │ │ │ │ + * {Number} Calculates the feature offset in x direction. Looking at the │ │ │ │ │ + * center of the feature bounds and the renderer extent, we calculate how │ │ │ │ │ + * many world widths the two are away from each other. This distance is │ │ │ │ │ + * used to shift the feature as close as possible to the center of the │ │ │ │ │ + * current enderer extent, which ensures that the feature is visible in the │ │ │ │ │ + * current viewport. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * inflate - {float} the ratio to enlarge the marker by (passing 2 │ │ │ │ │ - * will double the size). │ │ │ │ │ + * bounds - {} Bounds of the feature │ │ │ │ │ + * worldBounds - {} Bounds of the world │ │ │ │ │ */ │ │ │ │ │ - inflate: function(inflate) { │ │ │ │ │ - if (this.icon) { │ │ │ │ │ - this.icon.setSize({ │ │ │ │ │ - w: this.icon.size.w * inflate, │ │ │ │ │ - h: this.icon.size.h * inflate │ │ │ │ │ - }); │ │ │ │ │ + calculateFeatureDx: function(bounds, worldBounds) { │ │ │ │ │ + this.featureDx = 0; │ │ │ │ │ + if (worldBounds) { │ │ │ │ │ + var worldWidth = worldBounds.getWidth(), │ │ │ │ │ + rendererCenterX = (this.extent.left + this.extent.right) / 2, │ │ │ │ │ + featureCenterX = (bounds.left + bounds.right) / 2, │ │ │ │ │ + worldsAway = Math.round((featureCenterX - rendererCenterX) / worldWidth); │ │ │ │ │ + this.featureDx = worldsAway * worldWidth; │ │ │ │ │ } │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: setOpacity │ │ │ │ │ - * Change the opacity of the marker by changin the opacity of │ │ │ │ │ - * its icon │ │ │ │ │ + * Method: drawGeometry │ │ │ │ │ * │ │ │ │ │ + * Draw a geometry. This should only be called from the renderer itself. │ │ │ │ │ + * Use layer.drawFeature() from outside the renderer. │ │ │ │ │ + * virtual function │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * opacity - {float} Specified as fraction (0.4, etc) │ │ │ │ │ + * geometry - {} │ │ │ │ │ + * style - {Object} │ │ │ │ │ + * featureId - {} │ │ │ │ │ */ │ │ │ │ │ - setOpacity: function(opacity) { │ │ │ │ │ - this.icon.setOpacity(opacity); │ │ │ │ │ + drawGeometry: function(geometry, style, featureId) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: drawText │ │ │ │ │ + * Function for drawing text labels. │ │ │ │ │ + * This method is only called by the renderer itself. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * featureId - {String} │ │ │ │ │ + * style - │ │ │ │ │ + * location - {} │ │ │ │ │ + */ │ │ │ │ │ + drawText: function(featureId, style, location) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: removeText │ │ │ │ │ + * Function for removing text labels. │ │ │ │ │ + * This method is only called by the renderer itself. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * featureId - {String} │ │ │ │ │ + */ │ │ │ │ │ + removeText: function(featureId) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: clear │ │ │ │ │ + * Clear all vectors from the renderer. │ │ │ │ │ + * virtual function. │ │ │ │ │ + */ │ │ │ │ │ + clear: function() {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: getFeatureIdFromEvent │ │ │ │ │ + * Returns a feature id from an event on the renderer. │ │ │ │ │ + * How this happens is specific to the renderer. This should be │ │ │ │ │ + * called from layer.getFeatureFromEvent(). │ │ │ │ │ + * Virtual function. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {String} A feature id or undefined. │ │ │ │ │ + */ │ │ │ │ │ + getFeatureIdFromEvent: function(evt) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: eraseFeatures │ │ │ │ │ + * This is called by the layer to erase features │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * features - {Array()} │ │ │ │ │ + */ │ │ │ │ │ + eraseFeatures: function(features) { │ │ │ │ │ + if (!(OpenLayers.Util.isArray(features))) { │ │ │ │ │ + features = [features]; │ │ │ │ │ + } │ │ │ │ │ + for (var i = 0, len = features.length; i < len; ++i) { │ │ │ │ │ + var feature = features[i]; │ │ │ │ │ + this.eraseGeometry(feature.geometry, feature.id); │ │ │ │ │ + this.removeText(feature.id); │ │ │ │ │ + } │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: setUrl │ │ │ │ │ - * Change URL of the Icon Image. │ │ │ │ │ + * Method: eraseGeometry │ │ │ │ │ + * Remove a geometry from the renderer (by id). │ │ │ │ │ + * virtual function. │ │ │ │ │ * │ │ │ │ │ - * url - {String} │ │ │ │ │ + * Parameters: │ │ │ │ │ + * geometry - {} │ │ │ │ │ + * featureId - {String} │ │ │ │ │ */ │ │ │ │ │ - setUrl: function(url) { │ │ │ │ │ - this.icon.setUrl(url); │ │ │ │ │ + eraseGeometry: function(geometry, featureId) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: moveRoot │ │ │ │ │ + * moves this renderer's root to a (different) renderer. │ │ │ │ │ + * To be implemented by subclasses that require a common renderer root for │ │ │ │ │ + * feature selection. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * renderer - {} target renderer for the moved root │ │ │ │ │ + */ │ │ │ │ │ + moveRoot: function(renderer) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: getRenderLayerId │ │ │ │ │ + * Gets the layer that this renderer's output appears on. If moveRoot was │ │ │ │ │ + * used, this will be different from the id of the layer containing the │ │ │ │ │ + * features rendered by this renderer. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {String} the id of the output layer. │ │ │ │ │ + */ │ │ │ │ │ + getRenderLayerId: function() { │ │ │ │ │ + return this.container.id; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: display │ │ │ │ │ - * Hide or show the icon │ │ │ │ │ + /** │ │ │ │ │ + * Method: applyDefaultSymbolizer │ │ │ │ │ * │ │ │ │ │ - * display - {Boolean} │ │ │ │ │ + * Parameters: │ │ │ │ │ + * symbolizer - {Object} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Object} │ │ │ │ │ */ │ │ │ │ │ - display: function(display) { │ │ │ │ │ - this.icon.display(display); │ │ │ │ │ + applyDefaultSymbolizer: function(symbolizer) { │ │ │ │ │ + var result = OpenLayers.Util.extend({}, │ │ │ │ │ + OpenLayers.Renderer.defaultSymbolizer); │ │ │ │ │ + if (symbolizer.stroke === false) { │ │ │ │ │ + delete result.strokeWidth; │ │ │ │ │ + delete result.strokeColor; │ │ │ │ │ + } │ │ │ │ │ + if (symbolizer.fill === false) { │ │ │ │ │ + delete result.fillColor; │ │ │ │ │ + } │ │ │ │ │ + OpenLayers.Util.extend(result, symbolizer); │ │ │ │ │ + return result; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Marker" │ │ │ │ │ + CLASS_NAME: "OpenLayers.Renderer" │ │ │ │ │ }); │ │ │ │ │ │ │ │ │ │ - │ │ │ │ │ /** │ │ │ │ │ - * Function: defaultIcon │ │ │ │ │ - * Creates a default . │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} A default OpenLayers.Icon to use for a marker │ │ │ │ │ + * Constant: OpenLayers.Renderer.defaultSymbolizer │ │ │ │ │ + * {Object} Properties from this symbolizer will be applied to symbolizers │ │ │ │ │ + * with missing properties. This can also be used to set a global │ │ │ │ │ + * symbolizer default in OpenLayers. To be SLD 1.x compliant, add the │ │ │ │ │ + * following code before rendering any vector features: │ │ │ │ │ + * (code) │ │ │ │ │ + * OpenLayers.Renderer.defaultSymbolizer = { │ │ │ │ │ + * fillColor: "#808080", │ │ │ │ │ + * fillOpacity: 1, │ │ │ │ │ + * strokeColor: "#000000", │ │ │ │ │ + * strokeOpacity: 1, │ │ │ │ │ + * strokeWidth: 1, │ │ │ │ │ + * pointRadius: 3, │ │ │ │ │ + * graphicName: "square" │ │ │ │ │ + * }; │ │ │ │ │ + * (end) │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Marker.defaultIcon = function() { │ │ │ │ │ - return new OpenLayers.Icon(OpenLayers.Util.getImageLocation("marker.png"), { │ │ │ │ │ - w: 21, │ │ │ │ │ - h: 25 │ │ │ │ │ - }, { │ │ │ │ │ - x: -10.5, │ │ │ │ │ - y: -25 │ │ │ │ │ - }); │ │ │ │ │ +OpenLayers.Renderer.defaultSymbolizer = { │ │ │ │ │ + fillColor: "#000000", │ │ │ │ │ + strokeColor: "#000000", │ │ │ │ │ + strokeWidth: 2, │ │ │ │ │ + fillOpacity: 1, │ │ │ │ │ + strokeOpacity: 1, │ │ │ │ │ + pointRadius: 0, │ │ │ │ │ + labelAlign: 'cm' │ │ │ │ │ }; │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Constant: OpenLayers.Renderer.symbol │ │ │ │ │ + * Coordinate arrays for well known (named) symbols. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Renderer.symbol = { │ │ │ │ │ + "star": [350, 75, 379, 161, 469, 161, 397, 215, 423, 301, 350, 250, 277, 301, │ │ │ │ │ + 303, 215, 231, 161, 321, 161, 350, 75 │ │ │ │ │ + ], │ │ │ │ │ + "cross": [4, 0, 6, 0, 6, 4, 10, 4, 10, 6, 6, 6, 6, 10, 4, 10, 4, 6, 0, 6, 0, 4, 4, 4, │ │ │ │ │ + 4, 0 │ │ │ │ │ + ], │ │ │ │ │ + "x": [0, 0, 25, 0, 50, 35, 75, 0, 100, 0, 65, 50, 100, 100, 75, 100, 50, 65, 25, 100, 0, 100, 35, 50, 0, 0], │ │ │ │ │ + "square": [0, 0, 0, 1, 1, 1, 1, 0, 0, 0], │ │ │ │ │ + "triangle": [0, 10, 10, 10, 5, 0, 0, 10] │ │ │ │ │ +}; │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Handler.js │ │ │ │ │ + OpenLayers/Tile.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ + │ │ │ │ │ /** │ │ │ │ │ * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - * @requires OpenLayers/Events.js │ │ │ │ │ + * @requires OpenLayers/Util.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Handler │ │ │ │ │ - * Base class to construct a higher-level handler for event sequences. All │ │ │ │ │ - * handlers have activate and deactivate methods. In addition, they have │ │ │ │ │ - * methods named like browser events. When a handler is activated, any │ │ │ │ │ - * additional methods named like a browser event is registered as a │ │ │ │ │ - * listener for the corresponding event. When a handler is deactivated, │ │ │ │ │ - * those same methods are unregistered as event listeners. │ │ │ │ │ - * │ │ │ │ │ - * Handlers also typically have a callbacks object with keys named like │ │ │ │ │ - * the abstracted events or event sequences that they are in charge of │ │ │ │ │ - * handling. The controls that wrap handlers define the methods that │ │ │ │ │ - * correspond to these abstract events - so instead of listening for │ │ │ │ │ - * individual browser events, they only listen for the abstract events │ │ │ │ │ - * defined by the handler. │ │ │ │ │ - * │ │ │ │ │ - * Handlers are created by controls, which ultimately have the responsibility │ │ │ │ │ - * of making changes to the the state of the application. Handlers │ │ │ │ │ - * themselves may make temporary changes, but in general are expected to │ │ │ │ │ - * return the application in the same state that they found it. │ │ │ │ │ + * Class: OpenLayers.Tile │ │ │ │ │ + * This is a class designed to designate a single tile, however │ │ │ │ │ + * it is explicitly designed to do relatively little. Tiles store │ │ │ │ │ + * information about themselves -- such as the URL that they are related │ │ │ │ │ + * to, and their size - but do not add themselves to the layer div │ │ │ │ │ + * automatically, for example. Create a new tile with the │ │ │ │ │ + * constructor, or a subclass. │ │ │ │ │ + * │ │ │ │ │ + * TBD 3.0 - remove reference to url in above paragraph │ │ │ │ │ + * │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Handler = OpenLayers.Class({ │ │ │ │ │ +OpenLayers.Tile = OpenLayers.Class({ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: id │ │ │ │ │ - * {String} │ │ │ │ │ + * APIProperty: events │ │ │ │ │ + * {} An events object that handles all │ │ │ │ │ + * events on the tile. │ │ │ │ │ + * │ │ │ │ │ + * Register a listener for a particular event with the following syntax: │ │ │ │ │ + * (code) │ │ │ │ │ + * tile.events.register(type, obj, listener); │ │ │ │ │ + * (end) │ │ │ │ │ + * │ │ │ │ │ + * Supported event types: │ │ │ │ │ + * beforedraw - Triggered before the tile is drawn. Used to defer │ │ │ │ │ + * drawing to an animation queue. To defer drawing, listeners need │ │ │ │ │ + * to return false, which will abort drawing. The queue handler needs │ │ │ │ │ + * to call (true) to actually draw the tile. │ │ │ │ │ + * loadstart - Triggered when tile loading starts. │ │ │ │ │ + * loadend - Triggered when tile loading ends. │ │ │ │ │ + * loaderror - Triggered before the loadend event (i.e. when the tile is │ │ │ │ │ + * still hidden) if the tile could not be loaded. │ │ │ │ │ + * reload - Triggered when an already loading tile is reloaded. │ │ │ │ │ + * unload - Triggered before a tile is unloaded. │ │ │ │ │ */ │ │ │ │ │ - id: null, │ │ │ │ │ + events: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: control │ │ │ │ │ - * {}. The control that initialized this handler. The │ │ │ │ │ - * control is assumed to have a valid map property - that map is used │ │ │ │ │ - * in the handler's own setMap method. │ │ │ │ │ + * APIProperty: eventListeners │ │ │ │ │ + * {Object} If set as an option at construction, the eventListeners │ │ │ │ │ + * object will be registered with . Object │ │ │ │ │ + * structure must be a listeners object as shown in the example for │ │ │ │ │ + * the events.on method. │ │ │ │ │ + * │ │ │ │ │ + * This options can be set in the ``tileOptions`` option from │ │ │ │ │ + * . For example, to be notified of the │ │ │ │ │ + * ``loadend`` event of each tiles: │ │ │ │ │ + * (code) │ │ │ │ │ + * new OpenLayers.Layer.OSM('osm', 'http://tile.openstreetmap.org/${z}/${x}/${y}.png', { │ │ │ │ │ + * tileOptions: { │ │ │ │ │ + * eventListeners: { │ │ │ │ │ + * 'loadend': function(evt) { │ │ │ │ │ + * // do something on loadend │ │ │ │ │ + * } │ │ │ │ │ + * } │ │ │ │ │ + * } │ │ │ │ │ + * }); │ │ │ │ │ + * (end) │ │ │ │ │ */ │ │ │ │ │ - control: null, │ │ │ │ │ + eventListeners: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: map │ │ │ │ │ - * {} │ │ │ │ │ + * Property: id │ │ │ │ │ + * {String} null │ │ │ │ │ */ │ │ │ │ │ - map: null, │ │ │ │ │ + id: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: layer │ │ │ │ │ + * {} layer the tile is attached to │ │ │ │ │ + */ │ │ │ │ │ + layer: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: keyMask │ │ │ │ │ - * {Integer} Use bitwise operators and one or more of the OpenLayers.Handler │ │ │ │ │ - * constants to construct a keyMask. The keyMask is used by │ │ │ │ │ - * . If the keyMask matches the combination of keys │ │ │ │ │ - * down on an event, checkModifiers returns true. │ │ │ │ │ - * │ │ │ │ │ - * Example: │ │ │ │ │ - * (code) │ │ │ │ │ - * // handler only responds if the Shift key is down │ │ │ │ │ - * handler.keyMask = OpenLayers.Handler.MOD_SHIFT; │ │ │ │ │ + * Property: url │ │ │ │ │ + * {String} url of the request. │ │ │ │ │ * │ │ │ │ │ - * // handler only responds if Ctrl-Shift is down │ │ │ │ │ - * handler.keyMask = OpenLayers.Handler.MOD_SHIFT | │ │ │ │ │ - * OpenLayers.Handler.MOD_CTRL; │ │ │ │ │ - * (end) │ │ │ │ │ + * TBD 3.0 │ │ │ │ │ + * Deprecated. The base tile class does not need an url. This should be │ │ │ │ │ + * handled in subclasses. Does not belong here. │ │ │ │ │ */ │ │ │ │ │ - keyMask: null, │ │ │ │ │ + url: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: active │ │ │ │ │ - * {Boolean} │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: bounds │ │ │ │ │ + * {} null │ │ │ │ │ */ │ │ │ │ │ - active: false, │ │ │ │ │ + bounds: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: evt │ │ │ │ │ - * {Event} This property references the last event handled by the handler. │ │ │ │ │ - * Note that this property is not part of the stable API. Use of the │ │ │ │ │ - * evt property should be restricted to controls in the library │ │ │ │ │ - * or other applications that are willing to update with changes to │ │ │ │ │ - * the OpenLayers code. │ │ │ │ │ + /** │ │ │ │ │ + * Property: size │ │ │ │ │ + * {} null │ │ │ │ │ */ │ │ │ │ │ - evt: null, │ │ │ │ │ + size: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: touch │ │ │ │ │ - * {Boolean} Indicates the support of touch events. When touch events are │ │ │ │ │ - * started touch will be true and all mouse related listeners will do │ │ │ │ │ - * nothing. │ │ │ │ │ + /** │ │ │ │ │ + * Property: position │ │ │ │ │ + * {} Top Left pixel of the tile │ │ │ │ │ */ │ │ │ │ │ - touch: false, │ │ │ │ │ + position: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Handler │ │ │ │ │ - * Construct a handler. │ │ │ │ │ - * │ │ │ │ │ + * Property: isLoading │ │ │ │ │ + * {Boolean} Is the tile loading? │ │ │ │ │ + */ │ │ │ │ │ + isLoading: false, │ │ │ │ │ + │ │ │ │ │ + /** TBD 3.0 -- remove 'url' from the list of parameters to the constructor. │ │ │ │ │ + * there is no need for the base tile class to have a url. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Tile │ │ │ │ │ + * Constructor for a new instance. │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * control - {} The control that initialized this │ │ │ │ │ - * handler. The control is assumed to have a valid map property; that │ │ │ │ │ - * map is used in the handler's own setMap method. If a map property │ │ │ │ │ - * is present in the options argument it will be used instead. │ │ │ │ │ - * callbacks - {Object} An object whose properties correspond to abstracted │ │ │ │ │ - * events or sequences of browser events. The values for these │ │ │ │ │ - * properties are functions defined by the control that get called by │ │ │ │ │ - * the handler. │ │ │ │ │ - * options - {Object} An optional object whose properties will be set on │ │ │ │ │ - * the handler. │ │ │ │ │ + * layer - {} layer that the tile will go in. │ │ │ │ │ + * position - {} │ │ │ │ │ + * bounds - {} │ │ │ │ │ + * url - {} │ │ │ │ │ + * size - {} │ │ │ │ │ + * options - {Object} │ │ │ │ │ */ │ │ │ │ │ - initialize: function(control, callbacks, options) { │ │ │ │ │ + initialize: function(layer, position, bounds, url, size, options) { │ │ │ │ │ + this.layer = layer; │ │ │ │ │ + this.position = position.clone(); │ │ │ │ │ + this.setBounds(bounds); │ │ │ │ │ + this.url = url; │ │ │ │ │ + if (size) { │ │ │ │ │ + this.size = size.clone(); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + //give the tile a unique id based on its BBOX. │ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID("Tile_"); │ │ │ │ │ + │ │ │ │ │ OpenLayers.Util.extend(this, options); │ │ │ │ │ - this.control = control; │ │ │ │ │ - this.callbacks = callbacks; │ │ │ │ │ │ │ │ │ │ - var map = this.map || control.map; │ │ │ │ │ - if (map) { │ │ │ │ │ - this.setMap(map); │ │ │ │ │ + this.events = new OpenLayers.Events(this); │ │ │ │ │ + if (this.eventListeners instanceof Object) { │ │ │ │ │ + this.events.on(this.eventListeners); │ │ │ │ │ } │ │ │ │ │ - │ │ │ │ │ - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: setMap │ │ │ │ │ + * Method: unload │ │ │ │ │ + * Call immediately before destroying if you are listening to tile │ │ │ │ │ + * events, so that counters are properly handled if tile is still │ │ │ │ │ + * loading at destroy-time. Will only fire an event if the tile is │ │ │ │ │ + * still loading. │ │ │ │ │ */ │ │ │ │ │ - setMap: function(map) { │ │ │ │ │ - this.map = map; │ │ │ │ │ + unload: function() { │ │ │ │ │ + if (this.isLoading) { │ │ │ │ │ + this.isLoading = false; │ │ │ │ │ + this.events.triggerEvent("unload"); │ │ │ │ │ + } │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: checkModifiers │ │ │ │ │ - * Check the keyMask on the handler. If no is set, this always │ │ │ │ │ - * returns true. If a is set and it matches the combination │ │ │ │ │ - * of keys down on an event, this returns true. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} The keyMask matches the keys down on an event. │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: destroy │ │ │ │ │ + * Nullify references to prevent circular references and memory leaks. │ │ │ │ │ */ │ │ │ │ │ - checkModifiers: function(evt) { │ │ │ │ │ - if (this.keyMask == null) { │ │ │ │ │ - return true; │ │ │ │ │ - } │ │ │ │ │ - /* calculate the keyboard modifier mask for this event */ │ │ │ │ │ - var keyModifiers = │ │ │ │ │ - (evt.shiftKey ? OpenLayers.Handler.MOD_SHIFT : 0) | │ │ │ │ │ - (evt.ctrlKey ? OpenLayers.Handler.MOD_CTRL : 0) | │ │ │ │ │ - (evt.altKey ? OpenLayers.Handler.MOD_ALT : 0) | │ │ │ │ │ - (evt.metaKey ? OpenLayers.Handler.MOD_META : 0); │ │ │ │ │ + destroy: function() { │ │ │ │ │ + this.layer = null; │ │ │ │ │ + this.bounds = null; │ │ │ │ │ + this.size = null; │ │ │ │ │ + this.position = null; │ │ │ │ │ │ │ │ │ │ - /* if it differs from the handler object's key mask, │ │ │ │ │ - bail out of the event handler */ │ │ │ │ │ - return (keyModifiers == this.keyMask); │ │ │ │ │ + if (this.eventListeners) { │ │ │ │ │ + this.events.un(this.eventListeners); │ │ │ │ │ + } │ │ │ │ │ + this.events.destroy(); │ │ │ │ │ + this.eventListeners = null; │ │ │ │ │ + this.events = null; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: activate │ │ │ │ │ - * Turn on the handler. Returns false if the handler was already active. │ │ │ │ │ + * Method: draw │ │ │ │ │ + * Clear whatever is currently in the tile, then return whether or not │ │ │ │ │ + * it should actually be re-drawn. This is an example implementation │ │ │ │ │ + * that can be overridden by subclasses. The minimum thing to do here │ │ │ │ │ + * is to call and return the result from . │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * force - {Boolean} If true, the tile will not be cleared and no beforedraw │ │ │ │ │ + * event will be fired. This is used for drawing tiles asynchronously │ │ │ │ │ + * after drawing has been cancelled by returning false from a beforedraw │ │ │ │ │ + * listener. │ │ │ │ │ * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} The handler was activated. │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Whether or not the tile should actually be drawn. Returns null │ │ │ │ │ + * if a beforedraw listener returned false. │ │ │ │ │ */ │ │ │ │ │ - activate: function() { │ │ │ │ │ - if (this.active) { │ │ │ │ │ - return false; │ │ │ │ │ + draw: function(force) { │ │ │ │ │ + if (!force) { │ │ │ │ │ + //clear tile's contents and mark as not drawn │ │ │ │ │ + this.clear(); │ │ │ │ │ } │ │ │ │ │ - // register for event handlers defined on this class. │ │ │ │ │ - var events = OpenLayers.Events.prototype.BROWSER_EVENTS; │ │ │ │ │ - for (var i = 0, len = events.length; i < len; i++) { │ │ │ │ │ - if (this[events[i]]) { │ │ │ │ │ - this.register(events[i], this[events[i]]); │ │ │ │ │ - } │ │ │ │ │ + var draw = this.shouldDraw(); │ │ │ │ │ + if (draw && !force && this.events.triggerEvent("beforedraw") === false) { │ │ │ │ │ + draw = null; │ │ │ │ │ } │ │ │ │ │ - this.active = true; │ │ │ │ │ - return true; │ │ │ │ │ + return draw; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: deactivate │ │ │ │ │ - * Turn off the handler. Returns false if the handler was already inactive. │ │ │ │ │ + * Method: shouldDraw │ │ │ │ │ + * Return whether or not the tile should actually be (re-)drawn. The only │ │ │ │ │ + * case where we *wouldn't* want to draw the tile is if the tile is outside │ │ │ │ │ + * its layer's maxExtent │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Boolean} The handler was deactivated. │ │ │ │ │ + * {Boolean} Whether or not the tile should actually be drawn. │ │ │ │ │ */ │ │ │ │ │ - deactivate: function() { │ │ │ │ │ - if (!this.active) { │ │ │ │ │ - return false; │ │ │ │ │ - } │ │ │ │ │ - // unregister event handlers defined on this class. │ │ │ │ │ - var events = OpenLayers.Events.prototype.BROWSER_EVENTS; │ │ │ │ │ - for (var i = 0, len = events.length; i < len; i++) { │ │ │ │ │ - if (this[events[i]]) { │ │ │ │ │ - this.unregister(events[i], this[events[i]]); │ │ │ │ │ + shouldDraw: function() { │ │ │ │ │ + var withinMaxExtent = false, │ │ │ │ │ + maxExtent = this.layer.maxExtent; │ │ │ │ │ + if (maxExtent) { │ │ │ │ │ + var map = this.layer.map; │ │ │ │ │ + var worldBounds = map.baseLayer.wrapDateLine && map.getMaxExtent(); │ │ │ │ │ + if (this.bounds.intersectsBounds(maxExtent, { │ │ │ │ │ + inclusive: false, │ │ │ │ │ + worldBounds: worldBounds │ │ │ │ │ + })) { │ │ │ │ │ + withinMaxExtent = true; │ │ │ │ │ } │ │ │ │ │ } │ │ │ │ │ - this.touch = false; │ │ │ │ │ - this.active = false; │ │ │ │ │ - return true; │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: startTouch │ │ │ │ │ - * Start touch events, this method must be called by subclasses in │ │ │ │ │ - * "touchstart" method. When touch events are started will be │ │ │ │ │ - * true and all mouse related listeners will do nothing. │ │ │ │ │ - */ │ │ │ │ │ - startTouch: function() { │ │ │ │ │ - if (!this.touch) { │ │ │ │ │ - this.touch = true; │ │ │ │ │ - var events = [ │ │ │ │ │ - "mousedown", "mouseup", "mousemove", "click", "dblclick", │ │ │ │ │ - "mouseout" │ │ │ │ │ - ]; │ │ │ │ │ - for (var i = 0, len = events.length; i < len; i++) { │ │ │ │ │ - if (this[events[i]]) { │ │ │ │ │ - this.unregister(events[i], this[events[i]]); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ + return withinMaxExtent || this.layer.displayOutsideMaxExtent; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: callback │ │ │ │ │ - * Trigger the control's named callback with the given arguments │ │ │ │ │ + * Method: setBounds │ │ │ │ │ + * Sets the bounds on this instance │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * name - {String} The key for the callback that is one of the properties │ │ │ │ │ - * of the handler's callbacks object. │ │ │ │ │ - * args - {Array(*)} An array of arguments (any type) with which to call │ │ │ │ │ - * the callback (defined by the control). │ │ │ │ │ + * bounds {} │ │ │ │ │ */ │ │ │ │ │ - callback: function(name, args) { │ │ │ │ │ - if (name && this.callbacks[name]) { │ │ │ │ │ - this.callbacks[name].apply(this.control, args); │ │ │ │ │ + setBounds: function(bounds) { │ │ │ │ │ + bounds = bounds.clone(); │ │ │ │ │ + if (this.layer.map.baseLayer.wrapDateLine) { │ │ │ │ │ + var worldExtent = this.layer.map.getMaxExtent(), │ │ │ │ │ + tolerance = this.layer.map.getResolution(); │ │ │ │ │ + bounds = bounds.wrapDateLine(worldExtent, { │ │ │ │ │ + leftTolerance: tolerance, │ │ │ │ │ + rightTolerance: tolerance │ │ │ │ │ + }); │ │ │ │ │ } │ │ │ │ │ + this.bounds = bounds; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: register │ │ │ │ │ - * register an event on the map │ │ │ │ │ - */ │ │ │ │ │ - register: function(name, method) { │ │ │ │ │ - // TODO: deal with registerPriority in 3.0 │ │ │ │ │ - this.map.events.registerPriority(name, this, method); │ │ │ │ │ - this.map.events.registerPriority(name, this, this.setEvent); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: unregister │ │ │ │ │ - * unregister an event from the map │ │ │ │ │ - */ │ │ │ │ │ - unregister: function(name, method) { │ │ │ │ │ - this.map.events.unregister(name, this, method); │ │ │ │ │ - this.map.events.unregister(name, this, this.setEvent); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: setEvent │ │ │ │ │ - * With each registered browser event, the handler sets its own evt │ │ │ │ │ - * property. This property can be accessed by controls if needed │ │ │ │ │ - * to get more information about the event that the handler is │ │ │ │ │ - * processing. │ │ │ │ │ - * │ │ │ │ │ - * This allows modifier keys on the event to be checked (alt, shift, ctrl, │ │ │ │ │ - * and meta cannot be checked with the keyboard handler). For a │ │ │ │ │ - * control to determine which modifier keys are associated with the │ │ │ │ │ - * event that a handler is currently processing, it should access │ │ │ │ │ - * (code)handler.evt.altKey || handler.evt.shiftKey || │ │ │ │ │ - * handler.evt.ctrlKey || handler.evt.metaKey(end). │ │ │ │ │ + /** │ │ │ │ │ + * Method: moveTo │ │ │ │ │ + * Reposition the tile. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * evt - {Event} The browser event. │ │ │ │ │ + * bounds - {} │ │ │ │ │ + * position - {} │ │ │ │ │ + * redraw - {Boolean} Call draw method on tile after moving. │ │ │ │ │ + * Default is true │ │ │ │ │ */ │ │ │ │ │ - setEvent: function(evt) { │ │ │ │ │ - this.evt = evt; │ │ │ │ │ - return true; │ │ │ │ │ + moveTo: function(bounds, position, redraw) { │ │ │ │ │ + if (redraw == null) { │ │ │ │ │ + redraw = true; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + this.setBounds(bounds); │ │ │ │ │ + this.position = position.clone(); │ │ │ │ │ + if (redraw) { │ │ │ │ │ + this.draw(); │ │ │ │ │ + } │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: destroy │ │ │ │ │ - * Deconstruct the handler. │ │ │ │ │ + /** │ │ │ │ │ + * Method: clear │ │ │ │ │ + * Clear the tile of any bounds/position-related data so that it can │ │ │ │ │ + * be reused in a new location. │ │ │ │ │ */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - // unregister event listeners │ │ │ │ │ - this.deactivate(); │ │ │ │ │ - // eliminate circular references │ │ │ │ │ - this.control = this.map = null; │ │ │ │ │ + clear: function(draw) { │ │ │ │ │ + // to be extended by subclasses │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Handler" │ │ │ │ │ + CLASS_NAME: "OpenLayers.Tile" │ │ │ │ │ }); │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Handler.MOD_NONE │ │ │ │ │ - * If set as the , returns false if any key is down. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Handler.MOD_NONE = 0; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Handler.MOD_SHIFT │ │ │ │ │ - * If set as the , returns false if Shift is down. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Handler.MOD_SHIFT = 1; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Handler.MOD_CTRL │ │ │ │ │ - * If set as the , returns false if Ctrl is down. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Handler.MOD_CTRL = 2; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Handler.MOD_ALT │ │ │ │ │ - * If set as the , returns false if Alt is down. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Handler.MOD_ALT = 4; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Handler.MOD_META │ │ │ │ │ - * If set as the , returns false if Cmd is down. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Handler.MOD_META = 8; │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Format/WPSDescribeProcess.js │ │ │ │ │ + OpenLayers/Icon.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/Format/XML.js │ │ │ │ │ - * @requires OpenLayers/Format/OWSCommon/v1_1_0.js │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Format.WPSDescribeProcess │ │ │ │ │ - * Read WPS DescribeProcess responses. │ │ │ │ │ + * Class: OpenLayers.Icon │ │ │ │ │ + * │ │ │ │ │ + * The icon represents a graphical icon on the screen. Typically used in │ │ │ │ │ + * conjunction with a to represent markers on a screen. │ │ │ │ │ * │ │ │ │ │ - * Inherits from: │ │ │ │ │ - * - │ │ │ │ │ + * An icon has a url, size and position. It also contains an offset which │ │ │ │ │ + * allows the center point to be represented correctly. This can be │ │ │ │ │ + * provided either as a fixed offset or a function provided to calculate │ │ │ │ │ + * the desired offset. │ │ │ │ │ + * │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Format.WPSDescribeProcess = OpenLayers.Class( │ │ │ │ │ - OpenLayers.Format.XML, { │ │ │ │ │ +OpenLayers.Icon = OpenLayers.Class({ │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Constant: VERSION │ │ │ │ │ - * {String} 1.0.0 │ │ │ │ │ - */ │ │ │ │ │ - VERSION: "1.0.0", │ │ │ │ │ + /** │ │ │ │ │ + * Property: url │ │ │ │ │ + * {String} image url │ │ │ │ │ + */ │ │ │ │ │ + url: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: namespaces │ │ │ │ │ - * {Object} Mapping of namespace aliases to namespace URIs. │ │ │ │ │ - */ │ │ │ │ │ - namespaces: { │ │ │ │ │ - wps: "http://www.opengis.net/wps/1.0.0", │ │ │ │ │ - ows: "http://www.opengis.net/ows/1.1", │ │ │ │ │ - xsi: "http://www.w3.org/2001/XMLSchema-instance" │ │ │ │ │ - }, │ │ │ │ │ + /** │ │ │ │ │ + * Property: size │ │ │ │ │ + * {|Object} An OpenLayers.Size or │ │ │ │ │ + * an object with a 'w' and 'h' properties. │ │ │ │ │ + */ │ │ │ │ │ + size: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: schemaLocation │ │ │ │ │ - * {String} Schema location │ │ │ │ │ - */ │ │ │ │ │ - schemaLocation: "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd", │ │ │ │ │ + /** │ │ │ │ │ + * Property: offset │ │ │ │ │ + * {|Object} distance in pixels to offset the │ │ │ │ │ + * image when being rendered. An OpenLayers.Pixel or an object │ │ │ │ │ + * with a 'x' and 'y' properties. │ │ │ │ │ + */ │ │ │ │ │ + offset: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: defaultPrefix │ │ │ │ │ - */ │ │ │ │ │ - defaultPrefix: "wps", │ │ │ │ │ + /** │ │ │ │ │ + * Property: calculateOffset │ │ │ │ │ + * {Function} Function to calculate the offset (based on the size) │ │ │ │ │ + */ │ │ │ │ │ + calculateOffset: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: regExes │ │ │ │ │ - * Compiled regular expressions for manipulating strings. │ │ │ │ │ - */ │ │ │ │ │ - regExes: { │ │ │ │ │ - trimSpace: (/^\s*|\s*$/g), │ │ │ │ │ - removeSpace: (/\s*/g), │ │ │ │ │ - splitSpace: (/\s+/), │ │ │ │ │ - trimComma: (/\s*,\s*/g) │ │ │ │ │ - }, │ │ │ │ │ + /** │ │ │ │ │ + * Property: imageDiv │ │ │ │ │ + * {DOMElement} │ │ │ │ │ + */ │ │ │ │ │ + imageDiv: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Format.WPSDescribeProcess │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} An optional object whose properties will be set on │ │ │ │ │ - * this instance. │ │ │ │ │ - */ │ │ │ │ │ + /** │ │ │ │ │ + * Property: px │ │ │ │ │ + * {|Object} An OpenLayers.Pixel or an object │ │ │ │ │ + * with a 'x' and 'y' properties. │ │ │ │ │ + */ │ │ │ │ │ + px: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: read │ │ │ │ │ - * Parse a WPS DescribeProcess and return an object with its information. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * data - {String} or {DOMElement} data to read/parse. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} │ │ │ │ │ - */ │ │ │ │ │ - read: function(data) { │ │ │ │ │ - if (typeof data == "string") { │ │ │ │ │ - data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); │ │ │ │ │ - } │ │ │ │ │ - if (data && data.nodeType == 9) { │ │ │ │ │ - data = data.documentElement; │ │ │ │ │ - } │ │ │ │ │ - var info = {}; │ │ │ │ │ - this.readNode(data, info); │ │ │ │ │ - return info; │ │ │ │ │ - }, │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Icon │ │ │ │ │ + * Creates an icon, which is an image tag in a div. │ │ │ │ │ + * │ │ │ │ │ + * url - {String} │ │ │ │ │ + * size - {|Object} An OpenLayers.Size or an │ │ │ │ │ + * object with a 'w' and 'h' │ │ │ │ │ + * properties. │ │ │ │ │ + * offset - {|Object} An OpenLayers.Pixel or an │ │ │ │ │ + * object with a 'x' and 'y' │ │ │ │ │ + * properties. │ │ │ │ │ + * calculateOffset - {Function} │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(url, size, offset, calculateOffset) { │ │ │ │ │ + this.url = url; │ │ │ │ │ + this.size = size || { │ │ │ │ │ + w: 20, │ │ │ │ │ + h: 20 │ │ │ │ │ + }; │ │ │ │ │ + this.offset = offset || { │ │ │ │ │ + x: -(this.size.w / 2), │ │ │ │ │ + y: -(this.size.h / 2) │ │ │ │ │ + }; │ │ │ │ │ + this.calculateOffset = calculateOffset; │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: readers │ │ │ │ │ - * Contains public functions, grouped by namespace prefix, that will │ │ │ │ │ - * be applied when a namespaced node is found matching the function │ │ │ │ │ - * name. The function will be applied in the scope of this parser │ │ │ │ │ - * with two arguments: the node being read and a context object passed │ │ │ │ │ - * from the parent. │ │ │ │ │ - */ │ │ │ │ │ - readers: { │ │ │ │ │ - "wps": { │ │ │ │ │ - "ProcessDescriptions": function(node, obj) { │ │ │ │ │ - obj.processDescriptions = {}; │ │ │ │ │ - this.readChildNodes(node, obj.processDescriptions); │ │ │ │ │ - }, │ │ │ │ │ - "ProcessDescription": function(node, processDescriptions) { │ │ │ │ │ - var processVersion = this.getAttributeNS(node, this.namespaces.wps, "processVersion"); │ │ │ │ │ - var processDescription = { │ │ │ │ │ - processVersion: processVersion, │ │ │ │ │ - statusSupported: (node.getAttribute("statusSupported") === "true"), │ │ │ │ │ - storeSupported: (node.getAttribute("storeSupported") === "true") │ │ │ │ │ - }; │ │ │ │ │ - this.readChildNodes(node, processDescription); │ │ │ │ │ - processDescriptions[processDescription.identifier] = processDescription; │ │ │ │ │ - }, │ │ │ │ │ - "DataInputs": function(node, processDescription) { │ │ │ │ │ - processDescription.dataInputs = []; │ │ │ │ │ - this.readChildNodes(node, processDescription.dataInputs); │ │ │ │ │ - }, │ │ │ │ │ - "ProcessOutputs": function(node, processDescription) { │ │ │ │ │ - processDescription.processOutputs = []; │ │ │ │ │ - this.readChildNodes(node, processDescription.processOutputs); │ │ │ │ │ - }, │ │ │ │ │ - "Output": function(node, processOutputs) { │ │ │ │ │ - var output = {}; │ │ │ │ │ - this.readChildNodes(node, output); │ │ │ │ │ - processOutputs.push(output); │ │ │ │ │ - }, │ │ │ │ │ - "ComplexOutput": function(node, output) { │ │ │ │ │ - output.complexOutput = {}; │ │ │ │ │ - this.readChildNodes(node, output.complexOutput); │ │ │ │ │ - }, │ │ │ │ │ - "LiteralOutput": function(node, output) { │ │ │ │ │ - output.literalOutput = {}; │ │ │ │ │ - this.readChildNodes(node, output.literalOutput); │ │ │ │ │ - }, │ │ │ │ │ - "Input": function(node, dataInputs) { │ │ │ │ │ - var input = { │ │ │ │ │ - maxOccurs: parseInt(node.getAttribute("maxOccurs")), │ │ │ │ │ - minOccurs: parseInt(node.getAttribute("minOccurs")) │ │ │ │ │ - }; │ │ │ │ │ - this.readChildNodes(node, input); │ │ │ │ │ - dataInputs.push(input); │ │ │ │ │ - }, │ │ │ │ │ - "BoundingBoxData": function(node, input) { │ │ │ │ │ - input.boundingBoxData = {}; │ │ │ │ │ - this.readChildNodes(node, input.boundingBoxData); │ │ │ │ │ - }, │ │ │ │ │ - "CRS": function(node, obj) { │ │ │ │ │ - if (!obj.CRSs) { │ │ │ │ │ - obj.CRSs = {}; │ │ │ │ │ - } │ │ │ │ │ - obj.CRSs[this.getChildValue(node)] = true; │ │ │ │ │ - }, │ │ │ │ │ - "LiteralData": function(node, input) { │ │ │ │ │ - input.literalData = {}; │ │ │ │ │ - this.readChildNodes(node, input.literalData); │ │ │ │ │ - }, │ │ │ │ │ - "ComplexData": function(node, input) { │ │ │ │ │ - input.complexData = {}; │ │ │ │ │ - this.readChildNodes(node, input.complexData); │ │ │ │ │ - }, │ │ │ │ │ - "Default": function(node, complexData) { │ │ │ │ │ - complexData["default"] = {}; │ │ │ │ │ - this.readChildNodes(node, complexData["default"]); │ │ │ │ │ - }, │ │ │ │ │ - "Supported": function(node, complexData) { │ │ │ │ │ - complexData["supported"] = {}; │ │ │ │ │ - this.readChildNodes(node, complexData["supported"]); │ │ │ │ │ - }, │ │ │ │ │ - "Format": function(node, obj) { │ │ │ │ │ - var format = {}; │ │ │ │ │ - this.readChildNodes(node, format); │ │ │ │ │ - if (!obj.formats) { │ │ │ │ │ - obj.formats = {}; │ │ │ │ │ - } │ │ │ │ │ - obj.formats[format.mimeType] = true; │ │ │ │ │ - }, │ │ │ │ │ - "MimeType": function(node, format) { │ │ │ │ │ - format.mimeType = this.getChildValue(node); │ │ │ │ │ + var id = OpenLayers.Util.createUniqueID("OL_Icon_"); │ │ │ │ │ + this.imageDiv = OpenLayers.Util.createAlphaImageDiv(id); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: destroy │ │ │ │ │ + * Nullify references and remove event listeners to prevent circular │ │ │ │ │ + * references and memory leaks │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + // erase any drawn elements │ │ │ │ │ + this.erase(); │ │ │ │ │ + │ │ │ │ │ + OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild); │ │ │ │ │ + this.imageDiv.innerHTML = ""; │ │ │ │ │ + this.imageDiv = null; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: clone │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} A fresh copy of the icon. │ │ │ │ │ + */ │ │ │ │ │ + clone: function() { │ │ │ │ │ + return new OpenLayers.Icon(this.url, │ │ │ │ │ + this.size, │ │ │ │ │ + this.offset, │ │ │ │ │ + this.calculateOffset); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: setSize │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * size - {|Object} An OpenLayers.Size or │ │ │ │ │ + * an object with a 'w' and 'h' properties. │ │ │ │ │ + */ │ │ │ │ │ + setSize: function(size) { │ │ │ │ │ + if (size != null) { │ │ │ │ │ + this.size = size; │ │ │ │ │ + } │ │ │ │ │ + this.draw(); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: setUrl │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * url - {String} │ │ │ │ │ + */ │ │ │ │ │ + setUrl: function(url) { │ │ │ │ │ + if (url != null) { │ │ │ │ │ + this.url = url; │ │ │ │ │ + } │ │ │ │ │ + this.draw(); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: draw │ │ │ │ │ + * Move the div to the given pixel. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * px - {|Object} An OpenLayers.Pixel or an │ │ │ │ │ + * object with a 'x' and 'y' properties. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {DOMElement} A new DOM Image of this icon set at the location passed-in │ │ │ │ │ + */ │ │ │ │ │ + draw: function(px) { │ │ │ │ │ + OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, │ │ │ │ │ + null, │ │ │ │ │ + null, │ │ │ │ │ + this.size, │ │ │ │ │ + this.url, │ │ │ │ │ + "absolute"); │ │ │ │ │ + this.moveTo(px); │ │ │ │ │ + return this.imageDiv; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: erase │ │ │ │ │ + * Erase the underlying image element. │ │ │ │ │ + */ │ │ │ │ │ + erase: function() { │ │ │ │ │ + if (this.imageDiv != null && this.imageDiv.parentNode != null) { │ │ │ │ │ + OpenLayers.Element.remove(this.imageDiv); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: setOpacity │ │ │ │ │ + * Change the icon's opacity │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * opacity - {float} │ │ │ │ │ + */ │ │ │ │ │ + setOpacity: function(opacity) { │ │ │ │ │ + OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null, │ │ │ │ │ + null, null, null, null, opacity); │ │ │ │ │ + │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: moveTo │ │ │ │ │ + * move icon to passed in px. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * px - {|Object} the pixel position to move to. │ │ │ │ │ + * An OpenLayers.Pixel or an object with a 'x' and 'y' properties. │ │ │ │ │ + */ │ │ │ │ │ + moveTo: function(px) { │ │ │ │ │ + //if no px passed in, use stored location │ │ │ │ │ + if (px != null) { │ │ │ │ │ + this.px = px; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + if (this.imageDiv != null) { │ │ │ │ │ + if (this.px == null) { │ │ │ │ │ + this.display(false); │ │ │ │ │ + } else { │ │ │ │ │ + if (this.calculateOffset) { │ │ │ │ │ + this.offset = this.calculateOffset(this.size); │ │ │ │ │ } │ │ │ │ │ - }, │ │ │ │ │ - "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"] │ │ │ │ │ - }, │ │ │ │ │ + OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, { │ │ │ │ │ + x: this.px.x + this.offset.x, │ │ │ │ │ + y: this.px.y + this.offset.y │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Format.WPSDescribeProcess" │ │ │ │ │ + /** │ │ │ │ │ + * Method: display │ │ │ │ │ + * Hide or show the icon │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * display - {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + display: function(display) { │ │ │ │ │ + this.imageDiv.style.display = (display) ? "" : "none"; │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - }); │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: isDrawn │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Whether or not the icon is drawn. │ │ │ │ │ + */ │ │ │ │ │ + isDrawn: function() { │ │ │ │ │ + // nodeType 11 for ie, whose nodes *always* have a parentNode │ │ │ │ │ + // (of type document fragment) │ │ │ │ │ + var isDrawn = (this.imageDiv && this.imageDiv.parentNode && │ │ │ │ │ + (this.imageDiv.parentNode.nodeType != 11)); │ │ │ │ │ + │ │ │ │ │ + return isDrawn; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Icon" │ │ │ │ │ +}); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/WPSClient.js │ │ │ │ │ + OpenLayers/Strategy.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/SingleFile.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Events.js │ │ │ │ │ - * @requires OpenLayers/WPSProcess.js │ │ │ │ │ - * @requires OpenLayers/Format/WPSDescribeProcess.js │ │ │ │ │ - * @requires OpenLayers/Request.js │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.WPSClient │ │ │ │ │ - * High level API for interaction with Web Processing Services (WPS). │ │ │ │ │ - * An instance is used to create │ │ │ │ │ - * instances for servers known to the WPSClient. The WPSClient also caches │ │ │ │ │ - * DescribeProcess responses to reduce the number of requests sent to servers │ │ │ │ │ - * when processes are created. │ │ │ │ │ + * Class: OpenLayers.Strategy │ │ │ │ │ + * Abstract vector layer strategy class. Not to be instantiated directly. Use │ │ │ │ │ + * one of the strategy subclasses instead. │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.WPSClient = OpenLayers.Class({ │ │ │ │ │ +OpenLayers.Strategy = OpenLayers.Class({ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: servers │ │ │ │ │ - * {Object} Service metadata, keyed by a local identifier. │ │ │ │ │ - * │ │ │ │ │ - * Properties: │ │ │ │ │ - * url - {String} the url of the server │ │ │ │ │ - * version - {String} WPS version of the server │ │ │ │ │ - * processDescription - {Object} Cache of raw DescribeProcess │ │ │ │ │ - * responses, keyed by process identifier. │ │ │ │ │ + * Property: layer │ │ │ │ │ + * {} The layer this strategy belongs to. │ │ │ │ │ */ │ │ │ │ │ - servers: null, │ │ │ │ │ + layer: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: version │ │ │ │ │ - * {String} The default WPS version to use if none is configured. Default │ │ │ │ │ - * is '1.0.0'. │ │ │ │ │ + * Property: options │ │ │ │ │ + * {Object} Any options sent to the constructor. │ │ │ │ │ */ │ │ │ │ │ - version: '1.0.0', │ │ │ │ │ + options: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: active │ │ │ │ │ + * {Boolean} The control is active. │ │ │ │ │ + */ │ │ │ │ │ + active: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: lazy │ │ │ │ │ - * {Boolean} Should the DescribeProcess be deferred until a process is │ │ │ │ │ - * fully configured? Default is false. │ │ │ │ │ + * Property: autoActivate │ │ │ │ │ + * {Boolean} The creator of the strategy can set autoActivate to false │ │ │ │ │ + * to fully control when the protocol is activated and deactivated. │ │ │ │ │ + * Defaults to true. │ │ │ │ │ */ │ │ │ │ │ - lazy: false, │ │ │ │ │ + autoActivate: true, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: events │ │ │ │ │ - * {} │ │ │ │ │ - * │ │ │ │ │ - * Supported event types: │ │ │ │ │ - * describeprocess - Fires when the process description is available. │ │ │ │ │ - * Listeners receive an object with a 'raw' property holding the raw │ │ │ │ │ - * DescribeProcess response, and an 'identifier' property holding the │ │ │ │ │ - * process identifier of the described process. │ │ │ │ │ + * Property: autoDestroy │ │ │ │ │ + * {Boolean} The creator of the strategy can set autoDestroy to false │ │ │ │ │ + * to fully control when the strategy is destroyed. Defaults to │ │ │ │ │ + * true. │ │ │ │ │ */ │ │ │ │ │ - events: null, │ │ │ │ │ + autoDestroy: true, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.WPSClient │ │ │ │ │ + * Constructor: OpenLayers.Strategy │ │ │ │ │ + * Abstract class for vector strategies. Create instances of a subclass. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * options - {Object} Object whose properties will be set on the instance. │ │ │ │ │ - * │ │ │ │ │ - * Avaliable options: │ │ │ │ │ - * servers - {Object} Mandatory. Service metadata, keyed by a local │ │ │ │ │ - * identifier. Can either be a string with the service url or an │ │ │ │ │ - * object literal with additional metadata: │ │ │ │ │ - * │ │ │ │ │ - * (code) │ │ │ │ │ - * servers: { │ │ │ │ │ - * local: '/geoserver/wps' │ │ │ │ │ - * }, { │ │ │ │ │ - * opengeo: { │ │ │ │ │ - * url: 'http://demo.opengeo.org/geoserver/wps', │ │ │ │ │ - * version: '1.0.0' │ │ │ │ │ - * } │ │ │ │ │ - * } │ │ │ │ │ - * (end) │ │ │ │ │ - * │ │ │ │ │ - * lazy - {Boolean} Optional. Set to true if DescribeProcess should not be │ │ │ │ │ - * requested until a process is fully configured. Default is false. │ │ │ │ │ + * options - {Object} Optional object whose properties will be set on the │ │ │ │ │ + * instance. │ │ │ │ │ */ │ │ │ │ │ initialize: function(options) { │ │ │ │ │ OpenLayers.Util.extend(this, options); │ │ │ │ │ - this.events = new OpenLayers.Events(this); │ │ │ │ │ - this.servers = {}; │ │ │ │ │ - for (var s in options.servers) { │ │ │ │ │ - this.servers[s] = typeof options.servers[s] == 'string' ? { │ │ │ │ │ - url: options.servers[s], │ │ │ │ │ - version: this.version, │ │ │ │ │ - processDescription: {} │ │ │ │ │ - } : options.servers[s]; │ │ │ │ │ - } │ │ │ │ │ + this.options = options; │ │ │ │ │ + // set the active property here, so that user cannot override it │ │ │ │ │ + this.active = false; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: execute │ │ │ │ │ - * Shortcut to execute a process with a single function call. This is │ │ │ │ │ - * equivalent to using and then calling execute on the │ │ │ │ │ - * process. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} Options for the execute operation. │ │ │ │ │ - * │ │ │ │ │ - * Available options: │ │ │ │ │ - * server - {String} Mandatory. One of the local identifiers of the │ │ │ │ │ - * configured servers. │ │ │ │ │ - * process - {String} Mandatory. A process identifier known to the │ │ │ │ │ - * server. │ │ │ │ │ - * inputs - {Object} The inputs for the process, keyed by input identifier. │ │ │ │ │ - * For spatial data inputs, the value of an input is usually an │ │ │ │ │ - * , an or an array of │ │ │ │ │ - * geometries or features. │ │ │ │ │ - * output - {String} The identifier of an output to parse. Optional. If not │ │ │ │ │ - * provided, the first output will be parsed. │ │ │ │ │ - * success - {Function} Callback to call when the process is complete. │ │ │ │ │ - * This function is called with an outputs object as argument, which │ │ │ │ │ - * will have a property with the identifier of the requested output │ │ │ │ │ - * (e.g. 'result'). For processes that generate spatial output, the │ │ │ │ │ - * value will either be a single or an │ │ │ │ │ - * array of features. │ │ │ │ │ - * scope - {Object} Optional scope for the success callback. │ │ │ │ │ + * APIMethod: destroy │ │ │ │ │ + * Clean up the strategy. │ │ │ │ │ */ │ │ │ │ │ - execute: function(options) { │ │ │ │ │ - var process = this.getProcess(options.server, options.process); │ │ │ │ │ - process.execute({ │ │ │ │ │ - inputs: options.inputs, │ │ │ │ │ - success: options.success, │ │ │ │ │ - scope: options.scope │ │ │ │ │ - }); │ │ │ │ │ + destroy: function() { │ │ │ │ │ + this.deactivate(); │ │ │ │ │ + this.layer = null; │ │ │ │ │ + this.options = null; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getProcess │ │ │ │ │ - * Creates an . │ │ │ │ │ + * Method: setLayer │ │ │ │ │ + * Called to set the property. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * serverID - {String} Local identifier from the servers that this instance │ │ │ │ │ - * was constructed with. │ │ │ │ │ - * processID - {String} Process identifier known to the server. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} │ │ │ │ │ + * layer - {} │ │ │ │ │ */ │ │ │ │ │ - getProcess: function(serverID, processID) { │ │ │ │ │ - var process = new OpenLayers.WPSProcess({ │ │ │ │ │ - client: this, │ │ │ │ │ - server: serverID, │ │ │ │ │ - identifier: processID │ │ │ │ │ - }); │ │ │ │ │ - if (!this.lazy) { │ │ │ │ │ - process.describe(); │ │ │ │ │ - } │ │ │ │ │ - return process; │ │ │ │ │ + setLayer: function(layer) { │ │ │ │ │ + this.layer = layer; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: describeProcess │ │ │ │ │ + * Method: activate │ │ │ │ │ + * Activate the strategy. Register any listeners, do appropriate setup. │ │ │ │ │ * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * serverID - {String} Identifier of the server │ │ │ │ │ - * processID - {String} Identifier of the requested process │ │ │ │ │ - * callback - {Function} Callback to call when the description is available │ │ │ │ │ - * scope - {Object} Optional execution scope for the callback function │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} True if the strategy was successfully activated or false if │ │ │ │ │ + * the strategy was already active. │ │ │ │ │ */ │ │ │ │ │ - describeProcess: function(serverID, processID, callback, scope) { │ │ │ │ │ - var server = this.servers[serverID]; │ │ │ │ │ - if (!server.processDescription[processID]) { │ │ │ │ │ - if (!(processID in server.processDescription)) { │ │ │ │ │ - // set to null so we know a describeFeature request is pending │ │ │ │ │ - server.processDescription[processID] = null; │ │ │ │ │ - OpenLayers.Request.GET({ │ │ │ │ │ - url: server.url, │ │ │ │ │ - params: { │ │ │ │ │ - SERVICE: 'WPS', │ │ │ │ │ - VERSION: server.version, │ │ │ │ │ - REQUEST: 'DescribeProcess', │ │ │ │ │ - IDENTIFIER: processID │ │ │ │ │ - }, │ │ │ │ │ - success: function(response) { │ │ │ │ │ - server.processDescription[processID] = response.responseText; │ │ │ │ │ - this.events.triggerEvent('describeprocess', { │ │ │ │ │ - identifier: processID, │ │ │ │ │ - raw: response.responseText │ │ │ │ │ - }); │ │ │ │ │ - }, │ │ │ │ │ - scope: this │ │ │ │ │ - }); │ │ │ │ │ - } else { │ │ │ │ │ - // pending request │ │ │ │ │ - this.events.register('describeprocess', this, function describe(evt) { │ │ │ │ │ - if (evt.identifier === processID) { │ │ │ │ │ - this.events.unregister('describeprocess', this, describe); │ │ │ │ │ - callback.call(scope, evt.raw); │ │ │ │ │ - } │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - } else { │ │ │ │ │ - window.setTimeout(function() { │ │ │ │ │ - callback.call(scope, server.processDescription[processID]); │ │ │ │ │ - }, 0); │ │ │ │ │ + activate: function() { │ │ │ │ │ + if (!this.active) { │ │ │ │ │ + this.active = true; │ │ │ │ │ + return true; │ │ │ │ │ } │ │ │ │ │ + return false; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: destroy │ │ │ │ │ + * Method: deactivate │ │ │ │ │ + * Deactivate the strategy. Unregister any listeners, do appropriate │ │ │ │ │ + * tear-down. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} True if the strategy was successfully deactivated or false if │ │ │ │ │ + * the strategy was already inactive. │ │ │ │ │ */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - this.events.destroy(); │ │ │ │ │ - this.events = null; │ │ │ │ │ - this.servers = null; │ │ │ │ │ + deactivate: function() { │ │ │ │ │ + if (this.active) { │ │ │ │ │ + this.active = false; │ │ │ │ │ + return true; │ │ │ │ │ + } │ │ │ │ │ + return false; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: 'OpenLayers.WPSClient' │ │ │ │ │ - │ │ │ │ │ + CLASS_NAME: "OpenLayers.Strategy" │ │ │ │ │ }); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ OpenLayers/Layer/HTTPRequest.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ @@ -27436,313 +28092,14 @@ │ │ │ │ │ │ │ │ │ │ return OpenLayers.Util.urlAppend(url, paramsString); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ CLASS_NAME: "OpenLayers.Layer.HTTPRequest" │ │ │ │ │ }); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Tile.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - * @requires OpenLayers/Util.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Tile │ │ │ │ │ - * This is a class designed to designate a single tile, however │ │ │ │ │ - * it is explicitly designed to do relatively little. Tiles store │ │ │ │ │ - * information about themselves -- such as the URL that they are related │ │ │ │ │ - * to, and their size - but do not add themselves to the layer div │ │ │ │ │ - * automatically, for example. Create a new tile with the │ │ │ │ │ - * constructor, or a subclass. │ │ │ │ │ - * │ │ │ │ │ - * TBD 3.0 - remove reference to url in above paragraph │ │ │ │ │ - * │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Tile = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: events │ │ │ │ │ - * {} An events object that handles all │ │ │ │ │ - * events on the tile. │ │ │ │ │ - * │ │ │ │ │ - * Register a listener for a particular event with the following syntax: │ │ │ │ │ - * (code) │ │ │ │ │ - * tile.events.register(type, obj, listener); │ │ │ │ │ - * (end) │ │ │ │ │ - * │ │ │ │ │ - * Supported event types: │ │ │ │ │ - * beforedraw - Triggered before the tile is drawn. Used to defer │ │ │ │ │ - * drawing to an animation queue. To defer drawing, listeners need │ │ │ │ │ - * to return false, which will abort drawing. The queue handler needs │ │ │ │ │ - * to call (true) to actually draw the tile. │ │ │ │ │ - * loadstart - Triggered when tile loading starts. │ │ │ │ │ - * loadend - Triggered when tile loading ends. │ │ │ │ │ - * loaderror - Triggered before the loadend event (i.e. when the tile is │ │ │ │ │ - * still hidden) if the tile could not be loaded. │ │ │ │ │ - * reload - Triggered when an already loading tile is reloaded. │ │ │ │ │ - * unload - Triggered before a tile is unloaded. │ │ │ │ │ - */ │ │ │ │ │ - events: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: eventListeners │ │ │ │ │ - * {Object} If set as an option at construction, the eventListeners │ │ │ │ │ - * object will be registered with . Object │ │ │ │ │ - * structure must be a listeners object as shown in the example for │ │ │ │ │ - * the events.on method. │ │ │ │ │ - * │ │ │ │ │ - * This options can be set in the ``tileOptions`` option from │ │ │ │ │ - * . For example, to be notified of the │ │ │ │ │ - * ``loadend`` event of each tiles: │ │ │ │ │ - * (code) │ │ │ │ │ - * new OpenLayers.Layer.OSM('osm', 'http://tile.openstreetmap.org/${z}/${x}/${y}.png', { │ │ │ │ │ - * tileOptions: { │ │ │ │ │ - * eventListeners: { │ │ │ │ │ - * 'loadend': function(evt) { │ │ │ │ │ - * // do something on loadend │ │ │ │ │ - * } │ │ │ │ │ - * } │ │ │ │ │ - * } │ │ │ │ │ - * }); │ │ │ │ │ - * (end) │ │ │ │ │ - */ │ │ │ │ │ - eventListeners: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: id │ │ │ │ │ - * {String} null │ │ │ │ │ - */ │ │ │ │ │ - id: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: layer │ │ │ │ │ - * {} layer the tile is attached to │ │ │ │ │ - */ │ │ │ │ │ - layer: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: url │ │ │ │ │ - * {String} url of the request. │ │ │ │ │ - * │ │ │ │ │ - * TBD 3.0 │ │ │ │ │ - * Deprecated. The base tile class does not need an url. This should be │ │ │ │ │ - * handled in subclasses. Does not belong here. │ │ │ │ │ - */ │ │ │ │ │ - url: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: bounds │ │ │ │ │ - * {} null │ │ │ │ │ - */ │ │ │ │ │ - bounds: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: size │ │ │ │ │ - * {} null │ │ │ │ │ - */ │ │ │ │ │ - size: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: position │ │ │ │ │ - * {} Top Left pixel of the tile │ │ │ │ │ - */ │ │ │ │ │ - position: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: isLoading │ │ │ │ │ - * {Boolean} Is the tile loading? │ │ │ │ │ - */ │ │ │ │ │ - isLoading: false, │ │ │ │ │ - │ │ │ │ │ - /** TBD 3.0 -- remove 'url' from the list of parameters to the constructor. │ │ │ │ │ - * there is no need for the base tile class to have a url. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Tile │ │ │ │ │ - * Constructor for a new instance. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * layer - {} layer that the tile will go in. │ │ │ │ │ - * position - {} │ │ │ │ │ - * bounds - {} │ │ │ │ │ - * url - {} │ │ │ │ │ - * size - {} │ │ │ │ │ - * options - {Object} │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(layer, position, bounds, url, size, options) { │ │ │ │ │ - this.layer = layer; │ │ │ │ │ - this.position = position.clone(); │ │ │ │ │ - this.setBounds(bounds); │ │ │ │ │ - this.url = url; │ │ │ │ │ - if (size) { │ │ │ │ │ - this.size = size.clone(); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - //give the tile a unique id based on its BBOX. │ │ │ │ │ - this.id = OpenLayers.Util.createUniqueID("Tile_"); │ │ │ │ │ - │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - │ │ │ │ │ - this.events = new OpenLayers.Events(this); │ │ │ │ │ - if (this.eventListeners instanceof Object) { │ │ │ │ │ - this.events.on(this.eventListeners); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: unload │ │ │ │ │ - * Call immediately before destroying if you are listening to tile │ │ │ │ │ - * events, so that counters are properly handled if tile is still │ │ │ │ │ - * loading at destroy-time. Will only fire an event if the tile is │ │ │ │ │ - * still loading. │ │ │ │ │ - */ │ │ │ │ │ - unload: function() { │ │ │ │ │ - if (this.isLoading) { │ │ │ │ │ - this.isLoading = false; │ │ │ │ │ - this.events.triggerEvent("unload"); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: destroy │ │ │ │ │ - * Nullify references to prevent circular references and memory leaks. │ │ │ │ │ - */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - this.layer = null; │ │ │ │ │ - this.bounds = null; │ │ │ │ │ - this.size = null; │ │ │ │ │ - this.position = null; │ │ │ │ │ - │ │ │ │ │ - if (this.eventListeners) { │ │ │ │ │ - this.events.un(this.eventListeners); │ │ │ │ │ - } │ │ │ │ │ - this.events.destroy(); │ │ │ │ │ - this.eventListeners = null; │ │ │ │ │ - this.events = null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: draw │ │ │ │ │ - * Clear whatever is currently in the tile, then return whether or not │ │ │ │ │ - * it should actually be re-drawn. This is an example implementation │ │ │ │ │ - * that can be overridden by subclasses. The minimum thing to do here │ │ │ │ │ - * is to call and return the result from . │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * force - {Boolean} If true, the tile will not be cleared and no beforedraw │ │ │ │ │ - * event will be fired. This is used for drawing tiles asynchronously │ │ │ │ │ - * after drawing has been cancelled by returning false from a beforedraw │ │ │ │ │ - * listener. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} Whether or not the tile should actually be drawn. Returns null │ │ │ │ │ - * if a beforedraw listener returned false. │ │ │ │ │ - */ │ │ │ │ │ - draw: function(force) { │ │ │ │ │ - if (!force) { │ │ │ │ │ - //clear tile's contents and mark as not drawn │ │ │ │ │ - this.clear(); │ │ │ │ │ - } │ │ │ │ │ - var draw = this.shouldDraw(); │ │ │ │ │ - if (draw && !force && this.events.triggerEvent("beforedraw") === false) { │ │ │ │ │ - draw = null; │ │ │ │ │ - } │ │ │ │ │ - return draw; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: shouldDraw │ │ │ │ │ - * Return whether or not the tile should actually be (re-)drawn. The only │ │ │ │ │ - * case where we *wouldn't* want to draw the tile is if the tile is outside │ │ │ │ │ - * its layer's maxExtent │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} Whether or not the tile should actually be drawn. │ │ │ │ │ - */ │ │ │ │ │ - shouldDraw: function() { │ │ │ │ │ - var withinMaxExtent = false, │ │ │ │ │ - maxExtent = this.layer.maxExtent; │ │ │ │ │ - if (maxExtent) { │ │ │ │ │ - var map = this.layer.map; │ │ │ │ │ - var worldBounds = map.baseLayer.wrapDateLine && map.getMaxExtent(); │ │ │ │ │ - if (this.bounds.intersectsBounds(maxExtent, { │ │ │ │ │ - inclusive: false, │ │ │ │ │ - worldBounds: worldBounds │ │ │ │ │ - })) { │ │ │ │ │ - withinMaxExtent = true; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - return withinMaxExtent || this.layer.displayOutsideMaxExtent; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: setBounds │ │ │ │ │ - * Sets the bounds on this instance │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * bounds {} │ │ │ │ │ - */ │ │ │ │ │ - setBounds: function(bounds) { │ │ │ │ │ - bounds = bounds.clone(); │ │ │ │ │ - if (this.layer.map.baseLayer.wrapDateLine) { │ │ │ │ │ - var worldExtent = this.layer.map.getMaxExtent(), │ │ │ │ │ - tolerance = this.layer.map.getResolution(); │ │ │ │ │ - bounds = bounds.wrapDateLine(worldExtent, { │ │ │ │ │ - leftTolerance: tolerance, │ │ │ │ │ - rightTolerance: tolerance │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - this.bounds = bounds; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: moveTo │ │ │ │ │ - * Reposition the tile. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * bounds - {} │ │ │ │ │ - * position - {} │ │ │ │ │ - * redraw - {Boolean} Call draw method on tile after moving. │ │ │ │ │ - * Default is true │ │ │ │ │ - */ │ │ │ │ │ - moveTo: function(bounds, position, redraw) { │ │ │ │ │ - if (redraw == null) { │ │ │ │ │ - redraw = true; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - this.setBounds(bounds); │ │ │ │ │ - this.position = position.clone(); │ │ │ │ │ - if (redraw) { │ │ │ │ │ - this.draw(); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: clear │ │ │ │ │ - * Clear the tile of any bounds/position-related data so that it can │ │ │ │ │ - * be reused in a new location. │ │ │ │ │ - */ │ │ │ │ │ - clear: function(draw) { │ │ │ │ │ - // to be extended by subclasses │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Tile" │ │ │ │ │ -}); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ OpenLayers/Tile/Image.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ @@ -29553,547 +29910,1988 @@ │ │ │ │ │ var row = this.grid.pop(); │ │ │ │ │ for (i = 0, l = row.length; i < l; i++) { │ │ │ │ │ var tile = row[i]; │ │ │ │ │ this.destroyTile(tile); │ │ │ │ │ } │ │ │ │ │ } │ │ │ │ │ │ │ │ │ │ - // remove extra columns │ │ │ │ │ - for (i = 0, l = this.grid.length; i < l; i++) { │ │ │ │ │ - while (this.grid[i].length > columns) { │ │ │ │ │ - var row = this.grid[i]; │ │ │ │ │ - var tile = row.pop(); │ │ │ │ │ - this.destroyTile(tile); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ + // remove extra columns │ │ │ │ │ + for (i = 0, l = this.grid.length; i < l; i++) { │ │ │ │ │ + while (this.grid[i].length > columns) { │ │ │ │ │ + var row = this.grid[i]; │ │ │ │ │ + var tile = row.pop(); │ │ │ │ │ + this.destroyTile(tile); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: onMapResize │ │ │ │ │ + * For singleTile layers, this will set a new tile size according to the │ │ │ │ │ + * dimensions of the map pane. │ │ │ │ │ + */ │ │ │ │ │ + onMapResize: function() { │ │ │ │ │ + if (this.singleTile) { │ │ │ │ │ + this.clearGrid(); │ │ │ │ │ + this.setTileSize(); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getTileBounds │ │ │ │ │ + * Returns The tile bounds for a layer given a pixel location. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * viewPortPx - {} The location in the viewport. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} Bounds of the tile at the given pixel location. │ │ │ │ │ + */ │ │ │ │ │ + getTileBounds: function(viewPortPx) { │ │ │ │ │ + var maxExtent = this.maxExtent; │ │ │ │ │ + var resolution = this.getResolution(); │ │ │ │ │ + var tileMapWidth = resolution * this.tileSize.w; │ │ │ │ │ + var tileMapHeight = resolution * this.tileSize.h; │ │ │ │ │ + var mapPoint = this.getLonLatFromViewPortPx(viewPortPx); │ │ │ │ │ + var tileLeft = maxExtent.left + (tileMapWidth * │ │ │ │ │ + Math.floor((mapPoint.lon - │ │ │ │ │ + maxExtent.left) / │ │ │ │ │ + tileMapWidth)); │ │ │ │ │ + var tileBottom = maxExtent.bottom + (tileMapHeight * │ │ │ │ │ + Math.floor((mapPoint.lat - │ │ │ │ │ + maxExtent.bottom) / │ │ │ │ │ + tileMapHeight)); │ │ │ │ │ + return new OpenLayers.Bounds(tileLeft, tileBottom, │ │ │ │ │ + tileLeft + tileMapWidth, │ │ │ │ │ + tileBottom + tileMapHeight); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Layer.Grid" │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/TileManager.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Util.js │ │ │ │ │ + * @requires OpenLayers/BaseTypes.js │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Element.js │ │ │ │ │ + * @requires OpenLayers/Layer/Grid.js │ │ │ │ │ + * @requires OpenLayers/Tile/Image.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.TileManager │ │ │ │ │ + * Provides queueing of image requests and caching of image elements. │ │ │ │ │ + * │ │ │ │ │ + * Queueing avoids unnecessary image requests while changing zoom levels │ │ │ │ │ + * quickly, and helps improve dragging performance on mobile devices that show │ │ │ │ │ + * a lag in dragging when loading of new images starts. and │ │ │ │ │ + * are the configuration options to control this behavior. │ │ │ │ │ + * │ │ │ │ │ + * Caching avoids setting the src on image elements for images that have already │ │ │ │ │ + * been used. Several maps can share a TileManager instance, in which case each │ │ │ │ │ + * map gets its own tile queue, but all maps share the same tile cache. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.TileManager = OpenLayers.Class({ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: cacheSize │ │ │ │ │ + * {Number} Number of image elements to keep referenced in this instance's │ │ │ │ │ + * cache for fast reuse. Default is 256. │ │ │ │ │ + */ │ │ │ │ │ + cacheSize: 256, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: tilesPerFrame │ │ │ │ │ + * {Number} Number of queued tiles to load per frame (see ). │ │ │ │ │ + * Default is 2. │ │ │ │ │ + */ │ │ │ │ │ + tilesPerFrame: 2, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: frameDelay │ │ │ │ │ + * {Number} Delay between tile loading frames (see ) in │ │ │ │ │ + * milliseconds. Default is 16. │ │ │ │ │ + */ │ │ │ │ │ + frameDelay: 16, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: moveDelay │ │ │ │ │ + * {Number} Delay in milliseconds after a map's move event before loading │ │ │ │ │ + * tiles. Default is 100. │ │ │ │ │ + */ │ │ │ │ │ + moveDelay: 100, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: zoomDelay │ │ │ │ │ + * {Number} Delay in milliseconds after a map's zoomend event before loading │ │ │ │ │ + * tiles. Default is 200. │ │ │ │ │ + */ │ │ │ │ │ + zoomDelay: 200, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: maps │ │ │ │ │ + * {Array()} The maps to manage tiles on. │ │ │ │ │ + */ │ │ │ │ │ + maps: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: tileQueueId │ │ │ │ │ + * {Object} The ids of the loop, keyed by map id. │ │ │ │ │ + */ │ │ │ │ │ + tileQueueId: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: tileQueue │ │ │ │ │ + * {Object(Array())} Tiles queued for drawing, keyed by │ │ │ │ │ + * map id. │ │ │ │ │ + */ │ │ │ │ │ + tileQueue: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: tileCache │ │ │ │ │ + * {Object} Cached image elements, keyed by URL. │ │ │ │ │ + */ │ │ │ │ │ + tileCache: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: tileCacheIndex │ │ │ │ │ + * {Array(String)} URLs of cached tiles. First entry is the least recently │ │ │ │ │ + * used. │ │ │ │ │ + */ │ │ │ │ │ + tileCacheIndex: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.TileManager │ │ │ │ │ + * Constructor for a new instance. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * options - {Object} Configuration for this instance. │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(options) { │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ + this.maps = []; │ │ │ │ │ + this.tileQueueId = {}; │ │ │ │ │ + this.tileQueue = {}; │ │ │ │ │ + this.tileCache = {}; │ │ │ │ │ + this.tileCacheIndex = []; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: addMap │ │ │ │ │ + * Binds this instance to a map │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * map - {} │ │ │ │ │ + */ │ │ │ │ │ + addMap: function(map) { │ │ │ │ │ + if (this._destroyed || !OpenLayers.Layer.Grid) { │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + this.maps.push(map); │ │ │ │ │ + this.tileQueue[map.id] = []; │ │ │ │ │ + for (var i = 0, ii = map.layers.length; i < ii; ++i) { │ │ │ │ │ + this.addLayer({ │ │ │ │ │ + layer: map.layers[i] │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + map.events.on({ │ │ │ │ │ + move: this.move, │ │ │ │ │ + zoomend: this.zoomEnd, │ │ │ │ │ + changelayer: this.changeLayer, │ │ │ │ │ + addlayer: this.addLayer, │ │ │ │ │ + preremovelayer: this.removeLayer, │ │ │ │ │ + scope: this │ │ │ │ │ + }); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: removeMap │ │ │ │ │ + * Unbinds this instance from a map │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * map - {} │ │ │ │ │ + */ │ │ │ │ │ + removeMap: function(map) { │ │ │ │ │ + if (this._destroyed || !OpenLayers.Layer.Grid) { │ │ │ │ │ + return; │ │ │ │ │ + } │ │ │ │ │ + window.clearTimeout(this.tileQueueId[map.id]); │ │ │ │ │ + if (map.layers) { │ │ │ │ │ + for (var i = 0, ii = map.layers.length; i < ii; ++i) { │ │ │ │ │ + this.removeLayer({ │ │ │ │ │ + layer: map.layers[i] │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + if (map.events) { │ │ │ │ │ + map.events.un({ │ │ │ │ │ + move: this.move, │ │ │ │ │ + zoomend: this.zoomEnd, │ │ │ │ │ + changelayer: this.changeLayer, │ │ │ │ │ + addlayer: this.addLayer, │ │ │ │ │ + preremovelayer: this.removeLayer, │ │ │ │ │ + scope: this │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + delete this.tileQueue[map.id]; │ │ │ │ │ + delete this.tileQueueId[map.id]; │ │ │ │ │ + OpenLayers.Util.removeItem(this.maps, map); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: move │ │ │ │ │ + * Handles the map's move event │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} Listener argument │ │ │ │ │ + */ │ │ │ │ │ + move: function(evt) { │ │ │ │ │ + this.updateTimeout(evt.object, this.moveDelay, true); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: zoomEnd │ │ │ │ │ + * Handles the map's zoomEnd event │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} Listener argument │ │ │ │ │ + */ │ │ │ │ │ + zoomEnd: function(evt) { │ │ │ │ │ + this.updateTimeout(evt.object, this.zoomDelay); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: changeLayer │ │ │ │ │ + * Handles the map's changeLayer event │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} Listener argument │ │ │ │ │ + */ │ │ │ │ │ + changeLayer: function(evt) { │ │ │ │ │ + if (evt.property === 'visibility' || evt.property === 'params') { │ │ │ │ │ + this.updateTimeout(evt.object, 0); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: addLayer │ │ │ │ │ + * Handles the map's addlayer event │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} The listener argument │ │ │ │ │ + */ │ │ │ │ │ + addLayer: function(evt) { │ │ │ │ │ + var layer = evt.layer; │ │ │ │ │ + if (layer instanceof OpenLayers.Layer.Grid) { │ │ │ │ │ + layer.events.on({ │ │ │ │ │ + addtile: this.addTile, │ │ │ │ │ + retile: this.clearTileQueue, │ │ │ │ │ + scope: this │ │ │ │ │ + }); │ │ │ │ │ + var i, j, tile; │ │ │ │ │ + for (i = layer.grid.length - 1; i >= 0; --i) { │ │ │ │ │ + for (j = layer.grid[i].length - 1; j >= 0; --j) { │ │ │ │ │ + tile = layer.grid[i][j]; │ │ │ │ │ + this.addTile({ │ │ │ │ │ + tile: tile │ │ │ │ │ + }); │ │ │ │ │ + if (tile.url && !tile.imgDiv) { │ │ │ │ │ + this.manageTileCache({ │ │ │ │ │ + object: tile │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: removeLayer │ │ │ │ │ + * Handles the map's preremovelayer event │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} The listener argument │ │ │ │ │ + */ │ │ │ │ │ + removeLayer: function(evt) { │ │ │ │ │ + var layer = evt.layer; │ │ │ │ │ + if (layer instanceof OpenLayers.Layer.Grid) { │ │ │ │ │ + this.clearTileQueue({ │ │ │ │ │ + object: layer │ │ │ │ │ + }); │ │ │ │ │ + if (layer.events) { │ │ │ │ │ + layer.events.un({ │ │ │ │ │ + addtile: this.addTile, │ │ │ │ │ + retile: this.clearTileQueue, │ │ │ │ │ + scope: this │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + if (layer.grid) { │ │ │ │ │ + var i, j, tile; │ │ │ │ │ + for (i = layer.grid.length - 1; i >= 0; --i) { │ │ │ │ │ + for (j = layer.grid[i].length - 1; j >= 0; --j) { │ │ │ │ │ + tile = layer.grid[i][j]; │ │ │ │ │ + this.unloadTile({ │ │ │ │ │ + object: tile │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: updateTimeout │ │ │ │ │ + * Applies the or to the loop, │ │ │ │ │ + * and schedules more queue processing after if there are still │ │ │ │ │ + * tiles in the queue. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * map - {} The map to update the timeout for │ │ │ │ │ + * delay - {Number} The delay to apply │ │ │ │ │ + * nice - {Boolean} If true, the timeout function will only be created if │ │ │ │ │ + * the tilequeue is not empty. This is used by the move handler to │ │ │ │ │ + * avoid impacts on dragging performance. For other events, the tile │ │ │ │ │ + * queue may not be populated yet, so we need to set the timer │ │ │ │ │ + * regardless of the queue size. │ │ │ │ │ + */ │ │ │ │ │ + updateTimeout: function(map, delay, nice) { │ │ │ │ │ + window.clearTimeout(this.tileQueueId[map.id]); │ │ │ │ │ + var tileQueue = this.tileQueue[map.id]; │ │ │ │ │ + if (!nice || tileQueue.length) { │ │ │ │ │ + this.tileQueueId[map.id] = window.setTimeout( │ │ │ │ │ + OpenLayers.Function.bind(function() { │ │ │ │ │ + this.drawTilesFromQueue(map); │ │ │ │ │ + if (tileQueue.length) { │ │ │ │ │ + this.updateTimeout(map, this.frameDelay); │ │ │ │ │ + } │ │ │ │ │ + }, this), delay │ │ │ │ │ + ); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: addTile │ │ │ │ │ + * Listener for the layer's addtile event │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} The listener argument │ │ │ │ │ + */ │ │ │ │ │ + addTile: function(evt) { │ │ │ │ │ + if (evt.tile instanceof OpenLayers.Tile.Image) { │ │ │ │ │ + evt.tile.events.on({ │ │ │ │ │ + beforedraw: this.queueTileDraw, │ │ │ │ │ + beforeload: this.manageTileCache, │ │ │ │ │ + loadend: this.addToCache, │ │ │ │ │ + unload: this.unloadTile, │ │ │ │ │ + scope: this │ │ │ │ │ + }); │ │ │ │ │ + } else { │ │ │ │ │ + // Layer has the wrong tile type, so don't handle it any longer │ │ │ │ │ + this.removeLayer({ │ │ │ │ │ + layer: evt.tile.layer │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: unloadTile │ │ │ │ │ + * Listener for the tile's unload event │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} The listener argument │ │ │ │ │ + */ │ │ │ │ │ + unloadTile: function(evt) { │ │ │ │ │ + var tile = evt.object; │ │ │ │ │ + tile.events.un({ │ │ │ │ │ + beforedraw: this.queueTileDraw, │ │ │ │ │ + beforeload: this.manageTileCache, │ │ │ │ │ + loadend: this.addToCache, │ │ │ │ │ + unload: this.unloadTile, │ │ │ │ │ + scope: this │ │ │ │ │ + }); │ │ │ │ │ + OpenLayers.Util.removeItem(this.tileQueue[tile.layer.map.id], tile); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: queueTileDraw │ │ │ │ │ + * Adds a tile to the queue that will draw it. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} Listener argument of the tile's beforedraw event │ │ │ │ │ + */ │ │ │ │ │ + queueTileDraw: function(evt) { │ │ │ │ │ + var tile = evt.object; │ │ │ │ │ + var queued = false; │ │ │ │ │ + var layer = tile.layer; │ │ │ │ │ + var url = layer.getURL(tile.bounds); │ │ │ │ │ + var img = this.tileCache[url]; │ │ │ │ │ + if (img && img.className !== 'olTileImage') { │ │ │ │ │ + // cached image no longer valid, e.g. because we're olTileReplacing │ │ │ │ │ + delete this.tileCache[url]; │ │ │ │ │ + OpenLayers.Util.removeItem(this.tileCacheIndex, url); │ │ │ │ │ + img = null; │ │ │ │ │ + } │ │ │ │ │ + // queue only if image with same url not cached already │ │ │ │ │ + if (layer.url && (layer.async || !img)) { │ │ │ │ │ + // add to queue only if not in queue already │ │ │ │ │ + var tileQueue = this.tileQueue[layer.map.id]; │ │ │ │ │ + if (!~OpenLayers.Util.indexOf(tileQueue, tile)) { │ │ │ │ │ + tileQueue.push(tile); │ │ │ │ │ + } │ │ │ │ │ + queued = true; │ │ │ │ │ + } │ │ │ │ │ + return !queued; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: drawTilesFromQueue │ │ │ │ │ + * Draws tiles from the tileQueue, and unqueues the tiles │ │ │ │ │ + */ │ │ │ │ │ + drawTilesFromQueue: function(map) { │ │ │ │ │ + var tileQueue = this.tileQueue[map.id]; │ │ │ │ │ + var limit = this.tilesPerFrame; │ │ │ │ │ + var animating = map.zoomTween && map.zoomTween.playing; │ │ │ │ │ + while (!animating && tileQueue.length && limit) { │ │ │ │ │ + tileQueue.shift().draw(true); │ │ │ │ │ + --limit; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: manageTileCache │ │ │ │ │ + * Adds, updates, removes and fetches cache entries. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} Listener argument of the tile's beforeload event │ │ │ │ │ + */ │ │ │ │ │ + manageTileCache: function(evt) { │ │ │ │ │ + var tile = evt.object; │ │ │ │ │ + var img = this.tileCache[tile.url]; │ │ │ │ │ + if (img) { │ │ │ │ │ + // if image is on its layer's backbuffer, remove it from backbuffer │ │ │ │ │ + if (img.parentNode && │ │ │ │ │ + OpenLayers.Element.hasClass(img.parentNode, 'olBackBuffer')) { │ │ │ │ │ + img.parentNode.removeChild(img); │ │ │ │ │ + img.id = null; │ │ │ │ │ + } │ │ │ │ │ + // only use image from cache if it is not on a layer already │ │ │ │ │ + if (!img.parentNode) { │ │ │ │ │ + img.style.visibility = 'hidden'; │ │ │ │ │ + img.style.opacity = 0; │ │ │ │ │ + tile.setImage(img); │ │ │ │ │ + // LRU - move tile to the end of the array to mark it as the most │ │ │ │ │ + // recently used │ │ │ │ │ + OpenLayers.Util.removeItem(this.tileCacheIndex, tile.url); │ │ │ │ │ + this.tileCacheIndex.push(tile.url); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: addToCache │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} Listener argument for the tile's loadend event │ │ │ │ │ + */ │ │ │ │ │ + addToCache: function(evt) { │ │ │ │ │ + var tile = evt.object; │ │ │ │ │ + if (!this.tileCache[tile.url]) { │ │ │ │ │ + if (!OpenLayers.Element.hasClass(tile.imgDiv, 'olImageLoadError')) { │ │ │ │ │ + if (this.tileCacheIndex.length >= this.cacheSize) { │ │ │ │ │ + delete this.tileCache[this.tileCacheIndex[0]]; │ │ │ │ │ + this.tileCacheIndex.shift(); │ │ │ │ │ + } │ │ │ │ │ + this.tileCache[tile.url] = tile.imgDiv; │ │ │ │ │ + this.tileCacheIndex.push(tile.url); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: clearTileQueue │ │ │ │ │ + * Clears the tile queue from tiles of a specific layer │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Object} Listener argument of the layer's retile event │ │ │ │ │ + */ │ │ │ │ │ + clearTileQueue: function(evt) { │ │ │ │ │ + var layer = evt.object; │ │ │ │ │ + var tileQueue = this.tileQueue[layer.map.id]; │ │ │ │ │ + for (var i = tileQueue.length - 1; i >= 0; --i) { │ │ │ │ │ + if (tileQueue[i].layer === layer) { │ │ │ │ │ + tileQueue.splice(i, 1); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: destroy │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + for (var i = this.maps.length - 1; i >= 0; --i) { │ │ │ │ │ + this.removeMap(this.maps[i]); │ │ │ │ │ + } │ │ │ │ │ + this.maps = null; │ │ │ │ │ + this.tileQueue = null; │ │ │ │ │ + this.tileQueueId = null; │ │ │ │ │ + this.tileCache = null; │ │ │ │ │ + this.tileCacheIndex = null; │ │ │ │ │ + this._destroyed = true; │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Format/WPSDescribeProcess.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Format/XML.js │ │ │ │ │ + * @requires OpenLayers/Format/OWSCommon/v1_1_0.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Format.WPSDescribeProcess │ │ │ │ │ + * Read WPS DescribeProcess responses. │ │ │ │ │ + * │ │ │ │ │ + * Inherits from: │ │ │ │ │ + * - │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Format.WPSDescribeProcess = OpenLayers.Class( │ │ │ │ │ + OpenLayers.Format.XML, { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constant: VERSION │ │ │ │ │ + * {String} 1.0.0 │ │ │ │ │ + */ │ │ │ │ │ + VERSION: "1.0.0", │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: namespaces │ │ │ │ │ + * {Object} Mapping of namespace aliases to namespace URIs. │ │ │ │ │ + */ │ │ │ │ │ + namespaces: { │ │ │ │ │ + wps: "http://www.opengis.net/wps/1.0.0", │ │ │ │ │ + ows: "http://www.opengis.net/ows/1.1", │ │ │ │ │ + xsi: "http://www.w3.org/2001/XMLSchema-instance" │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: schemaLocation │ │ │ │ │ + * {String} Schema location │ │ │ │ │ + */ │ │ │ │ │ + schemaLocation: "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd", │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: defaultPrefix │ │ │ │ │ + */ │ │ │ │ │ + defaultPrefix: "wps", │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: regExes │ │ │ │ │ + * Compiled regular expressions for manipulating strings. │ │ │ │ │ + */ │ │ │ │ │ + regExes: { │ │ │ │ │ + trimSpace: (/^\s*|\s*$/g), │ │ │ │ │ + removeSpace: (/\s*/g), │ │ │ │ │ + splitSpace: (/\s+/), │ │ │ │ │ + trimComma: (/\s*,\s*/g) │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Format.WPSDescribeProcess │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * options - {Object} An optional object whose properties will be set on │ │ │ │ │ + * this instance. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: read │ │ │ │ │ + * Parse a WPS DescribeProcess and return an object with its information. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * data - {String} or {DOMElement} data to read/parse. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Object} │ │ │ │ │ + */ │ │ │ │ │ + read: function(data) { │ │ │ │ │ + if (typeof data == "string") { │ │ │ │ │ + data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); │ │ │ │ │ + } │ │ │ │ │ + if (data && data.nodeType == 9) { │ │ │ │ │ + data = data.documentElement; │ │ │ │ │ + } │ │ │ │ │ + var info = {}; │ │ │ │ │ + this.readNode(data, info); │ │ │ │ │ + return info; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: readers │ │ │ │ │ + * Contains public functions, grouped by namespace prefix, that will │ │ │ │ │ + * be applied when a namespaced node is found matching the function │ │ │ │ │ + * name. The function will be applied in the scope of this parser │ │ │ │ │ + * with two arguments: the node being read and a context object passed │ │ │ │ │ + * from the parent. │ │ │ │ │ + */ │ │ │ │ │ + readers: { │ │ │ │ │ + "wps": { │ │ │ │ │ + "ProcessDescriptions": function(node, obj) { │ │ │ │ │ + obj.processDescriptions = {}; │ │ │ │ │ + this.readChildNodes(node, obj.processDescriptions); │ │ │ │ │ + }, │ │ │ │ │ + "ProcessDescription": function(node, processDescriptions) { │ │ │ │ │ + var processVersion = this.getAttributeNS(node, this.namespaces.wps, "processVersion"); │ │ │ │ │ + var processDescription = { │ │ │ │ │ + processVersion: processVersion, │ │ │ │ │ + statusSupported: (node.getAttribute("statusSupported") === "true"), │ │ │ │ │ + storeSupported: (node.getAttribute("storeSupported") === "true") │ │ │ │ │ + }; │ │ │ │ │ + this.readChildNodes(node, processDescription); │ │ │ │ │ + processDescriptions[processDescription.identifier] = processDescription; │ │ │ │ │ + }, │ │ │ │ │ + "DataInputs": function(node, processDescription) { │ │ │ │ │ + processDescription.dataInputs = []; │ │ │ │ │ + this.readChildNodes(node, processDescription.dataInputs); │ │ │ │ │ + }, │ │ │ │ │ + "ProcessOutputs": function(node, processDescription) { │ │ │ │ │ + processDescription.processOutputs = []; │ │ │ │ │ + this.readChildNodes(node, processDescription.processOutputs); │ │ │ │ │ + }, │ │ │ │ │ + "Output": function(node, processOutputs) { │ │ │ │ │ + var output = {}; │ │ │ │ │ + this.readChildNodes(node, output); │ │ │ │ │ + processOutputs.push(output); │ │ │ │ │ + }, │ │ │ │ │ + "ComplexOutput": function(node, output) { │ │ │ │ │ + output.complexOutput = {}; │ │ │ │ │ + this.readChildNodes(node, output.complexOutput); │ │ │ │ │ + }, │ │ │ │ │ + "LiteralOutput": function(node, output) { │ │ │ │ │ + output.literalOutput = {}; │ │ │ │ │ + this.readChildNodes(node, output.literalOutput); │ │ │ │ │ + }, │ │ │ │ │ + "Input": function(node, dataInputs) { │ │ │ │ │ + var input = { │ │ │ │ │ + maxOccurs: parseInt(node.getAttribute("maxOccurs")), │ │ │ │ │ + minOccurs: parseInt(node.getAttribute("minOccurs")) │ │ │ │ │ + }; │ │ │ │ │ + this.readChildNodes(node, input); │ │ │ │ │ + dataInputs.push(input); │ │ │ │ │ + }, │ │ │ │ │ + "BoundingBoxData": function(node, input) { │ │ │ │ │ + input.boundingBoxData = {}; │ │ │ │ │ + this.readChildNodes(node, input.boundingBoxData); │ │ │ │ │ + }, │ │ │ │ │ + "CRS": function(node, obj) { │ │ │ │ │ + if (!obj.CRSs) { │ │ │ │ │ + obj.CRSs = {}; │ │ │ │ │ + } │ │ │ │ │ + obj.CRSs[this.getChildValue(node)] = true; │ │ │ │ │ + }, │ │ │ │ │ + "LiteralData": function(node, input) { │ │ │ │ │ + input.literalData = {}; │ │ │ │ │ + this.readChildNodes(node, input.literalData); │ │ │ │ │ + }, │ │ │ │ │ + "ComplexData": function(node, input) { │ │ │ │ │ + input.complexData = {}; │ │ │ │ │ + this.readChildNodes(node, input.complexData); │ │ │ │ │ + }, │ │ │ │ │ + "Default": function(node, complexData) { │ │ │ │ │ + complexData["default"] = {}; │ │ │ │ │ + this.readChildNodes(node, complexData["default"]); │ │ │ │ │ + }, │ │ │ │ │ + "Supported": function(node, complexData) { │ │ │ │ │ + complexData["supported"] = {}; │ │ │ │ │ + this.readChildNodes(node, complexData["supported"]); │ │ │ │ │ + }, │ │ │ │ │ + "Format": function(node, obj) { │ │ │ │ │ + var format = {}; │ │ │ │ │ + this.readChildNodes(node, format); │ │ │ │ │ + if (!obj.formats) { │ │ │ │ │ + obj.formats = {}; │ │ │ │ │ + } │ │ │ │ │ + obj.formats[format.mimeType] = true; │ │ │ │ │ + }, │ │ │ │ │ + "MimeType": function(node, format) { │ │ │ │ │ + format.mimeType = this.getChildValue(node); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"] │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Format.WPSDescribeProcess" │ │ │ │ │ + │ │ │ │ │ + }); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/WPSClient.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/SingleFile.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Events.js │ │ │ │ │ + * @requires OpenLayers/WPSProcess.js │ │ │ │ │ + * @requires OpenLayers/Format/WPSDescribeProcess.js │ │ │ │ │ + * @requires OpenLayers/Request.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.WPSClient │ │ │ │ │ + * High level API for interaction with Web Processing Services (WPS). │ │ │ │ │ + * An instance is used to create │ │ │ │ │ + * instances for servers known to the WPSClient. The WPSClient also caches │ │ │ │ │ + * DescribeProcess responses to reduce the number of requests sent to servers │ │ │ │ │ + * when processes are created. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.WPSClient = OpenLayers.Class({ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: servers │ │ │ │ │ + * {Object} Service metadata, keyed by a local identifier. │ │ │ │ │ + * │ │ │ │ │ + * Properties: │ │ │ │ │ + * url - {String} the url of the server │ │ │ │ │ + * version - {String} WPS version of the server │ │ │ │ │ + * processDescription - {Object} Cache of raw DescribeProcess │ │ │ │ │ + * responses, keyed by process identifier. │ │ │ │ │ + */ │ │ │ │ │ + servers: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: version │ │ │ │ │ + * {String} The default WPS version to use if none is configured. Default │ │ │ │ │ + * is '1.0.0'. │ │ │ │ │ + */ │ │ │ │ │ + version: '1.0.0', │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: lazy │ │ │ │ │ + * {Boolean} Should the DescribeProcess be deferred until a process is │ │ │ │ │ + * fully configured? Default is false. │ │ │ │ │ + */ │ │ │ │ │ + lazy: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: events │ │ │ │ │ + * {} │ │ │ │ │ + * │ │ │ │ │ + * Supported event types: │ │ │ │ │ + * describeprocess - Fires when the process description is available. │ │ │ │ │ + * Listeners receive an object with a 'raw' property holding the raw │ │ │ │ │ + * DescribeProcess response, and an 'identifier' property holding the │ │ │ │ │ + * process identifier of the described process. │ │ │ │ │ + */ │ │ │ │ │ + events: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.WPSClient │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * options - {Object} Object whose properties will be set on the instance. │ │ │ │ │ + * │ │ │ │ │ + * Avaliable options: │ │ │ │ │ + * servers - {Object} Mandatory. Service metadata, keyed by a local │ │ │ │ │ + * identifier. Can either be a string with the service url or an │ │ │ │ │ + * object literal with additional metadata: │ │ │ │ │ + * │ │ │ │ │ + * (code) │ │ │ │ │ + * servers: { │ │ │ │ │ + * local: '/geoserver/wps' │ │ │ │ │ + * }, { │ │ │ │ │ + * opengeo: { │ │ │ │ │ + * url: 'http://demo.opengeo.org/geoserver/wps', │ │ │ │ │ + * version: '1.0.0' │ │ │ │ │ + * } │ │ │ │ │ + * } │ │ │ │ │ + * (end) │ │ │ │ │ + * │ │ │ │ │ + * lazy - {Boolean} Optional. Set to true if DescribeProcess should not be │ │ │ │ │ + * requested until a process is fully configured. Default is false. │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(options) { │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ + this.events = new OpenLayers.Events(this); │ │ │ │ │ + this.servers = {}; │ │ │ │ │ + for (var s in options.servers) { │ │ │ │ │ + this.servers[s] = typeof options.servers[s] == 'string' ? { │ │ │ │ │ + url: options.servers[s], │ │ │ │ │ + version: this.version, │ │ │ │ │ + processDescription: {} │ │ │ │ │ + } : options.servers[s]; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: execute │ │ │ │ │ + * Shortcut to execute a process with a single function call. This is │ │ │ │ │ + * equivalent to using and then calling execute on the │ │ │ │ │ + * process. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * options - {Object} Options for the execute operation. │ │ │ │ │ + * │ │ │ │ │ + * Available options: │ │ │ │ │ + * server - {String} Mandatory. One of the local identifiers of the │ │ │ │ │ + * configured servers. │ │ │ │ │ + * process - {String} Mandatory. A process identifier known to the │ │ │ │ │ + * server. │ │ │ │ │ + * inputs - {Object} The inputs for the process, keyed by input identifier. │ │ │ │ │ + * For spatial data inputs, the value of an input is usually an │ │ │ │ │ + * , an or an array of │ │ │ │ │ + * geometries or features. │ │ │ │ │ + * output - {String} The identifier of an output to parse. Optional. If not │ │ │ │ │ + * provided, the first output will be parsed. │ │ │ │ │ + * success - {Function} Callback to call when the process is complete. │ │ │ │ │ + * This function is called with an outputs object as argument, which │ │ │ │ │ + * will have a property with the identifier of the requested output │ │ │ │ │ + * (e.g. 'result'). For processes that generate spatial output, the │ │ │ │ │ + * value will either be a single or an │ │ │ │ │ + * array of features. │ │ │ │ │ + * scope - {Object} Optional scope for the success callback. │ │ │ │ │ + */ │ │ │ │ │ + execute: function(options) { │ │ │ │ │ + var process = this.getProcess(options.server, options.process); │ │ │ │ │ + process.execute({ │ │ │ │ │ + inputs: options.inputs, │ │ │ │ │ + success: options.success, │ │ │ │ │ + scope: options.scope │ │ │ │ │ + }); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: getProcess │ │ │ │ │ + * Creates an . │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * serverID - {String} Local identifier from the servers that this instance │ │ │ │ │ + * was constructed with. │ │ │ │ │ + * processID - {String} Process identifier known to the server. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} │ │ │ │ │ + */ │ │ │ │ │ + getProcess: function(serverID, processID) { │ │ │ │ │ + var process = new OpenLayers.WPSProcess({ │ │ │ │ │ + client: this, │ │ │ │ │ + server: serverID, │ │ │ │ │ + identifier: processID │ │ │ │ │ + }); │ │ │ │ │ + if (!this.lazy) { │ │ │ │ │ + process.describe(); │ │ │ │ │ + } │ │ │ │ │ + return process; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: describeProcess │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * serverID - {String} Identifier of the server │ │ │ │ │ + * processID - {String} Identifier of the requested process │ │ │ │ │ + * callback - {Function} Callback to call when the description is available │ │ │ │ │ + * scope - {Object} Optional execution scope for the callback function │ │ │ │ │ + */ │ │ │ │ │ + describeProcess: function(serverID, processID, callback, scope) { │ │ │ │ │ + var server = this.servers[serverID]; │ │ │ │ │ + if (!server.processDescription[processID]) { │ │ │ │ │ + if (!(processID in server.processDescription)) { │ │ │ │ │ + // set to null so we know a describeFeature request is pending │ │ │ │ │ + server.processDescription[processID] = null; │ │ │ │ │ + OpenLayers.Request.GET({ │ │ │ │ │ + url: server.url, │ │ │ │ │ + params: { │ │ │ │ │ + SERVICE: 'WPS', │ │ │ │ │ + VERSION: server.version, │ │ │ │ │ + REQUEST: 'DescribeProcess', │ │ │ │ │ + IDENTIFIER: processID │ │ │ │ │ + }, │ │ │ │ │ + success: function(response) { │ │ │ │ │ + server.processDescription[processID] = response.responseText; │ │ │ │ │ + this.events.triggerEvent('describeprocess', { │ │ │ │ │ + identifier: processID, │ │ │ │ │ + raw: response.responseText │ │ │ │ │ + }); │ │ │ │ │ + }, │ │ │ │ │ + scope: this │ │ │ │ │ + }); │ │ │ │ │ + } else { │ │ │ │ │ + // pending request │ │ │ │ │ + this.events.register('describeprocess', this, function describe(evt) { │ │ │ │ │ + if (evt.identifier === processID) { │ │ │ │ │ + this.events.unregister('describeprocess', this, describe); │ │ │ │ │ + callback.call(scope, evt.raw); │ │ │ │ │ + } │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + } else { │ │ │ │ │ + window.setTimeout(function() { │ │ │ │ │ + callback.call(scope, server.processDescription[processID]); │ │ │ │ │ + }, 0); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: destroy │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + this.events.destroy(); │ │ │ │ │ + this.events = null; │ │ │ │ │ + this.servers = null; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: 'OpenLayers.WPSClient' │ │ │ │ │ + │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Control.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Control │ │ │ │ │ + * Controls affect the display or behavior of the map. They allow everything │ │ │ │ │ + * from panning and zooming to displaying a scale indicator. Controls by │ │ │ │ │ + * default are added to the map they are contained within however it is │ │ │ │ │ + * possible to add a control to an external div by passing the div in the │ │ │ │ │ + * options parameter. │ │ │ │ │ + * │ │ │ │ │ + * Example: │ │ │ │ │ + * The following example shows how to add many of the common controls │ │ │ │ │ + * to a map. │ │ │ │ │ + * │ │ │ │ │ + * > var map = new OpenLayers.Map('map', { controls: [] }); │ │ │ │ │ + * > │ │ │ │ │ + * > map.addControl(new OpenLayers.Control.PanZoomBar()); │ │ │ │ │ + * > map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':false})); │ │ │ │ │ + * > map.addControl(new OpenLayers.Control.Permalink()); │ │ │ │ │ + * > map.addControl(new OpenLayers.Control.Permalink('permalink')); │ │ │ │ │ + * > map.addControl(new OpenLayers.Control.MousePosition()); │ │ │ │ │ + * > map.addControl(new OpenLayers.Control.OverviewMap()); │ │ │ │ │ + * > map.addControl(new OpenLayers.Control.KeyboardDefaults()); │ │ │ │ │ + * │ │ │ │ │ + * The next code fragment is a quick example of how to intercept │ │ │ │ │ + * shift-mouse click to display the extent of the bounding box │ │ │ │ │ + * dragged out by the user. Usually controls are not created │ │ │ │ │ + * in exactly this manner. See the source for a more complete │ │ │ │ │ + * example: │ │ │ │ │ + * │ │ │ │ │ + * > var control = new OpenLayers.Control(); │ │ │ │ │ + * > OpenLayers.Util.extend(control, { │ │ │ │ │ + * > draw: function () { │ │ │ │ │ + * > // this Handler.Box will intercept the shift-mousedown │ │ │ │ │ + * > // before Control.MouseDefault gets to see it │ │ │ │ │ + * > this.box = new OpenLayers.Handler.Box( control, │ │ │ │ │ + * > {"done": this.notice}, │ │ │ │ │ + * > {keyMask: OpenLayers.Handler.MOD_SHIFT}); │ │ │ │ │ + * > this.box.activate(); │ │ │ │ │ + * > }, │ │ │ │ │ + * > │ │ │ │ │ + * > notice: function (bounds) { │ │ │ │ │ + * > OpenLayers.Console.userError(bounds); │ │ │ │ │ + * > } │ │ │ │ │ + * > }); │ │ │ │ │ + * > map.addControl(control); │ │ │ │ │ + * │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Control = OpenLayers.Class({ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: id │ │ │ │ │ + * {String} │ │ │ │ │ + */ │ │ │ │ │ + id: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: map │ │ │ │ │ + * {} this gets set in the addControl() function in │ │ │ │ │ + * OpenLayers.Map │ │ │ │ │ + */ │ │ │ │ │ + map: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: div │ │ │ │ │ + * {DOMElement} The element that contains the control, if not present the │ │ │ │ │ + * control is placed inside the map. │ │ │ │ │ + */ │ │ │ │ │ + div: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: type │ │ │ │ │ + * {Number} Controls can have a 'type'. The type determines the type of │ │ │ │ │ + * interactions which are possible with them when they are placed in an │ │ │ │ │ + * . │ │ │ │ │ + */ │ │ │ │ │ + type: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: allowSelection │ │ │ │ │ + * {Boolean} By default, controls do not allow selection, because │ │ │ │ │ + * it may interfere with map dragging. If this is true, OpenLayers │ │ │ │ │ + * will not prevent selection of the control. │ │ │ │ │ + * Default is false. │ │ │ │ │ + */ │ │ │ │ │ + allowSelection: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: displayClass │ │ │ │ │ + * {string} This property is used for CSS related to the drawing of the │ │ │ │ │ + * Control. │ │ │ │ │ + */ │ │ │ │ │ + displayClass: "", │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: title │ │ │ │ │ + * {string} This property is used for showing a tooltip over the │ │ │ │ │ + * Control. │ │ │ │ │ + */ │ │ │ │ │ + title: "", │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: autoActivate │ │ │ │ │ + * {Boolean} Activate the control when it is added to a map. Default is │ │ │ │ │ + * false. │ │ │ │ │ + */ │ │ │ │ │ + autoActivate: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: active │ │ │ │ │ + * {Boolean} The control is active (read-only). Use and │ │ │ │ │ + * to change control state. │ │ │ │ │ + */ │ │ │ │ │ + active: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: handlerOptions │ │ │ │ │ + * {Object} Used to set non-default properties on the control's handler │ │ │ │ │ + */ │ │ │ │ │ + handlerOptions: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: handler │ │ │ │ │ + * {} null │ │ │ │ │ + */ │ │ │ │ │ + handler: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: eventListeners │ │ │ │ │ + * {Object} If set as an option at construction, the eventListeners │ │ │ │ │ + * object will be registered with . Object │ │ │ │ │ + * structure must be a listeners object as shown in the example for │ │ │ │ │ + * the events.on method. │ │ │ │ │ + */ │ │ │ │ │ + eventListeners: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: events │ │ │ │ │ + * {} Events instance for listeners and triggering │ │ │ │ │ + * control specific events. │ │ │ │ │ + * │ │ │ │ │ + * Register a listener for a particular event with the following syntax: │ │ │ │ │ + * (code) │ │ │ │ │ + * control.events.register(type, obj, listener); │ │ │ │ │ + * (end) │ │ │ │ │ + * │ │ │ │ │ + * Listeners will be called with a reference to an event object. The │ │ │ │ │ + * properties of this event depends on exactly what happened. │ │ │ │ │ + * │ │ │ │ │ + * All event objects have at least the following properties: │ │ │ │ │ + * object - {Object} A reference to control.events.object (a reference │ │ │ │ │ + * to the control). │ │ │ │ │ + * element - {DOMElement} A reference to control.events.element (which │ │ │ │ │ + * will be null unless documented otherwise). │ │ │ │ │ + * │ │ │ │ │ + * Supported map event types: │ │ │ │ │ + * activate - Triggered when activated. │ │ │ │ │ + * deactivate - Triggered when deactivated. │ │ │ │ │ + */ │ │ │ │ │ + events: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Control │ │ │ │ │ + * Create an OpenLayers Control. The options passed as a parameter │ │ │ │ │ + * directly extend the control. For example passing the following: │ │ │ │ │ + * │ │ │ │ │ + * > var control = new OpenLayers.Control({div: myDiv}); │ │ │ │ │ + * │ │ │ │ │ + * Overrides the default div attribute value of null. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * options - {Object} │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(options) { │ │ │ │ │ + // We do this before the extend so that instances can override │ │ │ │ │ + // className in options. │ │ │ │ │ + this.displayClass = │ │ │ │ │ + this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, ""); │ │ │ │ │ + │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ + │ │ │ │ │ + this.events = new OpenLayers.Events(this); │ │ │ │ │ + if (this.eventListeners instanceof Object) { │ │ │ │ │ + this.events.on(this.eventListeners); │ │ │ │ │ + } │ │ │ │ │ + if (this.id == null) { │ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: destroy │ │ │ │ │ + * The destroy method is used to perform any clean up before the control │ │ │ │ │ + * is dereferenced. Typically this is where event listeners are removed │ │ │ │ │ + * to prevent memory leaks. │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + if (this.events) { │ │ │ │ │ + if (this.eventListeners) { │ │ │ │ │ + this.events.un(this.eventListeners); │ │ │ │ │ + } │ │ │ │ │ + this.events.destroy(); │ │ │ │ │ + this.events = null; │ │ │ │ │ + } │ │ │ │ │ + this.eventListeners = null; │ │ │ │ │ + │ │ │ │ │ + // eliminate circular references │ │ │ │ │ + if (this.handler) { │ │ │ │ │ + this.handler.destroy(); │ │ │ │ │ + this.handler = null; │ │ │ │ │ + } │ │ │ │ │ + if (this.handlers) { │ │ │ │ │ + for (var key in this.handlers) { │ │ │ │ │ + if (this.handlers.hasOwnProperty(key) && │ │ │ │ │ + typeof this.handlers[key].destroy == "function") { │ │ │ │ │ + this.handlers[key].destroy(); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + this.handlers = null; │ │ │ │ │ + } │ │ │ │ │ + if (this.map) { │ │ │ │ │ + this.map.removeControl(this); │ │ │ │ │ + this.map = null; │ │ │ │ │ + } │ │ │ │ │ + this.div = null; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: setMap │ │ │ │ │ + * Set the map property for the control. This is done through an accessor │ │ │ │ │ + * so that subclasses can override this and take special action once │ │ │ │ │ + * they have their map variable set. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * map - {} │ │ │ │ │ + */ │ │ │ │ │ + setMap: function(map) { │ │ │ │ │ + this.map = map; │ │ │ │ │ + if (this.handler) { │ │ │ │ │ + this.handler.setMap(map); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: draw │ │ │ │ │ + * The draw method is called when the control is ready to be displayed │ │ │ │ │ + * on the page. If a div has not been created one is created. Controls │ │ │ │ │ + * with a visual component will almost always want to override this method │ │ │ │ │ + * to customize the look of control. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * px - {} The top-left pixel position of the control │ │ │ │ │ + * or null. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {DOMElement} A reference to the DIV DOMElement containing the control │ │ │ │ │ + */ │ │ │ │ │ + draw: function(px) { │ │ │ │ │ + if (this.div == null) { │ │ │ │ │ + this.div = OpenLayers.Util.createDiv(this.id); │ │ │ │ │ + this.div.className = this.displayClass; │ │ │ │ │ + if (!this.allowSelection) { │ │ │ │ │ + this.div.className += " olControlNoSelect"; │ │ │ │ │ + this.div.setAttribute("unselectable", "on", 0); │ │ │ │ │ + this.div.onselectstart = OpenLayers.Function.False; │ │ │ │ │ + } │ │ │ │ │ + if (this.title != "") { │ │ │ │ │ + this.div.title = this.title; │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + if (px != null) { │ │ │ │ │ + this.position = px.clone(); │ │ │ │ │ + } │ │ │ │ │ + this.moveTo(this.position); │ │ │ │ │ + return this.div; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: moveTo │ │ │ │ │ + * Sets the left and top style attributes to the passed in pixel │ │ │ │ │ + * coordinates. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * px - {} │ │ │ │ │ + */ │ │ │ │ │ + moveTo: function(px) { │ │ │ │ │ + if ((px != null) && (this.div != null)) { │ │ │ │ │ + this.div.style.left = px.x + "px"; │ │ │ │ │ + this.div.style.top = px.y + "px"; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: activate │ │ │ │ │ + * Explicitly activates a control and it's associated │ │ │ │ │ + * handler if one has been set. Controls can be │ │ │ │ │ + * deactivated by calling the deactivate() method. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} True if the control was successfully activated or │ │ │ │ │ + * false if the control was already active. │ │ │ │ │ + */ │ │ │ │ │ + activate: function() { │ │ │ │ │ + if (this.active) { │ │ │ │ │ + return false; │ │ │ │ │ + } │ │ │ │ │ + if (this.handler) { │ │ │ │ │ + this.handler.activate(); │ │ │ │ │ + } │ │ │ │ │ + this.active = true; │ │ │ │ │ + if (this.map) { │ │ │ │ │ + OpenLayers.Element.addClass( │ │ │ │ │ + this.map.viewPortDiv, │ │ │ │ │ + this.displayClass.replace(/ /g, "") + "Active" │ │ │ │ │ + ); │ │ │ │ │ + } │ │ │ │ │ + this.events.triggerEvent("activate"); │ │ │ │ │ + return true; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: deactivate │ │ │ │ │ + * Deactivates a control and it's associated handler if any. The exact │ │ │ │ │ + * effect of this depends on the control itself. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} True if the control was effectively deactivated or false │ │ │ │ │ + * if the control was already inactive. │ │ │ │ │ + */ │ │ │ │ │ + deactivate: function() { │ │ │ │ │ + if (this.active) { │ │ │ │ │ + if (this.handler) { │ │ │ │ │ + this.handler.deactivate(); │ │ │ │ │ + } │ │ │ │ │ + this.active = false; │ │ │ │ │ + if (this.map) { │ │ │ │ │ + OpenLayers.Element.removeClass( │ │ │ │ │ + this.map.viewPortDiv, │ │ │ │ │ + this.displayClass.replace(/ /g, "") + "Active" │ │ │ │ │ + ); │ │ │ │ │ + } │ │ │ │ │ + this.events.triggerEvent("deactivate"); │ │ │ │ │ + return true; │ │ │ │ │ + } │ │ │ │ │ + return false; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Control" │ │ │ │ │ +}); │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Constant: OpenLayers.Control.TYPE_BUTTON │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Control.TYPE_BUTTON = 1; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Constant: OpenLayers.Control.TYPE_TOGGLE │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Control.TYPE_TOGGLE = 2; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Constant: OpenLayers.Control.TYPE_TOOL │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Control.TYPE_TOOL = 3; │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Handler.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + * @requires OpenLayers/Events.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Handler │ │ │ │ │ + * Base class to construct a higher-level handler for event sequences. All │ │ │ │ │ + * handlers have activate and deactivate methods. In addition, they have │ │ │ │ │ + * methods named like browser events. When a handler is activated, any │ │ │ │ │ + * additional methods named like a browser event is registered as a │ │ │ │ │ + * listener for the corresponding event. When a handler is deactivated, │ │ │ │ │ + * those same methods are unregistered as event listeners. │ │ │ │ │ + * │ │ │ │ │ + * Handlers also typically have a callbacks object with keys named like │ │ │ │ │ + * the abstracted events or event sequences that they are in charge of │ │ │ │ │ + * handling. The controls that wrap handlers define the methods that │ │ │ │ │ + * correspond to these abstract events - so instead of listening for │ │ │ │ │ + * individual browser events, they only listen for the abstract events │ │ │ │ │ + * defined by the handler. │ │ │ │ │ + * │ │ │ │ │ + * Handlers are created by controls, which ultimately have the responsibility │ │ │ │ │ + * of making changes to the the state of the application. Handlers │ │ │ │ │ + * themselves may make temporary changes, but in general are expected to │ │ │ │ │ + * return the application in the same state that they found it. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Handler = OpenLayers.Class({ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: id │ │ │ │ │ + * {String} │ │ │ │ │ + */ │ │ │ │ │ + id: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: control │ │ │ │ │ + * {}. The control that initialized this handler. The │ │ │ │ │ + * control is assumed to have a valid map property - that map is used │ │ │ │ │ + * in the handler's own setMap method. │ │ │ │ │ + */ │ │ │ │ │ + control: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: map │ │ │ │ │ + * {} │ │ │ │ │ + */ │ │ │ │ │ + map: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: keyMask │ │ │ │ │ + * {Integer} Use bitwise operators and one or more of the OpenLayers.Handler │ │ │ │ │ + * constants to construct a keyMask. The keyMask is used by │ │ │ │ │ + * . If the keyMask matches the combination of keys │ │ │ │ │ + * down on an event, checkModifiers returns true. │ │ │ │ │ + * │ │ │ │ │ + * Example: │ │ │ │ │ + * (code) │ │ │ │ │ + * // handler only responds if the Shift key is down │ │ │ │ │ + * handler.keyMask = OpenLayers.Handler.MOD_SHIFT; │ │ │ │ │ + * │ │ │ │ │ + * // handler only responds if Ctrl-Shift is down │ │ │ │ │ + * handler.keyMask = OpenLayers.Handler.MOD_SHIFT | │ │ │ │ │ + * OpenLayers.Handler.MOD_CTRL; │ │ │ │ │ + * (end) │ │ │ │ │ + */ │ │ │ │ │ + keyMask: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: active │ │ │ │ │ + * {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + active: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: evt │ │ │ │ │ + * {Event} This property references the last event handled by the handler. │ │ │ │ │ + * Note that this property is not part of the stable API. Use of the │ │ │ │ │ + * evt property should be restricted to controls in the library │ │ │ │ │ + * or other applications that are willing to update with changes to │ │ │ │ │ + * the OpenLayers code. │ │ │ │ │ + */ │ │ │ │ │ + evt: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: touch │ │ │ │ │ + * {Boolean} Indicates the support of touch events. When touch events are │ │ │ │ │ + * started touch will be true and all mouse related listeners will do │ │ │ │ │ + * nothing. │ │ │ │ │ + */ │ │ │ │ │ + touch: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Handler │ │ │ │ │ + * Construct a handler. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * control - {} The control that initialized this │ │ │ │ │ + * handler. The control is assumed to have a valid map property; that │ │ │ │ │ + * map is used in the handler's own setMap method. If a map property │ │ │ │ │ + * is present in the options argument it will be used instead. │ │ │ │ │ + * callbacks - {Object} An object whose properties correspond to abstracted │ │ │ │ │ + * events or sequences of browser events. The values for these │ │ │ │ │ + * properties are functions defined by the control that get called by │ │ │ │ │ + * the handler. │ │ │ │ │ + * options - {Object} An optional object whose properties will be set on │ │ │ │ │ + * the handler. │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(control, callbacks, options) { │ │ │ │ │ + OpenLayers.Util.extend(this, options); │ │ │ │ │ + this.control = control; │ │ │ │ │ + this.callbacks = callbacks; │ │ │ │ │ + │ │ │ │ │ + var map = this.map || control.map; │ │ │ │ │ + if (map) { │ │ │ │ │ + this.setMap(map); │ │ │ │ │ + } │ │ │ │ │ + │ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: setMap │ │ │ │ │ + */ │ │ │ │ │ + setMap: function(map) { │ │ │ │ │ + this.map = map; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: checkModifiers │ │ │ │ │ + * Check the keyMask on the handler. If no is set, this always │ │ │ │ │ + * returns true. If a is set and it matches the combination │ │ │ │ │ + * of keys down on an event, this returns true. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The keyMask matches the keys down on an event. │ │ │ │ │ + */ │ │ │ │ │ + checkModifiers: function(evt) { │ │ │ │ │ + if (this.keyMask == null) { │ │ │ │ │ + return true; │ │ │ │ │ + } │ │ │ │ │ + /* calculate the keyboard modifier mask for this event */ │ │ │ │ │ + var keyModifiers = │ │ │ │ │ + (evt.shiftKey ? OpenLayers.Handler.MOD_SHIFT : 0) | │ │ │ │ │ + (evt.ctrlKey ? OpenLayers.Handler.MOD_CTRL : 0) | │ │ │ │ │ + (evt.altKey ? OpenLayers.Handler.MOD_ALT : 0) | │ │ │ │ │ + (evt.metaKey ? OpenLayers.Handler.MOD_META : 0); │ │ │ │ │ + │ │ │ │ │ + /* if it differs from the handler object's key mask, │ │ │ │ │ + bail out of the event handler */ │ │ │ │ │ + return (keyModifiers == this.keyMask); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: activate │ │ │ │ │ + * Turn on the handler. Returns false if the handler was already active. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The handler was activated. │ │ │ │ │ + */ │ │ │ │ │ + activate: function() { │ │ │ │ │ + if (this.active) { │ │ │ │ │ + return false; │ │ │ │ │ + } │ │ │ │ │ + // register for event handlers defined on this class. │ │ │ │ │ + var events = OpenLayers.Events.prototype.BROWSER_EVENTS; │ │ │ │ │ + for (var i = 0, len = events.length; i < len; i++) { │ │ │ │ │ + if (this[events[i]]) { │ │ │ │ │ + this.register(events[i], this[events[i]]); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + this.active = true; │ │ │ │ │ + return true; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIMethod: deactivate │ │ │ │ │ + * Turn off the handler. Returns false if the handler was already inactive. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The handler was deactivated. │ │ │ │ │ + */ │ │ │ │ │ + deactivate: function() { │ │ │ │ │ + if (!this.active) { │ │ │ │ │ + return false; │ │ │ │ │ + } │ │ │ │ │ + // unregister event handlers defined on this class. │ │ │ │ │ + var events = OpenLayers.Events.prototype.BROWSER_EVENTS; │ │ │ │ │ + for (var i = 0, len = events.length; i < len; i++) { │ │ │ │ │ + if (this[events[i]]) { │ │ │ │ │ + this.unregister(events[i], this[events[i]]); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + this.touch = false; │ │ │ │ │ + this.active = false; │ │ │ │ │ + return true; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: startTouch │ │ │ │ │ + * Start touch events, this method must be called by subclasses in │ │ │ │ │ + * "touchstart" method. When touch events are started will be │ │ │ │ │ + * true and all mouse related listeners will do nothing. │ │ │ │ │ + */ │ │ │ │ │ + startTouch: function() { │ │ │ │ │ + if (!this.touch) { │ │ │ │ │ + this.touch = true; │ │ │ │ │ + var events = [ │ │ │ │ │ + "mousedown", "mouseup", "mousemove", "click", "dblclick", │ │ │ │ │ + "mouseout" │ │ │ │ │ + ]; │ │ │ │ │ + for (var i = 0, len = events.length; i < len; i++) { │ │ │ │ │ + if (this[events[i]]) { │ │ │ │ │ + this.unregister(events[i], this[events[i]]); │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: callback │ │ │ │ │ + * Trigger the control's named callback with the given arguments │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * name - {String} The key for the callback that is one of the properties │ │ │ │ │ + * of the handler's callbacks object. │ │ │ │ │ + * args - {Array(*)} An array of arguments (any type) with which to call │ │ │ │ │ + * the callback (defined by the control). │ │ │ │ │ + */ │ │ │ │ │ + callback: function(name, args) { │ │ │ │ │ + if (name && this.callbacks[name]) { │ │ │ │ │ + this.callbacks[name].apply(this.control, args); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: register │ │ │ │ │ + * register an event on the map │ │ │ │ │ + */ │ │ │ │ │ + register: function(name, method) { │ │ │ │ │ + // TODO: deal with registerPriority in 3.0 │ │ │ │ │ + this.map.events.registerPriority(name, this, method); │ │ │ │ │ + this.map.events.registerPriority(name, this, this.setEvent); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: onMapResize │ │ │ │ │ - * For singleTile layers, this will set a new tile size according to the │ │ │ │ │ - * dimensions of the map pane. │ │ │ │ │ + * Method: unregister │ │ │ │ │ + * unregister an event from the map │ │ │ │ │ */ │ │ │ │ │ - onMapResize: function() { │ │ │ │ │ - if (this.singleTile) { │ │ │ │ │ - this.clearGrid(); │ │ │ │ │ - this.setTileSize(); │ │ │ │ │ - } │ │ │ │ │ + unregister: function(name, method) { │ │ │ │ │ + this.map.events.unregister(name, this, method); │ │ │ │ │ + this.map.events.unregister(name, this, this.setEvent); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: getTileBounds │ │ │ │ │ - * Returns The tile bounds for a layer given a pixel location. │ │ │ │ │ + * Method: setEvent │ │ │ │ │ + * With each registered browser event, the handler sets its own evt │ │ │ │ │ + * property. This property can be accessed by controls if needed │ │ │ │ │ + * to get more information about the event that the handler is │ │ │ │ │ + * processing. │ │ │ │ │ * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * viewPortPx - {} The location in the viewport. │ │ │ │ │ + * This allows modifier keys on the event to be checked (alt, shift, ctrl, │ │ │ │ │ + * and meta cannot be checked with the keyboard handler). For a │ │ │ │ │ + * control to determine which modifier keys are associated with the │ │ │ │ │ + * event that a handler is currently processing, it should access │ │ │ │ │ + * (code)handler.evt.altKey || handler.evt.shiftKey || │ │ │ │ │ + * handler.evt.ctrlKey || handler.evt.metaKey(end). │ │ │ │ │ * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} Bounds of the tile at the given pixel location. │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} The browser event. │ │ │ │ │ */ │ │ │ │ │ - getTileBounds: function(viewPortPx) { │ │ │ │ │ - var maxExtent = this.maxExtent; │ │ │ │ │ - var resolution = this.getResolution(); │ │ │ │ │ - var tileMapWidth = resolution * this.tileSize.w; │ │ │ │ │ - var tileMapHeight = resolution * this.tileSize.h; │ │ │ │ │ - var mapPoint = this.getLonLatFromViewPortPx(viewPortPx); │ │ │ │ │ - var tileLeft = maxExtent.left + (tileMapWidth * │ │ │ │ │ - Math.floor((mapPoint.lon - │ │ │ │ │ - maxExtent.left) / │ │ │ │ │ - tileMapWidth)); │ │ │ │ │ - var tileBottom = maxExtent.bottom + (tileMapHeight * │ │ │ │ │ - Math.floor((mapPoint.lat - │ │ │ │ │ - maxExtent.bottom) / │ │ │ │ │ - tileMapHeight)); │ │ │ │ │ - return new OpenLayers.Bounds(tileLeft, tileBottom, │ │ │ │ │ - tileLeft + tileMapWidth, │ │ │ │ │ - tileBottom + tileMapHeight); │ │ │ │ │ + setEvent: function(evt) { │ │ │ │ │ + this.evt = evt; │ │ │ │ │ + return true; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Layer.Grid" │ │ │ │ │ + /** │ │ │ │ │ + * Method: destroy │ │ │ │ │ + * Deconstruct the handler. │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + // unregister event listeners │ │ │ │ │ + this.deactivate(); │ │ │ │ │ + // eliminate circular references │ │ │ │ │ + this.control = this.map = null; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Handler" │ │ │ │ │ }); │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Constant: OpenLayers.Handler.MOD_NONE │ │ │ │ │ + * If set as the , returns false if any key is down. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Handler.MOD_NONE = 0; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Constant: OpenLayers.Handler.MOD_SHIFT │ │ │ │ │ + * If set as the , returns false if Shift is down. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Handler.MOD_SHIFT = 1; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Constant: OpenLayers.Handler.MOD_CTRL │ │ │ │ │ + * If set as the , returns false if Ctrl is down. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Handler.MOD_CTRL = 2; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Constant: OpenLayers.Handler.MOD_ALT │ │ │ │ │ + * If set as the , returns false if Alt is down. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Handler.MOD_ALT = 4; │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Constant: OpenLayers.Handler.MOD_META │ │ │ │ │ + * If set as the , returns false if Cmd is down. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Handler.MOD_META = 8; │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/TileManager.js │ │ │ │ │ + OpenLayers/Spherical.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/SingleFile.js │ │ │ │ │ + */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/Util.js │ │ │ │ │ - * @requires OpenLayers/BaseTypes.js │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Element.js │ │ │ │ │ - * @requires OpenLayers/Layer/Grid.js │ │ │ │ │ - * @requires OpenLayers/Tile/Image.js │ │ │ │ │ + * Namespace: Spherical │ │ │ │ │ + * The OpenLayers.Spherical namespace includes utility functions for │ │ │ │ │ + * calculations on the basis of a spherical earth (ignoring ellipsoidal │ │ │ │ │ + * effects), which is accurate enough for most purposes. │ │ │ │ │ + * │ │ │ │ │ + * Relevant links: │ │ │ │ │ + * * http://www.movable-type.co.uk/scripts/latlong.html │ │ │ │ │ + * * http://code.google.com/apis/maps/documentation/javascript/reference.html#spherical │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ +OpenLayers.Spherical = OpenLayers.Spherical || {}; │ │ │ │ │ + │ │ │ │ │ +OpenLayers.Spherical.DEFAULT_RADIUS = 6378137; │ │ │ │ │ + │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.TileManager │ │ │ │ │ - * Provides queueing of image requests and caching of image elements. │ │ │ │ │ + * APIFunction: computeDistanceBetween │ │ │ │ │ + * Computes the distance between two LonLats. │ │ │ │ │ * │ │ │ │ │ - * Queueing avoids unnecessary image requests while changing zoom levels │ │ │ │ │ - * quickly, and helps improve dragging performance on mobile devices that show │ │ │ │ │ - * a lag in dragging when loading of new images starts. and │ │ │ │ │ - * are the configuration options to control this behavior. │ │ │ │ │ + * Parameters: │ │ │ │ │ + * from - {} or {Object} Starting point. A LonLat or │ │ │ │ │ + * a JavaScript literal with lon lat properties. │ │ │ │ │ + * to - {} or {Object} Ending point. A LonLat or a │ │ │ │ │ + * JavaScript literal with lon lat properties. │ │ │ │ │ + * radius - {Float} The radius. Optional. Defaults to 6378137 meters. │ │ │ │ │ * │ │ │ │ │ - * Caching avoids setting the src on image elements for images that have already │ │ │ │ │ - * been used. Several maps can share a TileManager instance, in which case each │ │ │ │ │ - * map gets its own tile queue, but all maps share the same tile cache. │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Float} The distance in meters. │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.TileManager = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: cacheSize │ │ │ │ │ - * {Number} Number of image elements to keep referenced in this instance's │ │ │ │ │ - * cache for fast reuse. Default is 256. │ │ │ │ │ - */ │ │ │ │ │ - cacheSize: 256, │ │ │ │ │ +OpenLayers.Spherical.computeDistanceBetween = function(from, to, radius) { │ │ │ │ │ + var R = radius || OpenLayers.Spherical.DEFAULT_RADIUS; │ │ │ │ │ + var sinHalfDeltaLon = Math.sin(Math.PI * (to.lon - from.lon) / 360); │ │ │ │ │ + var sinHalfDeltaLat = Math.sin(Math.PI * (to.lat - from.lat) / 360); │ │ │ │ │ + var a = sinHalfDeltaLat * sinHalfDeltaLat + │ │ │ │ │ + sinHalfDeltaLon * sinHalfDeltaLon * Math.cos(Math.PI * from.lat / 180) * Math.cos(Math.PI * to.lat / 180); │ │ │ │ │ + return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); │ │ │ │ │ +}; │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: tilesPerFrame │ │ │ │ │ - * {Number} Number of queued tiles to load per frame (see ). │ │ │ │ │ - * Default is 2. │ │ │ │ │ - */ │ │ │ │ │ - tilesPerFrame: 2, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: frameDelay │ │ │ │ │ - * {Number} Delay between tile loading frames (see ) in │ │ │ │ │ - * milliseconds. Default is 16. │ │ │ │ │ - */ │ │ │ │ │ - frameDelay: 16, │ │ │ │ │ +/** │ │ │ │ │ + * APIFunction: computeHeading │ │ │ │ │ + * Computes the heading from one LonLat to another LonLat. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * from - {} or {Object} Starting point. A LonLat or │ │ │ │ │ + * a JavaScript literal with lon lat properties. │ │ │ │ │ + * to - {} or {Object} Ending point. A LonLat or a │ │ │ │ │ + * JavaScript literal with lon lat properties. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Float} The heading in degrees. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Spherical.computeHeading = function(from, to) { │ │ │ │ │ + var y = Math.sin(Math.PI * (from.lon - to.lon) / 180) * Math.cos(Math.PI * to.lat / 180); │ │ │ │ │ + var x = Math.cos(Math.PI * from.lat / 180) * Math.sin(Math.PI * to.lat / 180) - │ │ │ │ │ + Math.sin(Math.PI * from.lat / 180) * Math.cos(Math.PI * to.lat / 180) * Math.cos(Math.PI * (from.lon - to.lon) / 180); │ │ │ │ │ + return 180 * Math.atan2(y, x) / Math.PI; │ │ │ │ │ +}; │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Marker.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: moveDelay │ │ │ │ │ - * {Number} Delay in milliseconds after a map's move event before loading │ │ │ │ │ - * tiles. Default is 100. │ │ │ │ │ - */ │ │ │ │ │ - moveDelay: 100, │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: zoomDelay │ │ │ │ │ - * {Number} Delay in milliseconds after a map's zoomend event before loading │ │ │ │ │ - * tiles. Default is 200. │ │ │ │ │ - */ │ │ │ │ │ - zoomDelay: 200, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: maps │ │ │ │ │ - * {Array()} The maps to manage tiles on. │ │ │ │ │ - */ │ │ │ │ │ - maps: null, │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + * @requires OpenLayers/Events.js │ │ │ │ │ + * @requires OpenLayers/Icon.js │ │ │ │ │ + */ │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: tileQueueId │ │ │ │ │ - * {Object} The ids of the loop, keyed by map id. │ │ │ │ │ - */ │ │ │ │ │ - tileQueueId: null, │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Marker │ │ │ │ │ + * Instances of OpenLayers.Marker are a combination of a │ │ │ │ │ + * and an . │ │ │ │ │ + * │ │ │ │ │ + * Markers are generally added to a special layer called │ │ │ │ │ + * . │ │ │ │ │ + * │ │ │ │ │ + * Example: │ │ │ │ │ + * (code) │ │ │ │ │ + * var markers = new OpenLayers.Layer.Markers( "Markers" ); │ │ │ │ │ + * map.addLayer(markers); │ │ │ │ │ + * │ │ │ │ │ + * var size = new OpenLayers.Size(21,25); │ │ │ │ │ + * var offset = new OpenLayers.Pixel(-(size.w/2), -size.h); │ │ │ │ │ + * var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset); │ │ │ │ │ + * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon)); │ │ │ │ │ + * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon.clone())); │ │ │ │ │ + * │ │ │ │ │ + * (end) │ │ │ │ │ + * │ │ │ │ │ + * Note that if you pass an icon into the Marker constructor, it will take │ │ │ │ │ + * that icon and use it. This means that you should not share icons between │ │ │ │ │ + * markers -- you use them once, but you should clone() for any additional │ │ │ │ │ + * markers using that same icon. │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Marker = OpenLayers.Class({ │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: tileQueue │ │ │ │ │ - * {Object(Array())} Tiles queued for drawing, keyed by │ │ │ │ │ - * map id. │ │ │ │ │ + /** │ │ │ │ │ + * Property: icon │ │ │ │ │ + * {} The icon used by this marker. │ │ │ │ │ */ │ │ │ │ │ - tileQueue: null, │ │ │ │ │ + icon: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: tileCache │ │ │ │ │ - * {Object} Cached image elements, keyed by URL. │ │ │ │ │ + /** │ │ │ │ │ + * Property: lonlat │ │ │ │ │ + * {} location of object │ │ │ │ │ */ │ │ │ │ │ - tileCache: null, │ │ │ │ │ + lonlat: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: tileCacheIndex │ │ │ │ │ - * {Array(String)} URLs of cached tiles. First entry is the least recently │ │ │ │ │ - * used. │ │ │ │ │ + /** │ │ │ │ │ + * Property: events │ │ │ │ │ + * {} the event handler. │ │ │ │ │ */ │ │ │ │ │ - tileCacheIndex: null, │ │ │ │ │ + events: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.TileManager │ │ │ │ │ - * Constructor for a new instance. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} Configuration for this instance. │ │ │ │ │ + * Property: map │ │ │ │ │ + * {} the map this marker is attached to │ │ │ │ │ */ │ │ │ │ │ - initialize: function(options) { │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - this.maps = []; │ │ │ │ │ - this.tileQueueId = {}; │ │ │ │ │ - this.tileQueue = {}; │ │ │ │ │ - this.tileCache = {}; │ │ │ │ │ - this.tileCacheIndex = []; │ │ │ │ │ - }, │ │ │ │ │ + map: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: addMap │ │ │ │ │ - * Binds this instance to a map │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Marker │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * map - {} │ │ │ │ │ + * lonlat - {} the position of this marker │ │ │ │ │ + * icon - {} the icon for this marker │ │ │ │ │ */ │ │ │ │ │ - addMap: function(map) { │ │ │ │ │ - if (this._destroyed || !OpenLayers.Layer.Grid) { │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - this.maps.push(map); │ │ │ │ │ - this.tileQueue[map.id] = []; │ │ │ │ │ - for (var i = 0, ii = map.layers.length; i < ii; ++i) { │ │ │ │ │ - this.addLayer({ │ │ │ │ │ - layer: map.layers[i] │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - map.events.on({ │ │ │ │ │ - move: this.move, │ │ │ │ │ - zoomend: this.zoomEnd, │ │ │ │ │ - changelayer: this.changeLayer, │ │ │ │ │ - addlayer: this.addLayer, │ │ │ │ │ - preremovelayer: this.removeLayer, │ │ │ │ │ - scope: this │ │ │ │ │ - }); │ │ │ │ │ - }, │ │ │ │ │ + initialize: function(lonlat, icon) { │ │ │ │ │ + this.lonlat = lonlat; │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: removeMap │ │ │ │ │ - * Unbinds this instance from a map │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * map - {} │ │ │ │ │ - */ │ │ │ │ │ - removeMap: function(map) { │ │ │ │ │ - if (this._destroyed || !OpenLayers.Layer.Grid) { │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - window.clearTimeout(this.tileQueueId[map.id]); │ │ │ │ │ - if (map.layers) { │ │ │ │ │ - for (var i = 0, ii = map.layers.length; i < ii; ++i) { │ │ │ │ │ - this.removeLayer({ │ │ │ │ │ - layer: map.layers[i] │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - if (map.events) { │ │ │ │ │ - map.events.un({ │ │ │ │ │ - move: this.move, │ │ │ │ │ - zoomend: this.zoomEnd, │ │ │ │ │ - changelayer: this.changeLayer, │ │ │ │ │ - addlayer: this.addLayer, │ │ │ │ │ - preremovelayer: this.removeLayer, │ │ │ │ │ - scope: this │ │ │ │ │ - }); │ │ │ │ │ + var newIcon = (icon) ? icon : OpenLayers.Marker.defaultIcon(); │ │ │ │ │ + if (this.icon == null) { │ │ │ │ │ + this.icon = newIcon; │ │ │ │ │ + } else { │ │ │ │ │ + this.icon.url = newIcon.url; │ │ │ │ │ + this.icon.size = newIcon.size; │ │ │ │ │ + this.icon.offset = newIcon.offset; │ │ │ │ │ + this.icon.calculateOffset = newIcon.calculateOffset; │ │ │ │ │ } │ │ │ │ │ - delete this.tileQueue[map.id]; │ │ │ │ │ - delete this.tileQueueId[map.id]; │ │ │ │ │ - OpenLayers.Util.removeItem(this.maps, map); │ │ │ │ │ + this.events = new OpenLayers.Events(this, this.icon.imageDiv); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: move │ │ │ │ │ - * Handles the map's move event │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {Object} Listener argument │ │ │ │ │ + * APIMethod: destroy │ │ │ │ │ + * Destroy the marker. You must first remove the marker from any │ │ │ │ │ + * layer which it has been added to, or you will get buggy behavior. │ │ │ │ │ + * (This can not be done within the marker since the marker does not │ │ │ │ │ + * know which layer it is attached to.) │ │ │ │ │ */ │ │ │ │ │ - move: function(evt) { │ │ │ │ │ - this.updateTimeout(evt.object, this.moveDelay, true); │ │ │ │ │ - }, │ │ │ │ │ + destroy: function() { │ │ │ │ │ + // erase any drawn features │ │ │ │ │ + this.erase(); │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: zoomEnd │ │ │ │ │ - * Handles the map's zoomEnd event │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {Object} Listener argument │ │ │ │ │ - */ │ │ │ │ │ - zoomEnd: function(evt) { │ │ │ │ │ - this.updateTimeout(evt.object, this.zoomDelay); │ │ │ │ │ - }, │ │ │ │ │ + this.map = null; │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: changeLayer │ │ │ │ │ - * Handles the map's changeLayer event │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {Object} Listener argument │ │ │ │ │ - */ │ │ │ │ │ - changeLayer: function(evt) { │ │ │ │ │ - if (evt.property === 'visibility' || evt.property === 'params') { │ │ │ │ │ - this.updateTimeout(evt.object, 0); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ + this.events.destroy(); │ │ │ │ │ + this.events = null; │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: addLayer │ │ │ │ │ - * Handles the map's addlayer event │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {Object} The listener argument │ │ │ │ │ - */ │ │ │ │ │ - addLayer: function(evt) { │ │ │ │ │ - var layer = evt.layer; │ │ │ │ │ - if (layer instanceof OpenLayers.Layer.Grid) { │ │ │ │ │ - layer.events.on({ │ │ │ │ │ - addtile: this.addTile, │ │ │ │ │ - retile: this.clearTileQueue, │ │ │ │ │ - scope: this │ │ │ │ │ - }); │ │ │ │ │ - var i, j, tile; │ │ │ │ │ - for (i = layer.grid.length - 1; i >= 0; --i) { │ │ │ │ │ - for (j = layer.grid[i].length - 1; j >= 0; --j) { │ │ │ │ │ - tile = layer.grid[i][j]; │ │ │ │ │ - this.addTile({ │ │ │ │ │ - tile: tile │ │ │ │ │ - }); │ │ │ │ │ - if (tile.url && !tile.imgDiv) { │ │ │ │ │ - this.manageTileCache({ │ │ │ │ │ - object: tile │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ + if (this.icon != null) { │ │ │ │ │ + this.icon.destroy(); │ │ │ │ │ + this.icon = null; │ │ │ │ │ } │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: removeLayer │ │ │ │ │ - * Handles the map's preremovelayer event │ │ │ │ │ - * │ │ │ │ │ + /** │ │ │ │ │ + * Method: draw │ │ │ │ │ + * Calls draw on the icon, and returns that output. │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * evt - {Object} The listener argument │ │ │ │ │ + * px - {} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {DOMElement} A new DOM Image with this marker's icon set at the │ │ │ │ │ + * location passed-in │ │ │ │ │ */ │ │ │ │ │ - removeLayer: function(evt) { │ │ │ │ │ - var layer = evt.layer; │ │ │ │ │ - if (layer instanceof OpenLayers.Layer.Grid) { │ │ │ │ │ - this.clearTileQueue({ │ │ │ │ │ - object: layer │ │ │ │ │ - }); │ │ │ │ │ - if (layer.events) { │ │ │ │ │ - layer.events.un({ │ │ │ │ │ - addtile: this.addTile, │ │ │ │ │ - retile: this.clearTileQueue, │ │ │ │ │ - scope: this │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - if (layer.grid) { │ │ │ │ │ - var i, j, tile; │ │ │ │ │ - for (i = layer.grid.length - 1; i >= 0; --i) { │ │ │ │ │ - for (j = layer.grid[i].length - 1; j >= 0; --j) { │ │ │ │ │ - tile = layer.grid[i][j]; │ │ │ │ │ - this.unloadTile({ │ │ │ │ │ - object: tile │ │ │ │ │ - }); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ + draw: function(px) { │ │ │ │ │ + return this.icon.draw(px); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: updateTimeout │ │ │ │ │ - * Applies the or to the loop, │ │ │ │ │ - * and schedules more queue processing after if there are still │ │ │ │ │ - * tiles in the queue. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * map - {} The map to update the timeout for │ │ │ │ │ - * delay - {Number} The delay to apply │ │ │ │ │ - * nice - {Boolean} If true, the timeout function will only be created if │ │ │ │ │ - * the tilequeue is not empty. This is used by the move handler to │ │ │ │ │ - * avoid impacts on dragging performance. For other events, the tile │ │ │ │ │ - * queue may not be populated yet, so we need to set the timer │ │ │ │ │ - * regardless of the queue size. │ │ │ │ │ + /** │ │ │ │ │ + * Method: erase │ │ │ │ │ + * Erases any drawn elements for this marker. │ │ │ │ │ */ │ │ │ │ │ - updateTimeout: function(map, delay, nice) { │ │ │ │ │ - window.clearTimeout(this.tileQueueId[map.id]); │ │ │ │ │ - var tileQueue = this.tileQueue[map.id]; │ │ │ │ │ - if (!nice || tileQueue.length) { │ │ │ │ │ - this.tileQueueId[map.id] = window.setTimeout( │ │ │ │ │ - OpenLayers.Function.bind(function() { │ │ │ │ │ - this.drawTilesFromQueue(map); │ │ │ │ │ - if (tileQueue.length) { │ │ │ │ │ - this.updateTimeout(map, this.frameDelay); │ │ │ │ │ - } │ │ │ │ │ - }, this), delay │ │ │ │ │ - ); │ │ │ │ │ + erase: function() { │ │ │ │ │ + if (this.icon != null) { │ │ │ │ │ + this.icon.erase(); │ │ │ │ │ } │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: addTile │ │ │ │ │ - * Listener for the layer's addtile event │ │ │ │ │ + * Method: moveTo │ │ │ │ │ + * Move the marker to the new location. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * evt - {Object} The listener argument │ │ │ │ │ + * px - {|Object} the pixel position to move to. │ │ │ │ │ + * An OpenLayers.Pixel or an object with a 'x' and 'y' properties. │ │ │ │ │ */ │ │ │ │ │ - addTile: function(evt) { │ │ │ │ │ - if (evt.tile instanceof OpenLayers.Tile.Image) { │ │ │ │ │ - evt.tile.events.on({ │ │ │ │ │ - beforedraw: this.queueTileDraw, │ │ │ │ │ - beforeload: this.manageTileCache, │ │ │ │ │ - loadend: this.addToCache, │ │ │ │ │ - unload: this.unloadTile, │ │ │ │ │ - scope: this │ │ │ │ │ - }); │ │ │ │ │ - } else { │ │ │ │ │ - // Layer has the wrong tile type, so don't handle it any longer │ │ │ │ │ - this.removeLayer({ │ │ │ │ │ - layer: evt.tile.layer │ │ │ │ │ - }); │ │ │ │ │ + moveTo: function(px) { │ │ │ │ │ + if ((px != null) && (this.icon != null)) { │ │ │ │ │ + this.icon.moveTo(px); │ │ │ │ │ } │ │ │ │ │ + this.lonlat = this.map.getLonLatFromLayerPx(px); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: unloadTile │ │ │ │ │ - * Listener for the tile's unload event │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {Object} The listener argument │ │ │ │ │ + * APIMethod: isDrawn │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Whether or not the marker is drawn. │ │ │ │ │ */ │ │ │ │ │ - unloadTile: function(evt) { │ │ │ │ │ - var tile = evt.object; │ │ │ │ │ - tile.events.un({ │ │ │ │ │ - beforedraw: this.queueTileDraw, │ │ │ │ │ - beforeload: this.manageTileCache, │ │ │ │ │ - loadend: this.addToCache, │ │ │ │ │ - unload: this.unloadTile, │ │ │ │ │ - scope: this │ │ │ │ │ - }); │ │ │ │ │ - OpenLayers.Util.removeItem(this.tileQueue[tile.layer.map.id], tile); │ │ │ │ │ + isDrawn: function() { │ │ │ │ │ + var isDrawn = (this.icon && this.icon.isDrawn()); │ │ │ │ │ + return isDrawn; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: queueTileDraw │ │ │ │ │ - * Adds a tile to the queue that will draw it. │ │ │ │ │ + * Method: onScreen │ │ │ │ │ * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {Object} Listener argument of the tile's beforedraw event │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Whether or not the marker is currently visible on screen. │ │ │ │ │ */ │ │ │ │ │ - queueTileDraw: function(evt) { │ │ │ │ │ - var tile = evt.object; │ │ │ │ │ - var queued = false; │ │ │ │ │ - var layer = tile.layer; │ │ │ │ │ - var url = layer.getURL(tile.bounds); │ │ │ │ │ - var img = this.tileCache[url]; │ │ │ │ │ - if (img && img.className !== 'olTileImage') { │ │ │ │ │ - // cached image no longer valid, e.g. because we're olTileReplacing │ │ │ │ │ - delete this.tileCache[url]; │ │ │ │ │ - OpenLayers.Util.removeItem(this.tileCacheIndex, url); │ │ │ │ │ - img = null; │ │ │ │ │ - } │ │ │ │ │ - // queue only if image with same url not cached already │ │ │ │ │ - if (layer.url && (layer.async || !img)) { │ │ │ │ │ - // add to queue only if not in queue already │ │ │ │ │ - var tileQueue = this.tileQueue[layer.map.id]; │ │ │ │ │ - if (!~OpenLayers.Util.indexOf(tileQueue, tile)) { │ │ │ │ │ - tileQueue.push(tile); │ │ │ │ │ - } │ │ │ │ │ - queued = true; │ │ │ │ │ - } │ │ │ │ │ - return !queued; │ │ │ │ │ - }, │ │ │ │ │ + onScreen: function() { │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: drawTilesFromQueue │ │ │ │ │ - * Draws tiles from the tileQueue, and unqueues the tiles │ │ │ │ │ - */ │ │ │ │ │ - drawTilesFromQueue: function(map) { │ │ │ │ │ - var tileQueue = this.tileQueue[map.id]; │ │ │ │ │ - var limit = this.tilesPerFrame; │ │ │ │ │ - var animating = map.zoomTween && map.zoomTween.playing; │ │ │ │ │ - while (!animating && tileQueue.length && limit) { │ │ │ │ │ - tileQueue.shift().draw(true); │ │ │ │ │ - --limit; │ │ │ │ │ + var onScreen = false; │ │ │ │ │ + if (this.map) { │ │ │ │ │ + var screenBounds = this.map.getExtent(); │ │ │ │ │ + onScreen = screenBounds.containsLonLat(this.lonlat); │ │ │ │ │ } │ │ │ │ │ + return onScreen; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: manageTileCache │ │ │ │ │ - * Adds, updates, removes and fetches cache entries. │ │ │ │ │ + * Method: inflate │ │ │ │ │ + * Englarges the markers icon by the specified ratio. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * evt - {Object} Listener argument of the tile's beforeload event │ │ │ │ │ + * inflate - {float} the ratio to enlarge the marker by (passing 2 │ │ │ │ │ + * will double the size). │ │ │ │ │ */ │ │ │ │ │ - manageTileCache: function(evt) { │ │ │ │ │ - var tile = evt.object; │ │ │ │ │ - var img = this.tileCache[tile.url]; │ │ │ │ │ - if (img) { │ │ │ │ │ - // if image is on its layer's backbuffer, remove it from backbuffer │ │ │ │ │ - if (img.parentNode && │ │ │ │ │ - OpenLayers.Element.hasClass(img.parentNode, 'olBackBuffer')) { │ │ │ │ │ - img.parentNode.removeChild(img); │ │ │ │ │ - img.id = null; │ │ │ │ │ - } │ │ │ │ │ - // only use image from cache if it is not on a layer already │ │ │ │ │ - if (!img.parentNode) { │ │ │ │ │ - img.style.visibility = 'hidden'; │ │ │ │ │ - img.style.opacity = 0; │ │ │ │ │ - tile.setImage(img); │ │ │ │ │ - // LRU - move tile to the end of the array to mark it as the most │ │ │ │ │ - // recently used │ │ │ │ │ - OpenLayers.Util.removeItem(this.tileCacheIndex, tile.url); │ │ │ │ │ - this.tileCacheIndex.push(tile.url); │ │ │ │ │ - } │ │ │ │ │ + inflate: function(inflate) { │ │ │ │ │ + if (this.icon) { │ │ │ │ │ + this.icon.setSize({ │ │ │ │ │ + w: this.icon.size.w * inflate, │ │ │ │ │ + h: this.icon.size.h * inflate │ │ │ │ │ + }); │ │ │ │ │ } │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: addToCache │ │ │ │ │ - * │ │ │ │ │ + /** │ │ │ │ │ + * Method: setOpacity │ │ │ │ │ + * Change the opacity of the marker by changin the opacity of │ │ │ │ │ + * its icon │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * evt - {Object} Listener argument for the tile's loadend event │ │ │ │ │ + * opacity - {float} Specified as fraction (0.4, etc) │ │ │ │ │ */ │ │ │ │ │ - addToCache: function(evt) { │ │ │ │ │ - var tile = evt.object; │ │ │ │ │ - if (!this.tileCache[tile.url]) { │ │ │ │ │ - if (!OpenLayers.Element.hasClass(tile.imgDiv, 'olImageLoadError')) { │ │ │ │ │ - if (this.tileCacheIndex.length >= this.cacheSize) { │ │ │ │ │ - delete this.tileCache[this.tileCacheIndex[0]]; │ │ │ │ │ - this.tileCacheIndex.shift(); │ │ │ │ │ - } │ │ │ │ │ - this.tileCache[tile.url] = tile.imgDiv; │ │ │ │ │ - this.tileCacheIndex.push(tile.url); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ + setOpacity: function(opacity) { │ │ │ │ │ + this.icon.setOpacity(opacity); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: clearTileQueue │ │ │ │ │ - * Clears the tile queue from tiles of a specific layer │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {Object} Listener argument of the layer's retile event │ │ │ │ │ + * Method: setUrl │ │ │ │ │ + * Change URL of the Icon Image. │ │ │ │ │ + * │ │ │ │ │ + * url - {String} │ │ │ │ │ */ │ │ │ │ │ - clearTileQueue: function(evt) { │ │ │ │ │ - var layer = evt.object; │ │ │ │ │ - var tileQueue = this.tileQueue[layer.map.id]; │ │ │ │ │ - for (var i = tileQueue.length - 1; i >= 0; --i) { │ │ │ │ │ - if (tileQueue[i].layer === layer) { │ │ │ │ │ - tileQueue.splice(i, 1); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ + setUrl: function(url) { │ │ │ │ │ + this.icon.setUrl(url); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: destroy │ │ │ │ │ + /** │ │ │ │ │ + * Method: display │ │ │ │ │ + * Hide or show the icon │ │ │ │ │ + * │ │ │ │ │ + * display - {Boolean} │ │ │ │ │ */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - for (var i = this.maps.length - 1; i >= 0; --i) { │ │ │ │ │ - this.removeMap(this.maps[i]); │ │ │ │ │ - } │ │ │ │ │ - this.maps = null; │ │ │ │ │ - this.tileQueue = null; │ │ │ │ │ - this.tileQueueId = null; │ │ │ │ │ - this.tileCache = null; │ │ │ │ │ - this.tileCacheIndex = null; │ │ │ │ │ - this._destroyed = true; │ │ │ │ │ - } │ │ │ │ │ + display: function(display) { │ │ │ │ │ + this.icon.display(display); │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ + CLASS_NAME: "OpenLayers.Marker" │ │ │ │ │ }); │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Function: defaultIcon │ │ │ │ │ + * Creates a default . │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {} A default OpenLayers.Icon to use for a marker │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Marker.defaultIcon = function() { │ │ │ │ │ + return new OpenLayers.Icon(OpenLayers.Util.getImageLocation("marker.png"), { │ │ │ │ │ + w: 21, │ │ │ │ │ + h: 25 │ │ │ │ │ + }, { │ │ │ │ │ + x: -10.5, │ │ │ │ │ + y: -25 │ │ │ │ │ + }); │ │ │ │ │ +}; │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ /* ====================================================================== │ │ │ │ │ OpenLayers/Popup.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ @@ -31160,2468 +32958,137 @@ │ │ │ │ │ │ │ │ │ │ OpenLayers.Popup.WIDTH = 200; │ │ │ │ │ OpenLayers.Popup.HEIGHT = 200; │ │ │ │ │ OpenLayers.Popup.COLOR = "white"; │ │ │ │ │ OpenLayers.Popup.OPACITY = 1; │ │ │ │ │ OpenLayers.Popup.BORDER = "0px"; │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Control.js │ │ │ │ │ + OpenLayers/Marker/Box.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ + │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ + * @requires OpenLayers/Marker.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Control │ │ │ │ │ - * Controls affect the display or behavior of the map. They allow everything │ │ │ │ │ - * from panning and zooming to displaying a scale indicator. Controls by │ │ │ │ │ - * default are added to the map they are contained within however it is │ │ │ │ │ - * possible to add a control to an external div by passing the div in the │ │ │ │ │ - * options parameter. │ │ │ │ │ - * │ │ │ │ │ - * Example: │ │ │ │ │ - * The following example shows how to add many of the common controls │ │ │ │ │ - * to a map. │ │ │ │ │ - * │ │ │ │ │ - * > var map = new OpenLayers.Map('map', { controls: [] }); │ │ │ │ │ - * > │ │ │ │ │ - * > map.addControl(new OpenLayers.Control.PanZoomBar()); │ │ │ │ │ - * > map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':false})); │ │ │ │ │ - * > map.addControl(new OpenLayers.Control.Permalink()); │ │ │ │ │ - * > map.addControl(new OpenLayers.Control.Permalink('permalink')); │ │ │ │ │ - * > map.addControl(new OpenLayers.Control.MousePosition()); │ │ │ │ │ - * > map.addControl(new OpenLayers.Control.OverviewMap()); │ │ │ │ │ - * > map.addControl(new OpenLayers.Control.KeyboardDefaults()); │ │ │ │ │ - * │ │ │ │ │ - * The next code fragment is a quick example of how to intercept │ │ │ │ │ - * shift-mouse click to display the extent of the bounding box │ │ │ │ │ - * dragged out by the user. Usually controls are not created │ │ │ │ │ - * in exactly this manner. See the source for a more complete │ │ │ │ │ - * example: │ │ │ │ │ + * Class: OpenLayers.Marker.Box │ │ │ │ │ * │ │ │ │ │ - * > var control = new OpenLayers.Control(); │ │ │ │ │ - * > OpenLayers.Util.extend(control, { │ │ │ │ │ - * > draw: function () { │ │ │ │ │ - * > // this Handler.Box will intercept the shift-mousedown │ │ │ │ │ - * > // before Control.MouseDefault gets to see it │ │ │ │ │ - * > this.box = new OpenLayers.Handler.Box( control, │ │ │ │ │ - * > {"done": this.notice}, │ │ │ │ │ - * > {keyMask: OpenLayers.Handler.MOD_SHIFT}); │ │ │ │ │ - * > this.box.activate(); │ │ │ │ │ - * > }, │ │ │ │ │ - * > │ │ │ │ │ - * > notice: function (bounds) { │ │ │ │ │ - * > OpenLayers.Console.userError(bounds); │ │ │ │ │ - * > } │ │ │ │ │ - * > }); │ │ │ │ │ - * > map.addControl(control); │ │ │ │ │ - * │ │ │ │ │ + * Inherits from: │ │ │ │ │ + * - │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Control = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: id │ │ │ │ │ - * {String} │ │ │ │ │ - */ │ │ │ │ │ - id: null, │ │ │ │ │ +OpenLayers.Marker.Box = OpenLayers.Class(OpenLayers.Marker, { │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: map │ │ │ │ │ - * {} this gets set in the addControl() function in │ │ │ │ │ - * OpenLayers.Map │ │ │ │ │ + * Property: bounds │ │ │ │ │ + * {} │ │ │ │ │ */ │ │ │ │ │ - map: null, │ │ │ │ │ + bounds: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: div │ │ │ │ │ - * {DOMElement} The element that contains the control, if not present the │ │ │ │ │ - * control is placed inside the map. │ │ │ │ │ + * Property: div │ │ │ │ │ + * {DOMElement} │ │ │ │ │ */ │ │ │ │ │ div: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: type │ │ │ │ │ - * {Number} Controls can have a 'type'. The type determines the type of │ │ │ │ │ - * interactions which are possible with them when they are placed in an │ │ │ │ │ - * . │ │ │ │ │ - */ │ │ │ │ │ - type: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: allowSelection │ │ │ │ │ - * {Boolean} By default, controls do not allow selection, because │ │ │ │ │ - * it may interfere with map dragging. If this is true, OpenLayers │ │ │ │ │ - * will not prevent selection of the control. │ │ │ │ │ - * Default is false. │ │ │ │ │ - */ │ │ │ │ │ - allowSelection: false, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: displayClass │ │ │ │ │ - * {string} This property is used for CSS related to the drawing of the │ │ │ │ │ - * Control. │ │ │ │ │ - */ │ │ │ │ │ - displayClass: "", │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: title │ │ │ │ │ - * {string} This property is used for showing a tooltip over the │ │ │ │ │ - * Control. │ │ │ │ │ - */ │ │ │ │ │ - title: "", │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: autoActivate │ │ │ │ │ - * {Boolean} Activate the control when it is added to a map. Default is │ │ │ │ │ - * false. │ │ │ │ │ - */ │ │ │ │ │ - autoActivate: false, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: active │ │ │ │ │ - * {Boolean} The control is active (read-only). Use and │ │ │ │ │ - * to change control state. │ │ │ │ │ - */ │ │ │ │ │ - active: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: handlerOptions │ │ │ │ │ - * {Object} Used to set non-default properties on the control's handler │ │ │ │ │ - */ │ │ │ │ │ - handlerOptions: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: handler │ │ │ │ │ - * {} null │ │ │ │ │ - */ │ │ │ │ │ - handler: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: eventListeners │ │ │ │ │ - * {Object} If set as an option at construction, the eventListeners │ │ │ │ │ - * object will be registered with . Object │ │ │ │ │ - * structure must be a listeners object as shown in the example for │ │ │ │ │ - * the events.on method. │ │ │ │ │ - */ │ │ │ │ │ - eventListeners: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: events │ │ │ │ │ - * {} Events instance for listeners and triggering │ │ │ │ │ - * control specific events. │ │ │ │ │ - * │ │ │ │ │ - * Register a listener for a particular event with the following syntax: │ │ │ │ │ - * (code) │ │ │ │ │ - * control.events.register(type, obj, listener); │ │ │ │ │ - * (end) │ │ │ │ │ - * │ │ │ │ │ - * Listeners will be called with a reference to an event object. The │ │ │ │ │ - * properties of this event depends on exactly what happened. │ │ │ │ │ - * │ │ │ │ │ - * All event objects have at least the following properties: │ │ │ │ │ - * object - {Object} A reference to control.events.object (a reference │ │ │ │ │ - * to the control). │ │ │ │ │ - * element - {DOMElement} A reference to control.events.element (which │ │ │ │ │ - * will be null unless documented otherwise). │ │ │ │ │ - * │ │ │ │ │ - * Supported map event types: │ │ │ │ │ - * activate - Triggered when activated. │ │ │ │ │ - * deactivate - Triggered when deactivated. │ │ │ │ │ - */ │ │ │ │ │ - events: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Control │ │ │ │ │ - * Create an OpenLayers Control. The options passed as a parameter │ │ │ │ │ - * directly extend the control. For example passing the following: │ │ │ │ │ - * │ │ │ │ │ - * > var control = new OpenLayers.Control({div: myDiv}); │ │ │ │ │ + * Constructor: OpenLayers.Marker.Box │ │ │ │ │ * │ │ │ │ │ - * Overrides the default div attribute value of null. │ │ │ │ │ - * │ │ │ │ │ * Parameters: │ │ │ │ │ - * options - {Object} │ │ │ │ │ + * bounds - {} │ │ │ │ │ + * borderColor - {String} │ │ │ │ │ + * borderWidth - {int} │ │ │ │ │ */ │ │ │ │ │ - initialize: function(options) { │ │ │ │ │ - // We do this before the extend so that instances can override │ │ │ │ │ - // className in options. │ │ │ │ │ - this.displayClass = │ │ │ │ │ - this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, ""); │ │ │ │ │ - │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - │ │ │ │ │ - this.events = new OpenLayers.Events(this); │ │ │ │ │ - if (this.eventListeners instanceof Object) { │ │ │ │ │ - this.events.on(this.eventListeners); │ │ │ │ │ - } │ │ │ │ │ - if (this.id == null) { │ │ │ │ │ - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ - } │ │ │ │ │ + initialize: function(bounds, borderColor, borderWidth) { │ │ │ │ │ + this.bounds = bounds; │ │ │ │ │ + this.div = OpenLayers.Util.createDiv(); │ │ │ │ │ + this.div.style.overflow = 'hidden'; │ │ │ │ │ + this.events = new OpenLayers.Events(this, this.div); │ │ │ │ │ + this.setBorder(borderColor, borderWidth); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: destroy │ │ │ │ │ - * The destroy method is used to perform any clean up before the control │ │ │ │ │ - * is dereferenced. Typically this is where event listeners are removed │ │ │ │ │ - * to prevent memory leaks. │ │ │ │ │ + * Method: destroy │ │ │ │ │ */ │ │ │ │ │ destroy: function() { │ │ │ │ │ - if (this.events) { │ │ │ │ │ - if (this.eventListeners) { │ │ │ │ │ - this.events.un(this.eventListeners); │ │ │ │ │ - } │ │ │ │ │ - this.events.destroy(); │ │ │ │ │ - this.events = null; │ │ │ │ │ - } │ │ │ │ │ - this.eventListeners = null; │ │ │ │ │ │ │ │ │ │ - // eliminate circular references │ │ │ │ │ - if (this.handler) { │ │ │ │ │ - this.handler.destroy(); │ │ │ │ │ - this.handler = null; │ │ │ │ │ - } │ │ │ │ │ - if (this.handlers) { │ │ │ │ │ - for (var key in this.handlers) { │ │ │ │ │ - if (this.handlers.hasOwnProperty(key) && │ │ │ │ │ - typeof this.handlers[key].destroy == "function") { │ │ │ │ │ - this.handlers[key].destroy(); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - this.handlers = null; │ │ │ │ │ - } │ │ │ │ │ - if (this.map) { │ │ │ │ │ - this.map.removeControl(this); │ │ │ │ │ - this.map = null; │ │ │ │ │ - } │ │ │ │ │ + this.bounds = null; │ │ │ │ │ this.div = null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: setMap │ │ │ │ │ - * Set the map property for the control. This is done through an accessor │ │ │ │ │ - * so that subclasses can override this and take special action once │ │ │ │ │ - * they have their map variable set. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * map - {} │ │ │ │ │ - */ │ │ │ │ │ - setMap: function(map) { │ │ │ │ │ - this.map = map; │ │ │ │ │ - if (this.handler) { │ │ │ │ │ - this.handler.setMap(map); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: draw │ │ │ │ │ - * The draw method is called when the control is ready to be displayed │ │ │ │ │ - * on the page. If a div has not been created one is created. Controls │ │ │ │ │ - * with a visual component will almost always want to override this method │ │ │ │ │ - * to customize the look of control. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * px - {} The top-left pixel position of the control │ │ │ │ │ - * or null. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {DOMElement} A reference to the DIV DOMElement containing the control │ │ │ │ │ - */ │ │ │ │ │ - draw: function(px) { │ │ │ │ │ - if (this.div == null) { │ │ │ │ │ - this.div = OpenLayers.Util.createDiv(this.id); │ │ │ │ │ - this.div.className = this.displayClass; │ │ │ │ │ - if (!this.allowSelection) { │ │ │ │ │ - this.div.className += " olControlNoSelect"; │ │ │ │ │ - this.div.setAttribute("unselectable", "on", 0); │ │ │ │ │ - this.div.onselectstart = OpenLayers.Function.False; │ │ │ │ │ - } │ │ │ │ │ - if (this.title != "") { │ │ │ │ │ - this.div.title = this.title; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - if (px != null) { │ │ │ │ │ - this.position = px.clone(); │ │ │ │ │ - } │ │ │ │ │ - this.moveTo(this.position); │ │ │ │ │ - return this.div; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: moveTo │ │ │ │ │ - * Sets the left and top style attributes to the passed in pixel │ │ │ │ │ - * coordinates. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * px - {} │ │ │ │ │ - */ │ │ │ │ │ - moveTo: function(px) { │ │ │ │ │ - if ((px != null) && (this.div != null)) { │ │ │ │ │ - this.div.style.left = px.x + "px"; │ │ │ │ │ - this.div.style.top = px.y + "px"; │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: activate │ │ │ │ │ - * Explicitly activates a control and it's associated │ │ │ │ │ - * handler if one has been set. Controls can be │ │ │ │ │ - * deactivated by calling the deactivate() method. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} True if the control was successfully activated or │ │ │ │ │ - * false if the control was already active. │ │ │ │ │ - */ │ │ │ │ │ - activate: function() { │ │ │ │ │ - if (this.active) { │ │ │ │ │ - return false; │ │ │ │ │ - } │ │ │ │ │ - if (this.handler) { │ │ │ │ │ - this.handler.activate(); │ │ │ │ │ - } │ │ │ │ │ - this.active = true; │ │ │ │ │ - if (this.map) { │ │ │ │ │ - OpenLayers.Element.addClass( │ │ │ │ │ - this.map.viewPortDiv, │ │ │ │ │ - this.displayClass.replace(/ /g, "") + "Active" │ │ │ │ │ - ); │ │ │ │ │ - } │ │ │ │ │ - this.events.triggerEvent("activate"); │ │ │ │ │ - return true; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: deactivate │ │ │ │ │ - * Deactivates a control and it's associated handler if any. The exact │ │ │ │ │ - * effect of this depends on the control itself. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} True if the control was effectively deactivated or false │ │ │ │ │ - * if the control was already inactive. │ │ │ │ │ - */ │ │ │ │ │ - deactivate: function() { │ │ │ │ │ - if (this.active) { │ │ │ │ │ - if (this.handler) { │ │ │ │ │ - this.handler.deactivate(); │ │ │ │ │ - } │ │ │ │ │ - this.active = false; │ │ │ │ │ - if (this.map) { │ │ │ │ │ - OpenLayers.Element.removeClass( │ │ │ │ │ - this.map.viewPortDiv, │ │ │ │ │ - this.displayClass.replace(/ /g, "") + "Active" │ │ │ │ │ - ); │ │ │ │ │ - } │ │ │ │ │ - this.events.triggerEvent("deactivate"); │ │ │ │ │ - return true; │ │ │ │ │ - } │ │ │ │ │ - return false; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Control" │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Control.TYPE_BUTTON │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Control.TYPE_BUTTON = 1; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Control.TYPE_TOGGLE │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Control.TYPE_TOGGLE = 2; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Control.TYPE_TOOL │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Control.TYPE_TOOL = 3; │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Rule.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - * @requires OpenLayers/Util.js │ │ │ │ │ - * @requires OpenLayers/Style.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Rule │ │ │ │ │ - * This class represents an SLD Rule, as being used for rule-based SLD styling. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Rule = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: id │ │ │ │ │ - * {String} A unique id for this session. │ │ │ │ │ - */ │ │ │ │ │ - id: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: name │ │ │ │ │ - * {String} name of this rule │ │ │ │ │ - */ │ │ │ │ │ - name: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: title │ │ │ │ │ - * {String} Title of this rule (set if included in SLD) │ │ │ │ │ - */ │ │ │ │ │ - title: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: description │ │ │ │ │ - * {String} Description of this rule (set if abstract is included in SLD) │ │ │ │ │ - */ │ │ │ │ │ - description: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: context │ │ │ │ │ - * {Object} An optional object with properties that the rule should be │ │ │ │ │ - * evaluated against. If no context is specified, feature.attributes will │ │ │ │ │ - * be used. │ │ │ │ │ - */ │ │ │ │ │ - context: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: filter │ │ │ │ │ - * {} Optional filter for the rule. │ │ │ │ │ - */ │ │ │ │ │ - filter: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: elseFilter │ │ │ │ │ - * {Boolean} Determines whether this rule is only to be applied only if │ │ │ │ │ - * no other rules match (ElseFilter according to the SLD specification). │ │ │ │ │ - * Default is false. For instances of OpenLayers.Rule, if elseFilter is │ │ │ │ │ - * false, the rule will always apply. For subclasses, the else property is │ │ │ │ │ - * ignored. │ │ │ │ │ - */ │ │ │ │ │ - elseFilter: false, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: symbolizer │ │ │ │ │ - * {Object} Symbolizer or hash of symbolizers for this rule. If hash of │ │ │ │ │ - * symbolizers, keys are one or more of ["Point", "Line", "Polygon"]. The │ │ │ │ │ - * latter if useful if it is required to style e.g. vertices of a line │ │ │ │ │ - * with a point symbolizer. Note, however, that this is not implemented │ │ │ │ │ - * yet in OpenLayers, but it is the way how symbolizers are defined in │ │ │ │ │ - * SLD. │ │ │ │ │ - */ │ │ │ │ │ - symbolizer: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: symbolizers │ │ │ │ │ - * {Array} Collection of symbolizers associated with this rule. If │ │ │ │ │ - * provided at construction, the symbolizers array has precedence │ │ │ │ │ - * over the deprecated symbolizer property. Note that multiple │ │ │ │ │ - * symbolizers are not currently supported by the vector renderers. │ │ │ │ │ - * Rules with multiple symbolizers are currently only useful for │ │ │ │ │ - * maintaining elements in an SLD document. │ │ │ │ │ - */ │ │ │ │ │ - symbolizers: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: minScaleDenominator │ │ │ │ │ - * {Number} or {String} minimum scale at which to draw the feature. │ │ │ │ │ - * In the case of a String, this can be a combination of text and │ │ │ │ │ - * propertyNames in the form "literal ${propertyName}" │ │ │ │ │ - */ │ │ │ │ │ - minScaleDenominator: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: maxScaleDenominator │ │ │ │ │ - * {Number} or {String} maximum scale at which to draw the feature. │ │ │ │ │ - * In the case of a String, this can be a combination of text and │ │ │ │ │ - * propertyNames in the form "literal ${propertyName}" │ │ │ │ │ - */ │ │ │ │ │ - maxScaleDenominator: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Rule │ │ │ │ │ - * Creates a Rule. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} An optional object with properties to set on the │ │ │ │ │ - * rule │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(options) { │ │ │ │ │ - this.symbolizer = {}; │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - if (this.symbolizers) { │ │ │ │ │ - delete this.symbolizer; │ │ │ │ │ - } │ │ │ │ │ - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: destroy │ │ │ │ │ - * nullify references to prevent circular references and memory leaks │ │ │ │ │ - */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - for (var i in this.symbolizer) { │ │ │ │ │ - this.symbolizer[i] = null; │ │ │ │ │ - } │ │ │ │ │ - this.symbolizer = null; │ │ │ │ │ - delete this.symbolizers; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: evaluate │ │ │ │ │ - * evaluates this rule for a specific feature │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * feature - {} feature to apply the rule to. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} true if the rule applies, false if it does not. │ │ │ │ │ - * This rule is the default rule and always returns true. │ │ │ │ │ - */ │ │ │ │ │ - evaluate: function(feature) { │ │ │ │ │ - var context = this.getContext(feature); │ │ │ │ │ - var applies = true; │ │ │ │ │ - │ │ │ │ │ - if (this.minScaleDenominator || this.maxScaleDenominator) { │ │ │ │ │ - var scale = feature.layer.map.getScale(); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // check if within minScale/maxScale bounds │ │ │ │ │ - if (this.minScaleDenominator) { │ │ │ │ │ - applies = scale >= OpenLayers.Style.createLiteral( │ │ │ │ │ - this.minScaleDenominator, context); │ │ │ │ │ - } │ │ │ │ │ - if (applies && this.maxScaleDenominator) { │ │ │ │ │ - applies = scale < OpenLayers.Style.createLiteral( │ │ │ │ │ - this.maxScaleDenominator, context); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // check if optional filter applies │ │ │ │ │ - if (applies && this.filter) { │ │ │ │ │ - // feature id filters get the feature, others get the context │ │ │ │ │ - if (this.filter.CLASS_NAME == "OpenLayers.Filter.FeatureId") { │ │ │ │ │ - applies = this.filter.evaluate(feature); │ │ │ │ │ - } else { │ │ │ │ │ - applies = this.filter.evaluate(context); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - return applies; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: getContext │ │ │ │ │ - * Gets the context for evaluating this rule │ │ │ │ │ - * │ │ │ │ │ - * Paramters: │ │ │ │ │ - * feature - {} feature to take the context from if │ │ │ │ │ - * none is specified. │ │ │ │ │ - */ │ │ │ │ │ - getContext: function(feature) { │ │ │ │ │ - var context = this.context; │ │ │ │ │ - if (!context) { │ │ │ │ │ - context = feature.attributes || feature.data; │ │ │ │ │ - } │ │ │ │ │ - if (typeof this.context == "function") { │ │ │ │ │ - context = this.context(feature); │ │ │ │ │ - } │ │ │ │ │ - return context; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: clone │ │ │ │ │ - * Clones this rule. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} Clone of this rule. │ │ │ │ │ - */ │ │ │ │ │ - clone: function() { │ │ │ │ │ - var options = OpenLayers.Util.extend({}, this); │ │ │ │ │ - if (this.symbolizers) { │ │ │ │ │ - // clone symbolizers │ │ │ │ │ - var len = this.symbolizers.length; │ │ │ │ │ - options.symbolizers = new Array(len); │ │ │ │ │ - for (var i = 0; i < len; ++i) { │ │ │ │ │ - options.symbolizers[i] = this.symbolizers[i].clone(); │ │ │ │ │ - } │ │ │ │ │ - } else { │ │ │ │ │ - // clone symbolizer │ │ │ │ │ - options.symbolizer = {}; │ │ │ │ │ - var value, type; │ │ │ │ │ - for (var key in this.symbolizer) { │ │ │ │ │ - value = this.symbolizer[key]; │ │ │ │ │ - type = typeof value; │ │ │ │ │ - if (type === "object") { │ │ │ │ │ - options.symbolizer[key] = OpenLayers.Util.extend({}, value); │ │ │ │ │ - } else if (type === "string") { │ │ │ │ │ - options.symbolizer[key] = value; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - // clone filter │ │ │ │ │ - options.filter = this.filter && this.filter.clone(); │ │ │ │ │ - // clone context │ │ │ │ │ - options.context = this.context && OpenLayers.Util.extend({}, this.context); │ │ │ │ │ - return new OpenLayers.Rule(options); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Rule" │ │ │ │ │ -}); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Renderer.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Renderer │ │ │ │ │ - * This is the base class for all renderers. │ │ │ │ │ - * │ │ │ │ │ - * This is based on a merger code written by Paul Spencer and Bertil Chapuis. │ │ │ │ │ - * It is largely composed of virtual functions that are to be implemented │ │ │ │ │ - * in technology-specific subclasses, but there is some generic code too. │ │ │ │ │ - * │ │ │ │ │ - * The functions that *are* implemented here merely deal with the maintenance │ │ │ │ │ - * of the size and extent variables, as well as the cached 'resolution' │ │ │ │ │ - * value. │ │ │ │ │ - * │ │ │ │ │ - * A note to the user that all subclasses should use getResolution() instead │ │ │ │ │ - * of directly accessing this.resolution in order to correctly use the │ │ │ │ │ - * cacheing system. │ │ │ │ │ - * │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Renderer = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: container │ │ │ │ │ - * {DOMElement} │ │ │ │ │ - */ │ │ │ │ │ - container: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: root │ │ │ │ │ - * {DOMElement} │ │ │ │ │ - */ │ │ │ │ │ - root: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: extent │ │ │ │ │ - * {} │ │ │ │ │ - */ │ │ │ │ │ - extent: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: locked │ │ │ │ │ - * {Boolean} If the renderer is currently in a state where many things │ │ │ │ │ - * are changing, the 'locked' property is set to true. This means │ │ │ │ │ - * that renderers can expect at least one more drawFeature event to be │ │ │ │ │ - * called with the 'locked' property set to 'true': In some renderers, │ │ │ │ │ - * this might make sense to use as a 'only update local information' │ │ │ │ │ - * flag. │ │ │ │ │ - */ │ │ │ │ │ - locked: false, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: size │ │ │ │ │ - * {} │ │ │ │ │ - */ │ │ │ │ │ - size: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: resolution │ │ │ │ │ - * {Float} cache of current map resolution │ │ │ │ │ - */ │ │ │ │ │ - resolution: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: map │ │ │ │ │ - * {} Reference to the map -- this is set in Vector's setMap() │ │ │ │ │ - */ │ │ │ │ │ - map: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: featureDx │ │ │ │ │ - * {Number} Feature offset in x direction. Will be calculated for and │ │ │ │ │ - * applied to the current feature while rendering (see │ │ │ │ │ - * ). │ │ │ │ │ - */ │ │ │ │ │ - featureDx: 0, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Renderer │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * containerID - {} │ │ │ │ │ - * options - {Object} options for this renderer. See sublcasses for │ │ │ │ │ - * supported options. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(containerID, options) { │ │ │ │ │ - this.container = OpenLayers.Util.getElement(containerID); │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: destroy │ │ │ │ │ - */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - this.container = null; │ │ │ │ │ - this.extent = null; │ │ │ │ │ - this.size = null; │ │ │ │ │ - this.resolution = null; │ │ │ │ │ - this.map = null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: supported │ │ │ │ │ - * This should be overridden by specific subclasses │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} Whether or not the browser supports the renderer class │ │ │ │ │ - */ │ │ │ │ │ - supported: function() { │ │ │ │ │ - return false; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: setExtent │ │ │ │ │ - * Set the visible part of the layer. │ │ │ │ │ - * │ │ │ │ │ - * Resolution has probably changed, so we nullify the resolution │ │ │ │ │ - * cache (this.resolution) -- this way it will be re-computed when │ │ │ │ │ - * next it is needed. │ │ │ │ │ - * We nullify the resolution cache (this.resolution) if resolutionChanged │ │ │ │ │ - * is set to true - this way it will be re-computed on the next │ │ │ │ │ - * getResolution() request. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * extent - {} │ │ │ │ │ - * resolutionChanged - {Boolean} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} true to notify the layer that the new extent does not exceed │ │ │ │ │ - * the coordinate range, and the features will not need to be redrawn. │ │ │ │ │ - * False otherwise. │ │ │ │ │ - */ │ │ │ │ │ - setExtent: function(extent, resolutionChanged) { │ │ │ │ │ - this.extent = extent.clone(); │ │ │ │ │ - if (this.map.baseLayer && this.map.baseLayer.wrapDateLine) { │ │ │ │ │ - var ratio = extent.getWidth() / this.map.getExtent().getWidth(), │ │ │ │ │ - extent = extent.scale(1 / ratio); │ │ │ │ │ - this.extent = extent.wrapDateLine(this.map.getMaxExtent()).scale(ratio); │ │ │ │ │ - } │ │ │ │ │ - if (resolutionChanged) { │ │ │ │ │ - this.resolution = null; │ │ │ │ │ - } │ │ │ │ │ - return true; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: setSize │ │ │ │ │ - * Sets the size of the drawing surface. │ │ │ │ │ - * │ │ │ │ │ - * Resolution has probably changed, so we nullify the resolution │ │ │ │ │ - * cache (this.resolution) -- this way it will be re-computed when │ │ │ │ │ - * next it is needed. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * size - {} │ │ │ │ │ - */ │ │ │ │ │ - setSize: function(size) { │ │ │ │ │ - this.size = size.clone(); │ │ │ │ │ - this.resolution = null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: getResolution │ │ │ │ │ - * Uses cached copy of resolution if available to minimize computing │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Float} The current map's resolution │ │ │ │ │ - */ │ │ │ │ │ - getResolution: function() { │ │ │ │ │ - this.resolution = this.resolution || this.map.getResolution(); │ │ │ │ │ - return this.resolution; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: drawFeature │ │ │ │ │ - * Draw the feature. The optional style argument can be used │ │ │ │ │ - * to override the feature's own style. This method should only │ │ │ │ │ - * be called from layer.drawFeature(). │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * feature - {} │ │ │ │ │ - * style - {} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} true if the feature has been drawn completely, false if not, │ │ │ │ │ - * undefined if the feature had no geometry │ │ │ │ │ - */ │ │ │ │ │ - drawFeature: function(feature, style) { │ │ │ │ │ - if (style == null) { │ │ │ │ │ - style = feature.style; │ │ │ │ │ - } │ │ │ │ │ - if (feature.geometry) { │ │ │ │ │ - var bounds = feature.geometry.getBounds(); │ │ │ │ │ - if (bounds) { │ │ │ │ │ - var worldBounds; │ │ │ │ │ - if (this.map.baseLayer && this.map.baseLayer.wrapDateLine) { │ │ │ │ │ - worldBounds = this.map.getMaxExtent(); │ │ │ │ │ - } │ │ │ │ │ - if (!bounds.intersectsBounds(this.extent, { │ │ │ │ │ - worldBounds: worldBounds │ │ │ │ │ - })) { │ │ │ │ │ - style = { │ │ │ │ │ - display: "none" │ │ │ │ │ - }; │ │ │ │ │ - } else { │ │ │ │ │ - this.calculateFeatureDx(bounds, worldBounds); │ │ │ │ │ - } │ │ │ │ │ - var rendered = this.drawGeometry(feature.geometry, style, feature.id); │ │ │ │ │ - if (style.display != "none" && style.label && rendered !== false) { │ │ │ │ │ - │ │ │ │ │ - var location = feature.geometry.getCentroid(); │ │ │ │ │ - if (style.labelXOffset || style.labelYOffset) { │ │ │ │ │ - var xOffset = isNaN(style.labelXOffset) ? 0 : style.labelXOffset; │ │ │ │ │ - var yOffset = isNaN(style.labelYOffset) ? 0 : style.labelYOffset; │ │ │ │ │ - var res = this.getResolution(); │ │ │ │ │ - location.move(xOffset * res, yOffset * res); │ │ │ │ │ - } │ │ │ │ │ - this.drawText(feature.id, style, location); │ │ │ │ │ - } else { │ │ │ │ │ - this.removeText(feature.id); │ │ │ │ │ - } │ │ │ │ │ - return rendered; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: calculateFeatureDx │ │ │ │ │ - * {Number} Calculates the feature offset in x direction. Looking at the │ │ │ │ │ - * center of the feature bounds and the renderer extent, we calculate how │ │ │ │ │ - * many world widths the two are away from each other. This distance is │ │ │ │ │ - * used to shift the feature as close as possible to the center of the │ │ │ │ │ - * current enderer extent, which ensures that the feature is visible in the │ │ │ │ │ - * current viewport. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * bounds - {} Bounds of the feature │ │ │ │ │ - * worldBounds - {} Bounds of the world │ │ │ │ │ - */ │ │ │ │ │ - calculateFeatureDx: function(bounds, worldBounds) { │ │ │ │ │ - this.featureDx = 0; │ │ │ │ │ - if (worldBounds) { │ │ │ │ │ - var worldWidth = worldBounds.getWidth(), │ │ │ │ │ - rendererCenterX = (this.extent.left + this.extent.right) / 2, │ │ │ │ │ - featureCenterX = (bounds.left + bounds.right) / 2, │ │ │ │ │ - worldsAway = Math.round((featureCenterX - rendererCenterX) / worldWidth); │ │ │ │ │ - this.featureDx = worldsAway * worldWidth; │ │ │ │ │ - } │ │ │ │ │ + OpenLayers.Marker.prototype.destroy.apply(this, arguments); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: drawGeometry │ │ │ │ │ - * │ │ │ │ │ - * Draw a geometry. This should only be called from the renderer itself. │ │ │ │ │ - * Use layer.drawFeature() from outside the renderer. │ │ │ │ │ - * virtual function │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * geometry - {} │ │ │ │ │ - * style - {Object} │ │ │ │ │ - * featureId - {} │ │ │ │ │ - */ │ │ │ │ │ - drawGeometry: function(geometry, style, featureId) {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: drawText │ │ │ │ │ - * Function for drawing text labels. │ │ │ │ │ - * This method is only called by the renderer itself. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * featureId - {String} │ │ │ │ │ - * style - │ │ │ │ │ - * location - {} │ │ │ │ │ - */ │ │ │ │ │ - drawText: function(featureId, style, location) {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: removeText │ │ │ │ │ - * Function for removing text labels. │ │ │ │ │ - * This method is only called by the renderer itself. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * featureId - {String} │ │ │ │ │ - */ │ │ │ │ │ - removeText: function(featureId) {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: clear │ │ │ │ │ - * Clear all vectors from the renderer. │ │ │ │ │ - * virtual function. │ │ │ │ │ - */ │ │ │ │ │ - clear: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: getFeatureIdFromEvent │ │ │ │ │ - * Returns a feature id from an event on the renderer. │ │ │ │ │ - * How this happens is specific to the renderer. This should be │ │ │ │ │ - * called from layer.getFeatureFromEvent(). │ │ │ │ │ - * Virtual function. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * evt - {} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} A feature id or undefined. │ │ │ │ │ - */ │ │ │ │ │ - getFeatureIdFromEvent: function(evt) {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: eraseFeatures │ │ │ │ │ - * This is called by the layer to erase features │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * features - {Array()} │ │ │ │ │ - */ │ │ │ │ │ - eraseFeatures: function(features) { │ │ │ │ │ - if (!(OpenLayers.Util.isArray(features))) { │ │ │ │ │ - features = [features]; │ │ │ │ │ - } │ │ │ │ │ - for (var i = 0, len = features.length; i < len; ++i) { │ │ │ │ │ - var feature = features[i]; │ │ │ │ │ - this.eraseGeometry(feature.geometry, feature.id); │ │ │ │ │ - this.removeText(feature.id); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: eraseGeometry │ │ │ │ │ - * Remove a geometry from the renderer (by id). │ │ │ │ │ - * virtual function. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * geometry - {} │ │ │ │ │ - * featureId - {String} │ │ │ │ │ - */ │ │ │ │ │ - eraseGeometry: function(geometry, featureId) {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: moveRoot │ │ │ │ │ - * moves this renderer's root to a (different) renderer. │ │ │ │ │ - * To be implemented by subclasses that require a common renderer root for │ │ │ │ │ - * feature selection. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * renderer - {} target renderer for the moved root │ │ │ │ │ - */ │ │ │ │ │ - moveRoot: function(renderer) {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: getRenderLayerId │ │ │ │ │ - * Gets the layer that this renderer's output appears on. If moveRoot was │ │ │ │ │ - * used, this will be different from the id of the layer containing the │ │ │ │ │ - * features rendered by this renderer. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} the id of the output layer. │ │ │ │ │ - */ │ │ │ │ │ - getRenderLayerId: function() { │ │ │ │ │ - return this.container.id; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: applyDefaultSymbolizer │ │ │ │ │ + * Method: setBorder │ │ │ │ │ + * Allow the user to change the box's color and border width │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * symbolizer - {Object} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} │ │ │ │ │ + * color - {String} Default is "red" │ │ │ │ │ + * width - {int} Default is 2 │ │ │ │ │ */ │ │ │ │ │ - applyDefaultSymbolizer: function(symbolizer) { │ │ │ │ │ - var result = OpenLayers.Util.extend({}, │ │ │ │ │ - OpenLayers.Renderer.defaultSymbolizer); │ │ │ │ │ - if (symbolizer.stroke === false) { │ │ │ │ │ - delete result.strokeWidth; │ │ │ │ │ - delete result.strokeColor; │ │ │ │ │ + setBorder: function(color, width) { │ │ │ │ │ + if (!color) { │ │ │ │ │ + color = "red"; │ │ │ │ │ } │ │ │ │ │ - if (symbolizer.fill === false) { │ │ │ │ │ - delete result.fillColor; │ │ │ │ │ + if (!width) { │ │ │ │ │ + width = 2; │ │ │ │ │ } │ │ │ │ │ - OpenLayers.Util.extend(result, symbolizer); │ │ │ │ │ - return result; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Renderer" │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Renderer.defaultSymbolizer │ │ │ │ │ - * {Object} Properties from this symbolizer will be applied to symbolizers │ │ │ │ │ - * with missing properties. This can also be used to set a global │ │ │ │ │ - * symbolizer default in OpenLayers. To be SLD 1.x compliant, add the │ │ │ │ │ - * following code before rendering any vector features: │ │ │ │ │ - * (code) │ │ │ │ │ - * OpenLayers.Renderer.defaultSymbolizer = { │ │ │ │ │ - * fillColor: "#808080", │ │ │ │ │ - * fillOpacity: 1, │ │ │ │ │ - * strokeColor: "#000000", │ │ │ │ │ - * strokeOpacity: 1, │ │ │ │ │ - * strokeWidth: 1, │ │ │ │ │ - * pointRadius: 3, │ │ │ │ │ - * graphicName: "square" │ │ │ │ │ - * }; │ │ │ │ │ - * (end) │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Renderer.defaultSymbolizer = { │ │ │ │ │ - fillColor: "#000000", │ │ │ │ │ - strokeColor: "#000000", │ │ │ │ │ - strokeWidth: 2, │ │ │ │ │ - fillOpacity: 1, │ │ │ │ │ - strokeOpacity: 1, │ │ │ │ │ - pointRadius: 0, │ │ │ │ │ - labelAlign: 'cm' │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Renderer.symbol │ │ │ │ │ - * Coordinate arrays for well known (named) symbols. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Renderer.symbol = { │ │ │ │ │ - "star": [350, 75, 379, 161, 469, 161, 397, 215, 423, 301, 350, 250, 277, 301, │ │ │ │ │ - 303, 215, 231, 161, 321, 161, 350, 75 │ │ │ │ │ - ], │ │ │ │ │ - "cross": [4, 0, 6, 0, 6, 4, 10, 4, 10, 6, 6, 6, 6, 10, 4, 10, 4, 6, 0, 6, 0, 4, 4, 4, │ │ │ │ │ - 4, 0 │ │ │ │ │ - ], │ │ │ │ │ - "x": [0, 0, 25, 0, 50, 35, 75, 0, 100, 0, 65, 50, 100, 100, 75, 100, 50, 65, 25, 100, 0, 100, 35, 50, 0, 0], │ │ │ │ │ - "square": [0, 0, 0, 1, 1, 1, 1, 0, 0, 0], │ │ │ │ │ - "triangle": [0, 10, 10, 10, 5, 0, 0, 10] │ │ │ │ │ -}; │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Symbolizer/Point.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Symbolizer.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Symbolizer.Point │ │ │ │ │ - * A symbolizer used to render point features. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Symbolizer.Point = OpenLayers.Class(OpenLayers.Symbolizer, { │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeColor │ │ │ │ │ - * {String} Color for line stroke. This is a RGB hex value (e.g. "#ff0000" │ │ │ │ │ - * for red). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeOpacity │ │ │ │ │ - * {Number} Stroke opacity (0-1). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeWidth │ │ │ │ │ - * {Number} Pixel stroke width. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeLinecap │ │ │ │ │ - * {String} Stroke cap type ("butt", "round", or "square"). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: strokeDashstyle │ │ │ │ │ - * {String} Stroke dash style according to the SLD spec. Note that the │ │ │ │ │ - * OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot", │ │ │ │ │ - * "longdash", "longdashdot", or "solid") will not work in SLD, but │ │ │ │ │ - * most SLD patterns will render correctly in OpenLayers. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: fillColor │ │ │ │ │ - * {String} RGB hex fill color (e.g. "#ff0000" for red). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: fillOpacity │ │ │ │ │ - * {Number} Fill opacity (0-1). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: pointRadius │ │ │ │ │ - * {Number} Pixel point radius. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: externalGraphic │ │ │ │ │ - * {String} Url to an external graphic that will be used for rendering │ │ │ │ │ - * points. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: graphicWidth │ │ │ │ │ - * {Number} Pixel width for sizing an external graphic. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: graphicHeight │ │ │ │ │ - * {Number} Pixel height for sizing an external graphic. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: graphicOpacity │ │ │ │ │ - * {Number} Opacity (0-1) for an external graphic. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: graphicXOffset │ │ │ │ │ - * {Number} Pixel offset along the positive x axis for displacing an │ │ │ │ │ - * external graphic. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: graphicYOffset │ │ │ │ │ - * {Number} Pixel offset along the positive y axis for displacing an │ │ │ │ │ - * external graphic. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: rotation │ │ │ │ │ - * {Number} The rotation of a graphic in the clockwise direction about its │ │ │ │ │ - * center point (or any point off center as specified by │ │ │ │ │ - * and ). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: graphicName │ │ │ │ │ - * {String} Named graphic to use when rendering points. Supported values │ │ │ │ │ - * include "circle", "square", "star", "x", "cross", and "triangle". │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Symbolizer.Point │ │ │ │ │ - * Create a symbolizer for rendering points. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} An object containing properties to be set on the │ │ │ │ │ - * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ - * construction. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * A new point symbolizer. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(config) { │ │ │ │ │ - OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Symbolizer.Point" │ │ │ │ │ - │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Symbolizer/Line.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Symbolizer.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Symbolizer.Line │ │ │ │ │ - * A symbolizer used to render line features. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Symbolizer.Line = OpenLayers.Class(OpenLayers.Symbolizer, { │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeColor │ │ │ │ │ - * {String} Color for line stroke. This is a RGB hex value (e.g. "#ff0000" │ │ │ │ │ - * for red). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeOpacity │ │ │ │ │ - * {Number} Stroke opacity (0-1). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeWidth │ │ │ │ │ - * {Number} Pixel stroke width. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeLinecap │ │ │ │ │ - * {String} Stroke cap type ("butt", "round", or "square"). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: strokeDashstyle │ │ │ │ │ - * {String} Stroke dash style according to the SLD spec. Note that the │ │ │ │ │ - * OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot", │ │ │ │ │ - * "longdash", "longdashdot", or "solid") will not work in SLD, but │ │ │ │ │ - * most SLD patterns will render correctly in OpenLayers. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Symbolizer.Line │ │ │ │ │ - * Create a symbolizer for rendering lines. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} An object containing properties to be set on the │ │ │ │ │ - * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ - * construction. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * A new line symbolizer. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(config) { │ │ │ │ │ - OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Symbolizer.Line" │ │ │ │ │ - │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Symbolizer/Polygon.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Symbolizer.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Symbolizer.Polygon │ │ │ │ │ - * A symbolizer used to render line features. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Symbolizer.Polygon = OpenLayers.Class(OpenLayers.Symbolizer, { │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeColor │ │ │ │ │ - * {String} Color for line stroke. This is a RGB hex value (e.g. "#ff0000" │ │ │ │ │ - * for red). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeOpacity │ │ │ │ │ - * {Number} Stroke opacity (0-1). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeWidth │ │ │ │ │ - * {Number} Pixel stroke width. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: strokeLinecap │ │ │ │ │ - * {String} Stroke cap type ("butt", "round", or "square"). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: strokeDashstyle │ │ │ │ │ - * {String} Stroke dash style according to the SLD spec. Note that the │ │ │ │ │ - * OpenLayers values for strokeDashstyle ("dot", "dash", "dashdot", │ │ │ │ │ - * "longdash", "longdashdot", or "solid") will not work in SLD, but │ │ │ │ │ - * most SLD patterns will render correctly in OpenLayers. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: fillColor │ │ │ │ │ - * {String} RGB hex fill color (e.g. "#ff0000" for red). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: fillOpacity │ │ │ │ │ - * {Number} Fill opacity (0-1). │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Symbolizer.Polygon │ │ │ │ │ - * Create a symbolizer for rendering polygons. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} An object containing properties to be set on the │ │ │ │ │ - * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ - * construction. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * A new polygon symbolizer. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(config) { │ │ │ │ │ - OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Symbolizer.Polygon" │ │ │ │ │ - │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Symbolizer/Text.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Symbolizer.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Symbolizer.Text │ │ │ │ │ - * A symbolizer used to render text labels for features. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Symbolizer.Text = OpenLayers.Class(OpenLayers.Symbolizer, { │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: label │ │ │ │ │ - * {String} The text for the label. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: fontFamily │ │ │ │ │ - * {String} The font family for the label. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: fontSize │ │ │ │ │ - * {String} The font size for the label. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: fontWeight │ │ │ │ │ - * {String} The font weight for the label. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: fontStyle │ │ │ │ │ - * {String} The font style for the label. │ │ │ │ │ - * │ │ │ │ │ - * No default set here. Use OpenLayers.Renderer.defaultRenderer for defaults. │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Symbolizer.Text │ │ │ │ │ - * Create a symbolizer for rendering text labels. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} An object containing properties to be set on the │ │ │ │ │ - * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ - * construction. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * A new text symbolizer. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(config) { │ │ │ │ │ - OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Symbolizer.Text" │ │ │ │ │ - │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Symbolizer/Raster.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/Symbolizer.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Symbolizer.Raster │ │ │ │ │ - * A symbolizer used to render raster images. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Symbolizer.Raster = OpenLayers.Class(OpenLayers.Symbolizer, { │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Symbolizer.Raster │ │ │ │ │ - * Create a symbolizer for rendering rasters. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} An object containing properties to be set on the │ │ │ │ │ - * symbolizer. Any documented symbolizer property can be set at │ │ │ │ │ - * construction. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * A new raster symbolizer. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(config) { │ │ │ │ │ - OpenLayers.Symbolizer.prototype.initialize.apply(this, arguments); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Symbolizer.Raster" │ │ │ │ │ - │ │ │ │ │ -}); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Style2.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - * @requires OpenLayers/Rule.js │ │ │ │ │ - * @requires OpenLayers/Symbolizer/Point.js │ │ │ │ │ - * @requires OpenLayers/Symbolizer/Line.js │ │ │ │ │ - * @requires OpenLayers/Symbolizer/Polygon.js │ │ │ │ │ - * @requires OpenLayers/Symbolizer/Text.js │ │ │ │ │ - * @requires OpenLayers/Symbolizer/Raster.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Style2 │ │ │ │ │ - * This class represents a collection of rules for rendering features. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Style2 = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: id │ │ │ │ │ - * {String} A unique id for this session. │ │ │ │ │ - */ │ │ │ │ │ - id: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: name │ │ │ │ │ - * {String} Style identifier. │ │ │ │ │ - */ │ │ │ │ │ - name: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: title │ │ │ │ │ - * {String} Title of this style. │ │ │ │ │ - */ │ │ │ │ │ - title: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: description │ │ │ │ │ - * {String} Description of this style. │ │ │ │ │ - */ │ │ │ │ │ - description: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: layerName │ │ │ │ │ - * {} Name of the layer that this style belongs to, usually │ │ │ │ │ - * according to the NamedLayer attribute of an SLD document. │ │ │ │ │ - */ │ │ │ │ │ - layerName: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: isDefault │ │ │ │ │ - * {Boolean} │ │ │ │ │ - */ │ │ │ │ │ - isDefault: false, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: rules │ │ │ │ │ - * {Array()} Collection of rendering rules. │ │ │ │ │ - */ │ │ │ │ │ - rules: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Style2 │ │ │ │ │ - * Creates a style representing a collection of rendering rules. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * config - {Object} An object containing properties to be set on the │ │ │ │ │ - * style. Any documented properties may be set at construction. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} A new style object. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(config) { │ │ │ │ │ - OpenLayers.Util.extend(this, config); │ │ │ │ │ - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); │ │ │ │ │ + this.div.style.border = width + "px solid " + color; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: destroy │ │ │ │ │ - * nullify references to prevent circular references and memory leaks │ │ │ │ │ - */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - for (var i = 0, len = this.rules.length; i < len; i++) { │ │ │ │ │ - this.rules[i].destroy(); │ │ │ │ │ - } │ │ │ │ │ - delete this.rules; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: clone │ │ │ │ │ - * Clones this style. │ │ │ │ │ + * Method: draw │ │ │ │ │ * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} Clone of this style. │ │ │ │ │ - */ │ │ │ │ │ - clone: function() { │ │ │ │ │ - var config = OpenLayers.Util.extend({}, this); │ │ │ │ │ - // clone rules │ │ │ │ │ - if (this.rules) { │ │ │ │ │ - config.rules = []; │ │ │ │ │ - for (var i = 0, len = this.rules.length; i < len; ++i) { │ │ │ │ │ - config.rules.push(this.rules[i].clone()); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return new OpenLayers.Style2(config); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Style2" │ │ │ │ │ -}); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Spherical.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/SingleFile.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Namespace: Spherical │ │ │ │ │ - * The OpenLayers.Spherical namespace includes utility functions for │ │ │ │ │ - * calculations on the basis of a spherical earth (ignoring ellipsoidal │ │ │ │ │ - * effects), which is accurate enough for most purposes. │ │ │ │ │ - * │ │ │ │ │ - * Relevant links: │ │ │ │ │ - * * http://www.movable-type.co.uk/scripts/latlong.html │ │ │ │ │ - * * http://code.google.com/apis/maps/documentation/javascript/reference.html#spherical │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Spherical = OpenLayers.Spherical || {}; │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Spherical.DEFAULT_RADIUS = 6378137; │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * APIFunction: computeDistanceBetween │ │ │ │ │ - * Computes the distance between two LonLats. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * from - {} or {Object} Starting point. A LonLat or │ │ │ │ │ - * a JavaScript literal with lon lat properties. │ │ │ │ │ - * to - {} or {Object} Ending point. A LonLat or a │ │ │ │ │ - * JavaScript literal with lon lat properties. │ │ │ │ │ - * radius - {Float} The radius. Optional. Defaults to 6378137 meters. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Float} The distance in meters. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Spherical.computeDistanceBetween = function(from, to, radius) { │ │ │ │ │ - var R = radius || OpenLayers.Spherical.DEFAULT_RADIUS; │ │ │ │ │ - var sinHalfDeltaLon = Math.sin(Math.PI * (to.lon - from.lon) / 360); │ │ │ │ │ - var sinHalfDeltaLat = Math.sin(Math.PI * (to.lat - from.lat) / 360); │ │ │ │ │ - var a = sinHalfDeltaLat * sinHalfDeltaLat + │ │ │ │ │ - sinHalfDeltaLon * sinHalfDeltaLon * Math.cos(Math.PI * from.lat / 180) * Math.cos(Math.PI * to.lat / 180); │ │ │ │ │ - return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); │ │ │ │ │ -}; │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * APIFunction: computeHeading │ │ │ │ │ - * Computes the heading from one LonLat to another LonLat. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * from - {} or {Object} Starting point. A LonLat or │ │ │ │ │ - * a JavaScript literal with lon lat properties. │ │ │ │ │ - * to - {} or {Object} Ending point. A LonLat or a │ │ │ │ │ - * JavaScript literal with lon lat properties. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Float} The heading in degrees. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Spherical.computeHeading = function(from, to) { │ │ │ │ │ - var y = Math.sin(Math.PI * (from.lon - to.lon) / 180) * Math.cos(Math.PI * to.lat / 180); │ │ │ │ │ - var x = Math.cos(Math.PI * from.lat / 180) * Math.sin(Math.PI * to.lat / 180) - │ │ │ │ │ - Math.sin(Math.PI * from.lat / 180) * Math.cos(Math.PI * to.lat / 180) * Math.cos(Math.PI * (from.lon - to.lon) / 180); │ │ │ │ │ - return 180 * Math.atan2(y, x) / Math.PI; │ │ │ │ │ -}; │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Protocol.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Protocol │ │ │ │ │ - * Abstract vector layer protocol class. Not to be instantiated directly. Use │ │ │ │ │ - * one of the protocol subclasses instead. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Protocol = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: format │ │ │ │ │ - * {} The format used by this protocol. │ │ │ │ │ - */ │ │ │ │ │ - format: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: options │ │ │ │ │ - * {Object} Any options sent to the constructor. │ │ │ │ │ - */ │ │ │ │ │ - options: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: autoDestroy │ │ │ │ │ - * {Boolean} The creator of the protocol can set autoDestroy to false │ │ │ │ │ - * to fully control when the protocol is destroyed. Defaults to │ │ │ │ │ - * true. │ │ │ │ │ - */ │ │ │ │ │ - autoDestroy: true, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: defaultFilter │ │ │ │ │ - * {} Optional default filter to read requests │ │ │ │ │ - */ │ │ │ │ │ - defaultFilter: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Protocol │ │ │ │ │ - * Abstract class for vector protocols. Create instances of a subclass. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} Optional object whose properties will be set on the │ │ │ │ │ - * instance. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(options) { │ │ │ │ │ - options = options || {}; │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - this.options = options; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: mergeWithDefaultFilter │ │ │ │ │ - * Merge filter passed to the read method with the default one │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * filter - {} │ │ │ │ │ - */ │ │ │ │ │ - mergeWithDefaultFilter: function(filter) { │ │ │ │ │ - var merged; │ │ │ │ │ - if (filter && this.defaultFilter) { │ │ │ │ │ - merged = new OpenLayers.Filter.Logical({ │ │ │ │ │ - type: OpenLayers.Filter.Logical.AND, │ │ │ │ │ - filters: [this.defaultFilter, filter] │ │ │ │ │ - }); │ │ │ │ │ - } else { │ │ │ │ │ - merged = filter || this.defaultFilter || undefined; │ │ │ │ │ - } │ │ │ │ │ - return merged; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: destroy │ │ │ │ │ - * Clean up the protocol. │ │ │ │ │ - */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - this.options = null; │ │ │ │ │ - this.format = null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: read │ │ │ │ │ - * Construct a request for reading new features. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} Optional object for configuring the request. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} An │ │ │ │ │ - * object, the same object will be passed to the callback function passed │ │ │ │ │ - * if one exists in the options object. │ │ │ │ │ - */ │ │ │ │ │ - read: function(options) { │ │ │ │ │ - options = options || {}; │ │ │ │ │ - options.filter = this.mergeWithDefaultFilter(options.filter); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: create │ │ │ │ │ - * Construct a request for writing newly created features. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * features - {Array({})} or │ │ │ │ │ - * {} │ │ │ │ │ - * options - {Object} Optional object for configuring the request. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} An │ │ │ │ │ - * object, the same object will be passed to the callback function passed │ │ │ │ │ - * if one exists in the options object. │ │ │ │ │ - */ │ │ │ │ │ - create: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: update │ │ │ │ │ - * Construct a request updating modified features. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * features - {Array({})} or │ │ │ │ │ - * {} │ │ │ │ │ - * options - {Object} Optional object for configuring the request. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} An │ │ │ │ │ - * object, the same object will be passed to the callback function passed │ │ │ │ │ - * if one exists in the options object. │ │ │ │ │ - */ │ │ │ │ │ - update: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: delete │ │ │ │ │ - * Construct a request deleting a removed feature. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * feature - {} │ │ │ │ │ - * options - {Object} Optional object for configuring the request. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} An │ │ │ │ │ - * object, the same object will be passed to the callback function passed │ │ │ │ │ - * if one exists in the options object. │ │ │ │ │ - */ │ │ │ │ │ - "delete": function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: commit │ │ │ │ │ - * Go over the features and for each take action │ │ │ │ │ - * based on the feature state. Possible actions are create, │ │ │ │ │ - * update and delete. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * features - {Array({})} │ │ │ │ │ - * options - {Object} Object whose possible keys are "create", "update", │ │ │ │ │ - * "delete", "callback" and "scope", the values referenced by the │ │ │ │ │ - * first three are objects as passed to the "create", "update", and │ │ │ │ │ - * "delete" methods, the value referenced by the "callback" key is │ │ │ │ │ - * a function which is called when the commit operation is complete │ │ │ │ │ - * using the scope referenced by the "scope" key. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Array({})} An array of │ │ │ │ │ - * objects. │ │ │ │ │ - */ │ │ │ │ │ - commit: function() {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: abort │ │ │ │ │ - * Abort an ongoing request. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * response - {} │ │ │ │ │ - */ │ │ │ │ │ - abort: function(response) {}, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: createCallback │ │ │ │ │ - * Returns a function that applies the given public method with resp and │ │ │ │ │ - * options arguments. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * method - {Function} The method to be applied by the callback. │ │ │ │ │ - * response - {} The protocol response object. │ │ │ │ │ - * options - {Object} Options sent to the protocol method │ │ │ │ │ - */ │ │ │ │ │ - createCallback: function(method, response, options) { │ │ │ │ │ - return OpenLayers.Function.bind(function() { │ │ │ │ │ - method.apply(this, [response, options]); │ │ │ │ │ - }, this); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Protocol" │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Protocol.Response │ │ │ │ │ - * Protocols return Response objects to their users. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Protocol.Response = OpenLayers.Class({ │ │ │ │ │ - /** │ │ │ │ │ - * Property: code │ │ │ │ │ - * {Number} - OpenLayers.Protocol.Response.SUCCESS or │ │ │ │ │ - * OpenLayers.Protocol.Response.FAILURE │ │ │ │ │ - */ │ │ │ │ │ - code: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: requestType │ │ │ │ │ - * {String} The type of request this response corresponds to. Either │ │ │ │ │ - * "create", "read", "update" or "delete". │ │ │ │ │ - */ │ │ │ │ │ - requestType: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: last │ │ │ │ │ - * {Boolean} - true if this is the last response expected in a commit, │ │ │ │ │ - * false otherwise, defaults to true. │ │ │ │ │ - */ │ │ │ │ │ - last: true, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: features │ │ │ │ │ - * {Array({})} or {} │ │ │ │ │ - * The features returned in the response by the server. Depending on the │ │ │ │ │ - * protocol's read payload, either features or data will be populated. │ │ │ │ │ - */ │ │ │ │ │ - features: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: data │ │ │ │ │ - * {Object} │ │ │ │ │ - * The data returned in the response by the server. Depending on the │ │ │ │ │ - * protocol's read payload, either features or data will be populated. │ │ │ │ │ - */ │ │ │ │ │ - data: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: reqFeatures │ │ │ │ │ - * {Array({})} or {} │ │ │ │ │ - * The features provided by the user and placed in the request by the │ │ │ │ │ - * protocol. │ │ │ │ │ - */ │ │ │ │ │ - reqFeatures: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: priv │ │ │ │ │ - */ │ │ │ │ │ - priv: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: error │ │ │ │ │ - * {Object} The error object in case a service exception was encountered. │ │ │ │ │ - */ │ │ │ │ │ - error: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Protocol.Response │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} Optional object whose properties will be set on the │ │ │ │ │ - * instance. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(options) { │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: success │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} - true on success, false otherwise │ │ │ │ │ - */ │ │ │ │ │ - success: function() { │ │ │ │ │ - return this.code > 0; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Protocol.Response" │ │ │ │ │ -}); │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Protocol.Response.SUCCESS = 1; │ │ │ │ │ -OpenLayers.Protocol.Response.FAILURE = 0; │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Strategy.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.Strategy │ │ │ │ │ - * Abstract vector layer strategy class. Not to be instantiated directly. Use │ │ │ │ │ - * one of the strategy subclasses instead. │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Strategy = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: layer │ │ │ │ │ - * {} The layer this strategy belongs to. │ │ │ │ │ - */ │ │ │ │ │ - layer: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: options │ │ │ │ │ - * {Object} Any options sent to the constructor. │ │ │ │ │ - */ │ │ │ │ │ - options: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: active │ │ │ │ │ - * {Boolean} The control is active. │ │ │ │ │ - */ │ │ │ │ │ - active: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: autoActivate │ │ │ │ │ - * {Boolean} The creator of the strategy can set autoActivate to false │ │ │ │ │ - * to fully control when the protocol is activated and deactivated. │ │ │ │ │ - * Defaults to true. │ │ │ │ │ - */ │ │ │ │ │ - autoActivate: true, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: autoDestroy │ │ │ │ │ - * {Boolean} The creator of the strategy can set autoDestroy to false │ │ │ │ │ - * to fully control when the strategy is destroyed. Defaults to │ │ │ │ │ - * true. │ │ │ │ │ - */ │ │ │ │ │ - autoDestroy: true, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Strategy │ │ │ │ │ - * Abstract class for vector strategies. Create instances of a subclass. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} Optional object whose properties will be set on the │ │ │ │ │ - * instance. │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(options) { │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - this.options = options; │ │ │ │ │ - // set the active property here, so that user cannot override it │ │ │ │ │ - this.active = false; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIMethod: destroy │ │ │ │ │ - * Clean up the strategy. │ │ │ │ │ - */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - this.deactivate(); │ │ │ │ │ - this.layer = null; │ │ │ │ │ - this.options = null; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: setLayer │ │ │ │ │ - * Called to set the property. │ │ │ │ │ - * │ │ │ │ │ * Parameters: │ │ │ │ │ - * layer - {} │ │ │ │ │ - */ │ │ │ │ │ - setLayer: function(layer) { │ │ │ │ │ - this.layer = layer; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: activate │ │ │ │ │ - * Activate the strategy. Register any listeners, do appropriate setup. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} True if the strategy was successfully activated or false if │ │ │ │ │ - * the strategy was already active. │ │ │ │ │ - */ │ │ │ │ │ - activate: function() { │ │ │ │ │ - if (!this.active) { │ │ │ │ │ - this.active = true; │ │ │ │ │ - return true; │ │ │ │ │ - } │ │ │ │ │ - return false; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: deactivate │ │ │ │ │ - * Deactivate the strategy. Unregister any listeners, do appropriate │ │ │ │ │ - * tear-down. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Boolean} True if the strategy was successfully deactivated or false if │ │ │ │ │ - * the strategy was already inactive. │ │ │ │ │ - */ │ │ │ │ │ - deactivate: function() { │ │ │ │ │ - if (this.active) { │ │ │ │ │ - this.active = false; │ │ │ │ │ - return true; │ │ │ │ │ - } │ │ │ │ │ - return false; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - CLASS_NAME: "OpenLayers.Strategy" │ │ │ │ │ -}); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/StyleMap.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - * @requires OpenLayers/Style.js │ │ │ │ │ - * @requires OpenLayers/Feature/Vector.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Class: OpenLayers.StyleMap │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.StyleMap = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: styles │ │ │ │ │ - * {Object} Hash of {}, keyed by names of well known │ │ │ │ │ - * rendering intents (e.g. "default", "temporary", "select", "delete"). │ │ │ │ │ - */ │ │ │ │ │ - styles: null, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: extendDefault │ │ │ │ │ - * {Boolean} if true, every render intent will extend the symbolizers │ │ │ │ │ - * specified for the "default" intent at rendering time. Otherwise, every │ │ │ │ │ - * rendering intent will be treated as a completely independent style. │ │ │ │ │ - */ │ │ │ │ │ - extendDefault: true, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.StyleMap │ │ │ │ │ + * px - {} │ │ │ │ │ + * sz - {} │ │ │ │ │ * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * style - {Object} Optional. Either a style hash, or a style object, or │ │ │ │ │ - * a hash of style objects (style hashes) keyed by rendering │ │ │ │ │ - * intent. If just one style hash or style object is passed, │ │ │ │ │ - * this will be used for all known render intents (default, │ │ │ │ │ - * select, temporary) │ │ │ │ │ - * options - {Object} optional hash of additional options for this │ │ │ │ │ - * instance │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(style, options) { │ │ │ │ │ - this.styles = { │ │ │ │ │ - "default": new OpenLayers.Style( │ │ │ │ │ - OpenLayers.Feature.Vector.style["default"]), │ │ │ │ │ - "select": new OpenLayers.Style( │ │ │ │ │ - OpenLayers.Feature.Vector.style["select"]), │ │ │ │ │ - "temporary": new OpenLayers.Style( │ │ │ │ │ - OpenLayers.Feature.Vector.style["temporary"]), │ │ │ │ │ - "delete": new OpenLayers.Style( │ │ │ │ │ - OpenLayers.Feature.Vector.style["delete"]) │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - // take whatever the user passed as style parameter and convert it │ │ │ │ │ - // into parts of stylemap. │ │ │ │ │ - if (style instanceof OpenLayers.Style) { │ │ │ │ │ - // user passed a style object │ │ │ │ │ - this.styles["default"] = style; │ │ │ │ │ - this.styles["select"] = style; │ │ │ │ │ - this.styles["temporary"] = style; │ │ │ │ │ - this.styles["delete"] = style; │ │ │ │ │ - } else if (typeof style == "object") { │ │ │ │ │ - for (var key in style) { │ │ │ │ │ - if (style[key] instanceof OpenLayers.Style) { │ │ │ │ │ - // user passed a hash of style objects │ │ │ │ │ - this.styles[key] = style[key]; │ │ │ │ │ - } else if (typeof style[key] == "object") { │ │ │ │ │ - // user passsed a hash of style hashes │ │ │ │ │ - this.styles[key] = new OpenLayers.Style(style[key]); │ │ │ │ │ - } else { │ │ │ │ │ - // user passed a style hash (i.e. symbolizer) │ │ │ │ │ - this.styles["default"] = new OpenLayers.Style(style); │ │ │ │ │ - this.styles["select"] = new OpenLayers.Style(style); │ │ │ │ │ - this.styles["temporary"] = new OpenLayers.Style(style); │ │ │ │ │ - this.styles["delete"] = new OpenLayers.Style(style); │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: destroy │ │ │ │ │ + * Returns: │ │ │ │ │ + * {DOMElement} A new DOM Image with this marker's icon set at the │ │ │ │ │ + * location passed-in │ │ │ │ │ */ │ │ │ │ │ - destroy: function() { │ │ │ │ │ - for (var key in this.styles) { │ │ │ │ │ - this.styles[key].destroy(); │ │ │ │ │ - } │ │ │ │ │ - this.styles = null; │ │ │ │ │ + draw: function(px, sz) { │ │ │ │ │ + OpenLayers.Util.modifyDOMElement(this.div, null, px, sz); │ │ │ │ │ + return this.div; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: createSymbolizer │ │ │ │ │ - * Creates the symbolizer for a feature for a render intent. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * feature - {} The feature to evaluate the rules │ │ │ │ │ - * of the intended style against. │ │ │ │ │ - * intent - {String} The intent determines the symbolizer that will be │ │ │ │ │ - * used to draw the feature. Well known intents are "default" │ │ │ │ │ - * (for just drawing the features), "select" (for selected │ │ │ │ │ - * features) and "temporary" (for drawing features). │ │ │ │ │ + * Method: onScreen │ │ │ │ │ * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} symbolizer hash │ │ │ │ │ + * Rreturn: │ │ │ │ │ + * {Boolean} Whether or not the marker is currently visible on screen. │ │ │ │ │ */ │ │ │ │ │ - createSymbolizer: function(feature, intent) { │ │ │ │ │ - if (!feature) { │ │ │ │ │ - feature = new OpenLayers.Feature.Vector(); │ │ │ │ │ - } │ │ │ │ │ - if (!this.styles[intent]) { │ │ │ │ │ - intent = "default"; │ │ │ │ │ - } │ │ │ │ │ - feature.renderIntent = intent; │ │ │ │ │ - var defaultSymbolizer = {}; │ │ │ │ │ - if (this.extendDefault && intent != "default") { │ │ │ │ │ - defaultSymbolizer = this.styles["default"].createSymbolizer(feature); │ │ │ │ │ + onScreen: function() { │ │ │ │ │ + var onScreen = false; │ │ │ │ │ + if (this.map) { │ │ │ │ │ + var screenBounds = this.map.getExtent(); │ │ │ │ │ + onScreen = screenBounds.containsBounds(this.bounds, true, true); │ │ │ │ │ } │ │ │ │ │ - return OpenLayers.Util.extend(defaultSymbolizer, │ │ │ │ │ - this.styles[intent].createSymbolizer(feature)); │ │ │ │ │ + return onScreen; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: addUniqueValueRules │ │ │ │ │ - * Convenience method to create comparison rules for unique values of a │ │ │ │ │ - * property. The rules will be added to the style object for a specified │ │ │ │ │ - * rendering intent. This method is a shortcut for creating something like │ │ │ │ │ - * the "unique value legends" familiar from well known desktop GIS systems │ │ │ │ │ + * Method: display │ │ │ │ │ + * Hide or show the icon │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * renderIntent - {String} rendering intent to add the rules to │ │ │ │ │ - * property - {String} values of feature attributes to create the │ │ │ │ │ - * rules for │ │ │ │ │ - * symbolizers - {Object} Hash of symbolizers, keyed by the desired │ │ │ │ │ - * property values │ │ │ │ │ - * context - {Object} An optional object with properties that │ │ │ │ │ - * symbolizers' property values should be evaluated │ │ │ │ │ - * against. If no context is specified, feature.attributes │ │ │ │ │ - * will be used │ │ │ │ │ + * display - {Boolean} │ │ │ │ │ */ │ │ │ │ │ - addUniqueValueRules: function(renderIntent, property, symbolizers, context) { │ │ │ │ │ - var rules = []; │ │ │ │ │ - for (var value in symbolizers) { │ │ │ │ │ - rules.push(new OpenLayers.Rule({ │ │ │ │ │ - symbolizer: symbolizers[value], │ │ │ │ │ - context: context, │ │ │ │ │ - filter: new OpenLayers.Filter.Comparison({ │ │ │ │ │ - type: OpenLayers.Filter.Comparison.EQUAL_TO, │ │ │ │ │ - property: property, │ │ │ │ │ - value: value │ │ │ │ │ - }) │ │ │ │ │ - })); │ │ │ │ │ - } │ │ │ │ │ - this.styles[renderIntent].addRules(rules); │ │ │ │ │ + display: function(display) { │ │ │ │ │ + this.div.style.display = (display) ? "" : "none"; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.StyleMap" │ │ │ │ │ + CLASS_NAME: "OpenLayers.Marker.Box" │ │ │ │ │ }); │ │ │ │ │ -/* ====================================================================== │ │ │ │ │ - OpenLayers/Kinetic.js │ │ │ │ │ - ====================================================================== */ │ │ │ │ │ - │ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ - * full text of the license. */ │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js │ │ │ │ │ - * @requires OpenLayers/Animation.js │ │ │ │ │ - */ │ │ │ │ │ - │ │ │ │ │ -OpenLayers.Kinetic = OpenLayers.Class({ │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: threshold │ │ │ │ │ - * In most cases changing the threshold isn't needed. │ │ │ │ │ - * In px/ms, default to 0. │ │ │ │ │ - */ │ │ │ │ │ - threshold: 0, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: deceleration │ │ │ │ │ - * {Float} the deseleration in px/ms², default to 0.0035. │ │ │ │ │ - */ │ │ │ │ │ - deceleration: 0.0035, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: nbPoints │ │ │ │ │ - * {Integer} the number of points we use to calculate the kinetic │ │ │ │ │ - * initial values. │ │ │ │ │ - */ │ │ │ │ │ - nbPoints: 100, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: delay │ │ │ │ │ - * {Float} time to consider to calculate the kinetic initial values. │ │ │ │ │ - * In ms, default to 200. │ │ │ │ │ - */ │ │ │ │ │ - delay: 200, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: points │ │ │ │ │ - * List of points use to calculate the kinetic initial values. │ │ │ │ │ - */ │ │ │ │ │ - points: undefined, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Property: timerId │ │ │ │ │ - * ID of the timer. │ │ │ │ │ - */ │ │ │ │ │ - timerId: undefined, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Constructor: OpenLayers.Kinetic │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} │ │ │ │ │ - */ │ │ │ │ │ - initialize: function(options) { │ │ │ │ │ - OpenLayers.Util.extend(this, options); │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: begin │ │ │ │ │ - * Begins the dragging. │ │ │ │ │ - */ │ │ │ │ │ - begin: function() { │ │ │ │ │ - OpenLayers.Animation.stop(this.timerId); │ │ │ │ │ - this.timerId = undefined; │ │ │ │ │ - this.points = []; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: update │ │ │ │ │ - * Updates during the dragging. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * xy - {} The new position. │ │ │ │ │ - */ │ │ │ │ │ - update: function(xy) { │ │ │ │ │ - this.points.unshift({ │ │ │ │ │ - xy: xy, │ │ │ │ │ - tick: new Date().getTime() │ │ │ │ │ - }); │ │ │ │ │ - if (this.points.length > this.nbPoints) { │ │ │ │ │ - this.points.pop(); │ │ │ │ │ - } │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: end │ │ │ │ │ - * Ends the dragging, start the kinetic. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * xy - {} The last position. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} An object with two properties: "speed", and "theta". The │ │ │ │ │ - * "speed" and "theta" values are to be passed to the move │ │ │ │ │ - * function when starting the animation. │ │ │ │ │ - */ │ │ │ │ │ - end: function(xy) { │ │ │ │ │ - var last, now = new Date().getTime(); │ │ │ │ │ - for (var i = 0, l = this.points.length, point; i < l; i++) { │ │ │ │ │ - point = this.points[i]; │ │ │ │ │ - if (now - point.tick > this.delay) { │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ - last = point; │ │ │ │ │ - } │ │ │ │ │ - if (!last) { │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - var time = new Date().getTime() - last.tick; │ │ │ │ │ - var dist = Math.sqrt(Math.pow(xy.x - last.xy.x, 2) + │ │ │ │ │ - Math.pow(xy.y - last.xy.y, 2)); │ │ │ │ │ - var speed = dist / time; │ │ │ │ │ - if (speed == 0 || speed < this.threshold) { │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - var theta = Math.asin((xy.y - last.xy.y) / dist); │ │ │ │ │ - if (last.xy.x <= xy.x) { │ │ │ │ │ - theta = Math.PI - theta; │ │ │ │ │ - } │ │ │ │ │ - return { │ │ │ │ │ - speed: speed, │ │ │ │ │ - theta: theta │ │ │ │ │ - }; │ │ │ │ │ - }, │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * Method: move │ │ │ │ │ - * Launch the kinetic move pan. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * info - {Object} An object with two properties, "speed", and "theta". │ │ │ │ │ - * These values are those returned from the "end" call. │ │ │ │ │ - * callback - {Function} Function called on every step of the animation, │ │ │ │ │ - * receives x, y (values to pan), end (is the last point). │ │ │ │ │ - */ │ │ │ │ │ - move: function(info, callback) { │ │ │ │ │ - var v0 = info.speed; │ │ │ │ │ - var fx = Math.cos(info.theta); │ │ │ │ │ - var fy = -Math.sin(info.theta); │ │ │ │ │ - │ │ │ │ │ - var initialTime = new Date().getTime(); │ │ │ │ │ - │ │ │ │ │ - var lastX = 0; │ │ │ │ │ - var lastY = 0; │ │ │ │ │ - │ │ │ │ │ - var timerCallback = function() { │ │ │ │ │ - if (this.timerId == null) { │ │ │ │ │ - return; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - var t = new Date().getTime() - initialTime; │ │ │ │ │ - │ │ │ │ │ - var p = (-this.deceleration * Math.pow(t, 2)) / 2.0 + v0 * t; │ │ │ │ │ - var x = p * fx; │ │ │ │ │ - var y = p * fy; │ │ │ │ │ - │ │ │ │ │ - var args = {}; │ │ │ │ │ - args.end = false; │ │ │ │ │ - var v = -this.deceleration * t + v0; │ │ │ │ │ - │ │ │ │ │ - if (v <= 0) { │ │ │ │ │ - OpenLayers.Animation.stop(this.timerId); │ │ │ │ │ - this.timerId = null; │ │ │ │ │ - args.end = true; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - args.x = x - lastX; │ │ │ │ │ - args.y = y - lastY; │ │ │ │ │ - lastX = x; │ │ │ │ │ - lastY = y; │ │ │ │ │ - callback(args.x, args.y, args.end); │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - this.timerId = OpenLayers.Animation.start( │ │ │ │ │ - OpenLayers.Function.bind(timerCallback, this) │ │ │ │ │ - ); │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Kinetic" │ │ │ │ │ -}); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ OpenLayers/Events/featureclick.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ @@ -34175,11974 +33642,9525 @@ │ │ │ │ │ } │ │ │ │ │ } │ │ │ │ │ return propagate; │ │ │ │ │ } │ │ │ │ │ │ │ │ │ │ }); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Format/WMSGetFeatureInfo.js │ │ │ │ │ + OpenLayers/Handler/Drag.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/Format/XML.js │ │ │ │ │ + * @requires OpenLayers/Handler.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Format.WMSGetFeatureInfo │ │ │ │ │ - * Class to read GetFeatureInfo responses from Web Mapping Services │ │ │ │ │ + * Class: OpenLayers.Handler.Drag │ │ │ │ │ + * The drag handler is used to deal with sequences of browser events related │ │ │ │ │ + * to dragging. The handler is used by controls that want to know when │ │ │ │ │ + * a drag sequence begins, when a drag is happening, and when it has │ │ │ │ │ + * finished. │ │ │ │ │ + * │ │ │ │ │ + * Controls that use the drag handler typically construct it with callbacks │ │ │ │ │ + * for 'down', 'move', and 'done'. Callbacks for these keys are called │ │ │ │ │ + * when the drag begins, with each move, and when the drag is done. In │ │ │ │ │ + * addition, controls can have callbacks keyed to 'up' and 'out' if they │ │ │ │ │ + * care to differentiate between the types of events that correspond with │ │ │ │ │ + * the end of a drag sequence. If no drag actually occurs (no mouse move) │ │ │ │ │ + * the 'down' and 'up' callbacks will be called, but not the 'done' │ │ │ │ │ + * callback. │ │ │ │ │ + * │ │ │ │ │ + * Create a new drag handler with the constructor. │ │ │ │ │ * │ │ │ │ │ * Inherits from: │ │ │ │ │ - * - │ │ │ │ │ + * - │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Format.WMSGetFeatureInfo = OpenLayers.Class(OpenLayers.Format.XML, { │ │ │ │ │ +OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: started │ │ │ │ │ + * {Boolean} When a mousedown or touchstart event is received, we want to │ │ │ │ │ + * record it, but not set 'dragging' until the mouse moves after starting. │ │ │ │ │ + */ │ │ │ │ │ + started: false, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: layerIdentifier │ │ │ │ │ - * {String} All xml nodes containing this search criteria will populate an │ │ │ │ │ - * internal array of layer nodes. │ │ │ │ │ + * Property: stopDown │ │ │ │ │ + * {Boolean} Stop propagation of mousedown events from getting to listeners │ │ │ │ │ + * on the same element. Default is true. │ │ │ │ │ */ │ │ │ │ │ - layerIdentifier: '_layer', │ │ │ │ │ + stopDown: true, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: dragging │ │ │ │ │ + * {Boolean} │ │ │ │ │ + */ │ │ │ │ │ + dragging: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: last │ │ │ │ │ + * {} The last pixel location of the drag. │ │ │ │ │ + */ │ │ │ │ │ + last: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: start │ │ │ │ │ + * {} The first pixel location of the drag. │ │ │ │ │ + */ │ │ │ │ │ + start: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: featureIdentifier │ │ │ │ │ - * {String} All xml nodes containing this search criteria will populate an │ │ │ │ │ - * internal array of feature nodes for each layer node found. │ │ │ │ │ + * Property: lastMoveEvt │ │ │ │ │ + * {Object} The last mousemove event that occurred. Used to │ │ │ │ │ + * position the map correctly when our "delay drag" │ │ │ │ │ + * timeout expired. │ │ │ │ │ */ │ │ │ │ │ - featureIdentifier: '_feature', │ │ │ │ │ + lastMoveEvt: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: regExes │ │ │ │ │ - * Compiled regular expressions for manipulating strings. │ │ │ │ │ + * Property: oldOnselectstart │ │ │ │ │ + * {Function} │ │ │ │ │ */ │ │ │ │ │ - regExes: { │ │ │ │ │ - trimSpace: (/^\s*|\s*$/g), │ │ │ │ │ - removeSpace: (/\s*/g), │ │ │ │ │ - splitSpace: (/\s+/), │ │ │ │ │ - trimComma: (/\s*,\s*/g) │ │ │ │ │ - }, │ │ │ │ │ + oldOnselectstart: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: gmlFormat │ │ │ │ │ - * {} internal GML format for parsing geometries │ │ │ │ │ - * in msGMLOutput │ │ │ │ │ + * Property: interval │ │ │ │ │ + * {Integer} In order to increase performance, an interval (in │ │ │ │ │ + * milliseconds) can be set to reduce the number of drag events │ │ │ │ │ + * called. If set, a new drag event will not be set until the │ │ │ │ │ + * interval has passed. │ │ │ │ │ + * Defaults to 0, meaning no interval. │ │ │ │ │ */ │ │ │ │ │ - gmlFormat: null, │ │ │ │ │ + interval: 0, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Format.WMSGetFeatureInfo │ │ │ │ │ - * Create a new parser for WMS GetFeatureInfo responses │ │ │ │ │ - * │ │ │ │ │ + * Property: timeoutId │ │ │ │ │ + * {String} The id of the timeout used for the mousedown interval. │ │ │ │ │ + * This is "private", and should be left alone. │ │ │ │ │ + */ │ │ │ │ │ + timeoutId: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: documentDrag │ │ │ │ │ + * {Boolean} If set to true, the handler will also handle mouse moves when │ │ │ │ │ + * the cursor has moved out of the map viewport. Default is false. │ │ │ │ │ + */ │ │ │ │ │ + documentDrag: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: documentEvents │ │ │ │ │ + * {Boolean} Are we currently observing document events? │ │ │ │ │ + */ │ │ │ │ │ + documentEvents: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Handler.Drag │ │ │ │ │ + * Returns OpenLayers.Handler.Drag │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * options - {Object} An optional object whose properties will be set on │ │ │ │ │ - * this instance. │ │ │ │ │ + * control - {} The control that is making use of │ │ │ │ │ + * this handler. If a handler is being used without a control, the │ │ │ │ │ + * handlers setMap method must be overridden to deal properly with │ │ │ │ │ + * the map. │ │ │ │ │ + * callbacks - {Object} An object containing a single function to be │ │ │ │ │ + * called when the drag operation is finished. The callback should │ │ │ │ │ + * expect to recieve a single argument, the pixel location of the event. │ │ │ │ │ + * Callbacks for 'move' and 'done' are supported. You can also speficy │ │ │ │ │ + * callbacks for 'down', 'up', and 'out' to respond to those events. │ │ │ │ │ + * options - {Object} │ │ │ │ │ */ │ │ │ │ │ + initialize: function(control, callbacks, options) { │ │ │ │ │ + OpenLayers.Handler.prototype.initialize.apply(this, arguments); │ │ │ │ │ + │ │ │ │ │ + if (this.documentDrag === true) { │ │ │ │ │ + var me = this; │ │ │ │ │ + this._docMove = function(evt) { │ │ │ │ │ + me.mousemove({ │ │ │ │ │ + xy: { │ │ │ │ │ + x: evt.clientX, │ │ │ │ │ + y: evt.clientY │ │ │ │ │ + }, │ │ │ │ │ + element: document │ │ │ │ │ + }); │ │ │ │ │ + }; │ │ │ │ │ + this._docUp = function(evt) { │ │ │ │ │ + me.mouseup({ │ │ │ │ │ + xy: { │ │ │ │ │ + x: evt.clientX, │ │ │ │ │ + y: evt.clientY │ │ │ │ │ + } │ │ │ │ │ + }); │ │ │ │ │ + }; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: read │ │ │ │ │ - * Read WMS GetFeatureInfo data from a string, and return an array of features │ │ │ │ │ + * Method: dragstart │ │ │ │ │ + * This private method is factorized from mousedown and touchstart methods │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * data - {String} or {DOMElement} data to read/parse. │ │ │ │ │ + * evt - {Event} The event │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Array()} An array of features. │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ */ │ │ │ │ │ - read: function(data) { │ │ │ │ │ - var result; │ │ │ │ │ - if (typeof data == "string") { │ │ │ │ │ - data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); │ │ │ │ │ - } │ │ │ │ │ - var root = data.documentElement; │ │ │ │ │ - if (root) { │ │ │ │ │ - var scope = this; │ │ │ │ │ - var read = this["read_" + root.nodeName]; │ │ │ │ │ - if (read) { │ │ │ │ │ - result = read.call(this, root); │ │ │ │ │ - } else { │ │ │ │ │ - // fall-back to GML since this is a common output format for WMS │ │ │ │ │ - // GetFeatureInfo responses │ │ │ │ │ - result = new OpenLayers.Format.GML((this.options ? this.options : {})).read(data); │ │ │ │ │ + dragstart: function(evt) { │ │ │ │ │ + var propagate = true; │ │ │ │ │ + this.dragging = false; │ │ │ │ │ + if (this.checkModifiers(evt) && │ │ │ │ │ + (OpenLayers.Event.isLeftClick(evt) || │ │ │ │ │ + OpenLayers.Event.isSingleTouch(evt))) { │ │ │ │ │ + this.started = true; │ │ │ │ │ + this.start = evt.xy; │ │ │ │ │ + this.last = evt.xy; │ │ │ │ │ + OpenLayers.Element.addClass( │ │ │ │ │ + this.map.viewPortDiv, "olDragDown" │ │ │ │ │ + ); │ │ │ │ │ + this.down(evt); │ │ │ │ │ + this.callback("down", [evt.xy]); │ │ │ │ │ + │ │ │ │ │ + // prevent document dragging │ │ │ │ │ + OpenLayers.Event.preventDefault(evt); │ │ │ │ │ + │ │ │ │ │ + if (!this.oldOnselectstart) { │ │ │ │ │ + this.oldOnselectstart = document.onselectstart ? │ │ │ │ │ + document.onselectstart : OpenLayers.Function.True; │ │ │ │ │ } │ │ │ │ │ + document.onselectstart = OpenLayers.Function.False; │ │ │ │ │ + │ │ │ │ │ + propagate = !this.stopDown; │ │ │ │ │ } else { │ │ │ │ │ - result = data; │ │ │ │ │ + this.started = false; │ │ │ │ │ + this.start = null; │ │ │ │ │ + this.last = null; │ │ │ │ │ } │ │ │ │ │ - return result; │ │ │ │ │ + return propagate; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - │ │ │ │ │ /** │ │ │ │ │ - * Method: read_msGMLOutput │ │ │ │ │ - * Parse msGMLOutput nodes. │ │ │ │ │ + * Method: dragmove │ │ │ │ │ + * This private method is factorized from mousemove and touchmove methods │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * data - {DOMElement} │ │ │ │ │ + * evt - {Event} The event │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Array} │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ */ │ │ │ │ │ - read_msGMLOutput: function(data) { │ │ │ │ │ - var response = []; │ │ │ │ │ - var layerNodes = this.getSiblingNodesByTagCriteria(data, │ │ │ │ │ - this.layerIdentifier); │ │ │ │ │ - if (layerNodes) { │ │ │ │ │ - for (var i = 0, len = layerNodes.length; i < len; ++i) { │ │ │ │ │ - var node = layerNodes[i]; │ │ │ │ │ - var layerName = node.nodeName; │ │ │ │ │ - if (node.prefix) { │ │ │ │ │ - layerName = layerName.split(':')[1]; │ │ │ │ │ - } │ │ │ │ │ - var layerName = layerName.replace(this.layerIdentifier, ''); │ │ │ │ │ - var featureNodes = this.getSiblingNodesByTagCriteria(node, │ │ │ │ │ - this.featureIdentifier); │ │ │ │ │ - if (featureNodes) { │ │ │ │ │ - for (var j = 0; j < featureNodes.length; j++) { │ │ │ │ │ - var featureNode = featureNodes[j]; │ │ │ │ │ - var geomInfo = this.parseGeometry(featureNode); │ │ │ │ │ - var attributes = this.parseAttributes(featureNode); │ │ │ │ │ - var feature = new OpenLayers.Feature.Vector(geomInfo.geometry, │ │ │ │ │ - attributes, null); │ │ │ │ │ - feature.bounds = geomInfo.bounds; │ │ │ │ │ - feature.type = layerName; │ │ │ │ │ - response.push(feature); │ │ │ │ │ - } │ │ │ │ │ + dragmove: function(evt) { │ │ │ │ │ + this.lastMoveEvt = evt; │ │ │ │ │ + if (this.started && !this.timeoutId && (evt.xy.x != this.last.x || │ │ │ │ │ + evt.xy.y != this.last.y)) { │ │ │ │ │ + if (this.documentDrag === true && this.documentEvents) { │ │ │ │ │ + if (evt.element === document) { │ │ │ │ │ + this.adjustXY(evt); │ │ │ │ │ + // do setEvent manually because the documentEvents are not │ │ │ │ │ + // registered with the map │ │ │ │ │ + this.setEvent(evt); │ │ │ │ │ + } else { │ │ │ │ │ + this.removeDocumentEvents(); │ │ │ │ │ } │ │ │ │ │ } │ │ │ │ │ + if (this.interval > 0) { │ │ │ │ │ + this.timeoutId = setTimeout( │ │ │ │ │ + OpenLayers.Function.bind(this.removeTimeout, this), │ │ │ │ │ + this.interval); │ │ │ │ │ + } │ │ │ │ │ + this.dragging = true; │ │ │ │ │ + │ │ │ │ │ + this.move(evt); │ │ │ │ │ + this.callback("move", [evt.xy]); │ │ │ │ │ + if (!this.oldOnselectstart) { │ │ │ │ │ + this.oldOnselectstart = document.onselectstart; │ │ │ │ │ + document.onselectstart = OpenLayers.Function.False; │ │ │ │ │ + } │ │ │ │ │ + this.last = evt.xy; │ │ │ │ │ } │ │ │ │ │ - return response; │ │ │ │ │ + return true; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: read_FeatureInfoResponse │ │ │ │ │ - * Parse FeatureInfoResponse nodes. │ │ │ │ │ + * Method: dragend │ │ │ │ │ + * This private method is factorized from mouseup and touchend methods │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * data - {DOMElement} │ │ │ │ │ + * evt - {Event} The event │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Array} │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ */ │ │ │ │ │ - read_FeatureInfoResponse: function(data) { │ │ │ │ │ - var response = []; │ │ │ │ │ - var featureNodes = this.getElementsByTagNameNS(data, '*', │ │ │ │ │ - 'FIELDS'); │ │ │ │ │ + dragend: function(evt) { │ │ │ │ │ + if (this.started) { │ │ │ │ │ + if (this.documentDrag === true && this.documentEvents) { │ │ │ │ │ + this.adjustXY(evt); │ │ │ │ │ + this.removeDocumentEvents(); │ │ │ │ │ + } │ │ │ │ │ + var dragged = (this.start != this.last); │ │ │ │ │ + this.started = false; │ │ │ │ │ + this.dragging = false; │ │ │ │ │ + OpenLayers.Element.removeClass( │ │ │ │ │ + this.map.viewPortDiv, "olDragDown" │ │ │ │ │ + ); │ │ │ │ │ + this.up(evt); │ │ │ │ │ + this.callback("up", [evt.xy]); │ │ │ │ │ + if (dragged) { │ │ │ │ │ + this.callback("done", [evt.xy]); │ │ │ │ │ + } │ │ │ │ │ + document.onselectstart = this.oldOnselectstart; │ │ │ │ │ + } │ │ │ │ │ + return true; │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - for (var i = 0, len = featureNodes.length; i < len; i++) { │ │ │ │ │ - var featureNode = featureNodes[i]; │ │ │ │ │ - var geom = null; │ │ │ │ │ + /** │ │ │ │ │ + * The four methods below (down, move, up, and out) are used by subclasses │ │ │ │ │ + * to do their own processing related to these mouse events. │ │ │ │ │ + */ │ │ │ │ │ │ │ │ │ │ - // attributes can be actual attributes on the FIELDS tag, │ │ │ │ │ - // or FIELD children │ │ │ │ │ - var attributes = {}; │ │ │ │ │ - var j; │ │ │ │ │ - var jlen = featureNode.attributes.length; │ │ │ │ │ - if (jlen > 0) { │ │ │ │ │ - for (j = 0; j < jlen; j++) { │ │ │ │ │ - var attribute = featureNode.attributes[j]; │ │ │ │ │ - attributes[attribute.nodeName] = attribute.nodeValue; │ │ │ │ │ - } │ │ │ │ │ + /** │ │ │ │ │ + * Method: down │ │ │ │ │ + * This method is called during the handling of the mouse down event. │ │ │ │ │ + * Subclasses can do their own processing here. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} The mouse down event │ │ │ │ │ + */ │ │ │ │ │ + down: function(evt) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: move │ │ │ │ │ + * This method is called during the handling of the mouse move event. │ │ │ │ │ + * Subclasses can do their own processing here. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} The mouse move event │ │ │ │ │ + * │ │ │ │ │ + */ │ │ │ │ │ + move: function(evt) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: up │ │ │ │ │ + * This method is called during the handling of the mouse up event. │ │ │ │ │ + * Subclasses can do their own processing here. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} The mouse up event │ │ │ │ │ + */ │ │ │ │ │ + up: function(evt) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: out │ │ │ │ │ + * This method is called during the handling of the mouse out event. │ │ │ │ │ + * Subclasses can do their own processing here. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} The mouse out event │ │ │ │ │ + */ │ │ │ │ │ + out: function(evt) {}, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * The methods below are part of the magic of event handling. Because │ │ │ │ │ + * they are named like browser events, they are registered as listeners │ │ │ │ │ + * for the events they represent. │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: mousedown │ │ │ │ │ + * Handle mousedown events │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ + */ │ │ │ │ │ + mousedown: function(evt) { │ │ │ │ │ + return this.dragstart(evt); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: touchstart │ │ │ │ │ + * Handle touchstart events │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ + */ │ │ │ │ │ + touchstart: function(evt) { │ │ │ │ │ + this.startTouch(); │ │ │ │ │ + return this.dragstart(evt); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: mousemove │ │ │ │ │ + * Handle mousemove events │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ + */ │ │ │ │ │ + mousemove: function(evt) { │ │ │ │ │ + return this.dragmove(evt); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: touchmove │ │ │ │ │ + * Handle touchmove events │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ + */ │ │ │ │ │ + touchmove: function(evt) { │ │ │ │ │ + return this.dragmove(evt); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: removeTimeout │ │ │ │ │ + * Private. Called by mousemove() to remove the drag timeout. │ │ │ │ │ + */ │ │ │ │ │ + removeTimeout: function() { │ │ │ │ │ + this.timeoutId = null; │ │ │ │ │ + // if timeout expires while we're still dragging (mouseup │ │ │ │ │ + // hasn't occurred) then call mousemove to move to the │ │ │ │ │ + // correct position │ │ │ │ │ + if (this.dragging) { │ │ │ │ │ + this.mousemove(this.lastMoveEvt); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: mouseup │ │ │ │ │ + * Handle mouseup events │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ + */ │ │ │ │ │ + mouseup: function(evt) { │ │ │ │ │ + return this.dragend(evt); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: touchend │ │ │ │ │ + * Handle touchend events │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ + */ │ │ │ │ │ + touchend: function(evt) { │ │ │ │ │ + // override evt.xy with last position since touchend does not have │ │ │ │ │ + // any touch position │ │ │ │ │ + evt.xy = this.last; │ │ │ │ │ + return this.dragend(evt); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: mouseout │ │ │ │ │ + * Handle mouseout events │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ + */ │ │ │ │ │ + mouseout: function(evt) { │ │ │ │ │ + if (this.started && OpenLayers.Util.mouseLeft(evt, this.map.viewPortDiv)) { │ │ │ │ │ + if (this.documentDrag === true) { │ │ │ │ │ + this.addDocumentEvents(); │ │ │ │ │ } else { │ │ │ │ │ - var nodes = featureNode.childNodes; │ │ │ │ │ - for (j = 0, jlen = nodes.length; j < jlen; ++j) { │ │ │ │ │ - var node = nodes[j]; │ │ │ │ │ - if (node.nodeType != 3) { │ │ │ │ │ - attributes[node.getAttribute("name")] = │ │ │ │ │ - node.getAttribute("value"); │ │ │ │ │ - } │ │ │ │ │ + var dragged = (this.start != this.last); │ │ │ │ │ + this.started = false; │ │ │ │ │ + this.dragging = false; │ │ │ │ │ + OpenLayers.Element.removeClass( │ │ │ │ │ + this.map.viewPortDiv, "olDragDown" │ │ │ │ │ + ); │ │ │ │ │ + this.out(evt); │ │ │ │ │ + this.callback("out", []); │ │ │ │ │ + if (dragged) { │ │ │ │ │ + this.callback("done", [evt.xy]); │ │ │ │ │ + } │ │ │ │ │ + if (document.onselectstart) { │ │ │ │ │ + document.onselectstart = this.oldOnselectstart; │ │ │ │ │ } │ │ │ │ │ } │ │ │ │ │ + } │ │ │ │ │ + return true; │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - response.push( │ │ │ │ │ - new OpenLayers.Feature.Vector(geom, attributes, null) │ │ │ │ │ + /** │ │ │ │ │ + * Method: click │ │ │ │ │ + * The drag handler captures the click event. If something else registers │ │ │ │ │ + * for clicks on the same element, its listener will not be called │ │ │ │ │ + * after a drag. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * evt - {Event} │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Let the event propagate. │ │ │ │ │ + */ │ │ │ │ │ + click: function(evt) { │ │ │ │ │ + // let the click event propagate only if the mouse moved │ │ │ │ │ + return (this.start == this.last); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: activate │ │ │ │ │ + * Activate the handler. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The handler was successfully activated. │ │ │ │ │ + */ │ │ │ │ │ + activate: function() { │ │ │ │ │ + var activated = false; │ │ │ │ │ + if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) { │ │ │ │ │ + this.dragging = false; │ │ │ │ │ + activated = true; │ │ │ │ │ + } │ │ │ │ │ + return activated; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: deactivate │ │ │ │ │ + * Deactivate the handler. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} The handler was successfully deactivated. │ │ │ │ │ + */ │ │ │ │ │ + deactivate: function() { │ │ │ │ │ + var deactivated = false; │ │ │ │ │ + if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { │ │ │ │ │ + this.started = false; │ │ │ │ │ + this.dragging = false; │ │ │ │ │ + this.start = null; │ │ │ │ │ + this.last = null; │ │ │ │ │ + deactivated = true; │ │ │ │ │ + OpenLayers.Element.removeClass( │ │ │ │ │ + this.map.viewPortDiv, "olDragDown" │ │ │ │ │ ); │ │ │ │ │ } │ │ │ │ │ - return response; │ │ │ │ │ + return deactivated; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: getSiblingNodesByTagCriteria │ │ │ │ │ - * Recursively searches passed xml node and all it's descendant levels for │ │ │ │ │ - * nodes whose tagName contains the passed search string. This returns an │ │ │ │ │ - * array of all sibling nodes which match the criteria from the highest │ │ │ │ │ - * hierarchial level from which a match is found. │ │ │ │ │ + * Method: adjustXY │ │ │ │ │ + * Converts event coordinates that are relative to the document body to │ │ │ │ │ + * ones that are relative to the map viewport. The latter is the default in │ │ │ │ │ + * OpenLayers. │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * node - {DOMElement} An xml node │ │ │ │ │ - * criteria - {String} Search string which will match some part of a tagName │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * Array({DOMElement}) An array of sibling xml nodes │ │ │ │ │ + * evt - {Object} │ │ │ │ │ */ │ │ │ │ │ - getSiblingNodesByTagCriteria: function(node, criteria) { │ │ │ │ │ - var nodes = []; │ │ │ │ │ - var children, tagName, n, matchNodes, child; │ │ │ │ │ - if (node && node.hasChildNodes()) { │ │ │ │ │ - children = node.childNodes; │ │ │ │ │ - n = children.length; │ │ │ │ │ + adjustXY: function(evt) { │ │ │ │ │ + var pos = OpenLayers.Util.pagePosition(this.map.viewPortDiv); │ │ │ │ │ + evt.xy.x -= pos[0]; │ │ │ │ │ + evt.xy.y -= pos[1]; │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - for (var k = 0; k < n; k++) { │ │ │ │ │ - child = children[k]; │ │ │ │ │ - while (child && child.nodeType != 1) { │ │ │ │ │ - child = child.nextSibling; │ │ │ │ │ - k++; │ │ │ │ │ + /** │ │ │ │ │ + * Method: addDocumentEvents │ │ │ │ │ + * Start observing document events when documentDrag is true and the mouse │ │ │ │ │ + * cursor leaves the map viewport while dragging. │ │ │ │ │ + */ │ │ │ │ │ + addDocumentEvents: function() { │ │ │ │ │ + OpenLayers.Element.addClass(document.body, "olDragDown"); │ │ │ │ │ + this.documentEvents = true; │ │ │ │ │ + OpenLayers.Event.observe(document, "mousemove", this._docMove); │ │ │ │ │ + OpenLayers.Event.observe(document, "mouseup", this._docUp); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: removeDocumentEvents │ │ │ │ │ + * Stops observing document events when documentDrag is true and the mouse │ │ │ │ │ + * cursor re-enters the map viewport while dragging. │ │ │ │ │ + */ │ │ │ │ │ + removeDocumentEvents: function() { │ │ │ │ │ + OpenLayers.Element.removeClass(document.body, "olDragDown"); │ │ │ │ │ + this.documentEvents = false; │ │ │ │ │ + OpenLayers.Event.stopObserving(document, "mousemove", this._docMove); │ │ │ │ │ + OpenLayers.Event.stopObserving(document, "mouseup", this._docUp); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Handler.Drag" │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Handler/Box.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Handler.js │ │ │ │ │ + * @requires OpenLayers/Handler/Drag.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Handler.Box │ │ │ │ │ + * Handler for dragging a rectangle across the map. Box is displayed │ │ │ │ │ + * on mouse down, moves on mouse move, and is finished on mouse up. │ │ │ │ │ + * │ │ │ │ │ + * Inherits from: │ │ │ │ │ + * - │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: dragHandler │ │ │ │ │ + * {} │ │ │ │ │ + */ │ │ │ │ │ + dragHandler: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: boxDivClassName │ │ │ │ │ + * {String} The CSS class to use for drawing the box. Default is │ │ │ │ │ + * olHandlerBoxZoomBox │ │ │ │ │ + */ │ │ │ │ │ + boxDivClassName: 'olHandlerBoxZoomBox', │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: boxOffsets │ │ │ │ │ + * {Object} Caches box offsets from css. This is used by the getBoxOffsets │ │ │ │ │ + * method. │ │ │ │ │ + */ │ │ │ │ │ + boxOffsets: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Handler.Box │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * control - {} │ │ │ │ │ + * callbacks - {Object} An object with a properties whose values are │ │ │ │ │ + * functions. Various callbacks described below. │ │ │ │ │ + * options - {Object} │ │ │ │ │ + * │ │ │ │ │ + * Named callbacks: │ │ │ │ │ + * start - Called when the box drag operation starts. │ │ │ │ │ + * done - Called when the box drag operation is finished. │ │ │ │ │ + * The callback should expect to receive a single argument, the box │ │ │ │ │ + * bounds or a pixel. If the box dragging didn't span more than a 5 │ │ │ │ │ + * pixel distance, a pixel will be returned instead of a bounds object. │ │ │ │ │ + */ │ │ │ │ │ + initialize: function(control, callbacks, options) { │ │ │ │ │ + OpenLayers.Handler.prototype.initialize.apply(this, arguments); │ │ │ │ │ + this.dragHandler = new OpenLayers.Handler.Drag( │ │ │ │ │ + this, { │ │ │ │ │ + down: this.startBox, │ │ │ │ │ + move: this.moveBox, │ │ │ │ │ + out: this.removeBox, │ │ │ │ │ + up: this.endBox │ │ │ │ │ + }, { │ │ │ │ │ + keyMask: this.keyMask │ │ │ │ │ + } │ │ │ │ │ + ); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: destroy │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + OpenLayers.Handler.prototype.destroy.apply(this, arguments); │ │ │ │ │ + if (this.dragHandler) { │ │ │ │ │ + this.dragHandler.destroy(); │ │ │ │ │ + this.dragHandler = null; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: setMap │ │ │ │ │ + */ │ │ │ │ │ + setMap: function(map) { │ │ │ │ │ + OpenLayers.Handler.prototype.setMap.apply(this, arguments); │ │ │ │ │ + if (this.dragHandler) { │ │ │ │ │ + this.dragHandler.setMap(map); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: startBox │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * xy - {} │ │ │ │ │ + */ │ │ │ │ │ + startBox: function(xy) { │ │ │ │ │ + this.callback("start", []); │ │ │ │ │ + this.zoomBox = OpenLayers.Util.createDiv('zoomBox', { │ │ │ │ │ + x: -9999, │ │ │ │ │ + y: -9999 │ │ │ │ │ + }); │ │ │ │ │ + this.zoomBox.className = this.boxDivClassName; │ │ │ │ │ + this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; │ │ │ │ │ + │ │ │ │ │ + this.map.viewPortDiv.appendChild(this.zoomBox); │ │ │ │ │ + │ │ │ │ │ + OpenLayers.Element.addClass( │ │ │ │ │ + this.map.viewPortDiv, "olDrawBox" │ │ │ │ │ + ); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: moveBox │ │ │ │ │ + */ │ │ │ │ │ + moveBox: function(xy) { │ │ │ │ │ + var startX = this.dragHandler.start.x; │ │ │ │ │ + var startY = this.dragHandler.start.y; │ │ │ │ │ + var deltaX = Math.abs(startX - xy.x); │ │ │ │ │ + var deltaY = Math.abs(startY - xy.y); │ │ │ │ │ + │ │ │ │ │ + var offset = this.getBoxOffsets(); │ │ │ │ │ + this.zoomBox.style.width = (deltaX + offset.width + 1) + "px"; │ │ │ │ │ + this.zoomBox.style.height = (deltaY + offset.height + 1) + "px"; │ │ │ │ │ + this.zoomBox.style.left = (xy.x < startX ? │ │ │ │ │ + startX - deltaX - offset.left : startX - offset.left) + "px"; │ │ │ │ │ + this.zoomBox.style.top = (xy.y < startY ? │ │ │ │ │ + startY - deltaY - offset.top : startY - offset.top) + "px"; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: endBox │ │ │ │ │ + */ │ │ │ │ │ + endBox: function(end) { │ │ │ │ │ + var result; │ │ │ │ │ + if (Math.abs(this.dragHandler.start.x - end.x) > 5 || │ │ │ │ │ + Math.abs(this.dragHandler.start.y - end.y) > 5) { │ │ │ │ │ + var start = this.dragHandler.start; │ │ │ │ │ + var top = Math.min(start.y, end.y); │ │ │ │ │ + var bottom = Math.max(start.y, end.y); │ │ │ │ │ + var left = Math.min(start.x, end.x); │ │ │ │ │ + var right = Math.max(start.x, end.x); │ │ │ │ │ + result = new OpenLayers.Bounds(left, bottom, right, top); │ │ │ │ │ + } else { │ │ │ │ │ + result = this.dragHandler.start.clone(); // i.e. OL.Pixel │ │ │ │ │ + } │ │ │ │ │ + this.removeBox(); │ │ │ │ │ + │ │ │ │ │ + this.callback("done", [result]); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: removeBox │ │ │ │ │ + * Remove the zoombox from the screen and nullify our reference to it. │ │ │ │ │ + */ │ │ │ │ │ + removeBox: function() { │ │ │ │ │ + this.map.viewPortDiv.removeChild(this.zoomBox); │ │ │ │ │ + this.zoomBox = null; │ │ │ │ │ + this.boxOffsets = null; │ │ │ │ │ + OpenLayers.Element.removeClass( │ │ │ │ │ + this.map.viewPortDiv, "olDrawBox" │ │ │ │ │ + ); │ │ │ │ │ + │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: activate │ │ │ │ │ + */ │ │ │ │ │ + activate: function() { │ │ │ │ │ + if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) { │ │ │ │ │ + this.dragHandler.activate(); │ │ │ │ │ + return true; │ │ │ │ │ + } else { │ │ │ │ │ + return false; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: deactivate │ │ │ │ │ + */ │ │ │ │ │ + deactivate: function() { │ │ │ │ │ + if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { │ │ │ │ │ + if (this.dragHandler.deactivate()) { │ │ │ │ │ + if (this.zoomBox) { │ │ │ │ │ + this.removeBox(); │ │ │ │ │ } │ │ │ │ │ - tagName = (child ? child.nodeName : ''); │ │ │ │ │ - if (tagName.length > 0 && tagName.indexOf(criteria) > -1) { │ │ │ │ │ - nodes.push(child); │ │ │ │ │ - } else { │ │ │ │ │ - matchNodes = this.getSiblingNodesByTagCriteria( │ │ │ │ │ - child, criteria); │ │ │ │ │ + } │ │ │ │ │ + return true; │ │ │ │ │ + } else { │ │ │ │ │ + return false; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: getBoxOffsets │ │ │ │ │ + * Determines border offsets for a box, according to the box model. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Object} an object with the following offsets: │ │ │ │ │ + * - left │ │ │ │ │ + * - right │ │ │ │ │ + * - top │ │ │ │ │ + * - bottom │ │ │ │ │ + * - width │ │ │ │ │ + * - height │ │ │ │ │ + */ │ │ │ │ │ + getBoxOffsets: function() { │ │ │ │ │ + if (!this.boxOffsets) { │ │ │ │ │ + // Determine the box model. If the testDiv's clientWidth is 3, then │ │ │ │ │ + // the borders are outside and we are dealing with the w3c box │ │ │ │ │ + // model. Otherwise, the browser uses the traditional box model and │ │ │ │ │ + // the borders are inside the box bounds, leaving us with a │ │ │ │ │ + // clientWidth of 1. │ │ │ │ │ + var testDiv = document.createElement("div"); │ │ │ │ │ + //testDiv.style.visibility = "hidden"; │ │ │ │ │ + testDiv.style.position = "absolute"; │ │ │ │ │ + testDiv.style.border = "1px solid black"; │ │ │ │ │ + testDiv.style.width = "3px"; │ │ │ │ │ + document.body.appendChild(testDiv); │ │ │ │ │ + var w3cBoxModel = testDiv.clientWidth == 3; │ │ │ │ │ + document.body.removeChild(testDiv); │ │ │ │ │ + │ │ │ │ │ + var left = parseInt(OpenLayers.Element.getStyle(this.zoomBox, │ │ │ │ │ + "border-left-width")); │ │ │ │ │ + var right = parseInt(OpenLayers.Element.getStyle( │ │ │ │ │ + this.zoomBox, "border-right-width")); │ │ │ │ │ + var top = parseInt(OpenLayers.Element.getStyle(this.zoomBox, │ │ │ │ │ + "border-top-width")); │ │ │ │ │ + var bottom = parseInt(OpenLayers.Element.getStyle( │ │ │ │ │ + this.zoomBox, "border-bottom-width")); │ │ │ │ │ + this.boxOffsets = { │ │ │ │ │ + left: left, │ │ │ │ │ + right: right, │ │ │ │ │ + top: top, │ │ │ │ │ + bottom: bottom, │ │ │ │ │ + width: w3cBoxModel === false ? left + right : 0, │ │ │ │ │ + height: w3cBoxModel === false ? top + bottom : 0 │ │ │ │ │ + }; │ │ │ │ │ + } │ │ │ │ │ + return this.boxOffsets; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + CLASS_NAME: "OpenLayers.Handler.Box" │ │ │ │ │ +}); │ │ │ │ │ +/* ====================================================================== │ │ │ │ │ + OpenLayers/Control/ZoomBox.js │ │ │ │ │ + ====================================================================== */ │ │ │ │ │ + │ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ + * full text of the license. */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * @requires OpenLayers/Control.js │ │ │ │ │ + * @requires OpenLayers/Handler/Box.js │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ +/** │ │ │ │ │ + * Class: OpenLayers.Control.ZoomBox │ │ │ │ │ + * The ZoomBox control enables zooming directly to a given extent, by drawing │ │ │ │ │ + * a box on the map. The box is drawn by holding down shift, whilst dragging │ │ │ │ │ + * the mouse. │ │ │ │ │ + * │ │ │ │ │ + * Inherits from: │ │ │ │ │ + * - │ │ │ │ │ + */ │ │ │ │ │ +OpenLayers.Control.ZoomBox = OpenLayers.Class(OpenLayers.Control, { │ │ │ │ │ + /** │ │ │ │ │ + * Property: type │ │ │ │ │ + * {OpenLayers.Control.TYPE} │ │ │ │ │ + */ │ │ │ │ │ + type: OpenLayers.Control.TYPE_TOOL, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: out │ │ │ │ │ + * {Boolean} Should the control be used for zooming out? │ │ │ │ │ + */ │ │ │ │ │ + out: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: keyMask │ │ │ │ │ + * {Integer} Zoom only occurs if the keyMask matches the combination of │ │ │ │ │ + * keys down. Use bitwise operators and one or more of the │ │ │ │ │ + * constants to construct a keyMask. Leave null if │ │ │ │ │ + * not used mask. Default is null. │ │ │ │ │ + */ │ │ │ │ │ + keyMask: null, │ │ │ │ │ │ │ │ │ │ - if (matchNodes.length > 0) { │ │ │ │ │ - (nodes.length == 0) ? │ │ │ │ │ - nodes = matchNodes: nodes.push(matchNodes); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: alwaysZoom │ │ │ │ │ + * {Boolean} Always zoom in/out when box drawn, even if the zoom level does │ │ │ │ │ + * not change. │ │ │ │ │ + */ │ │ │ │ │ + alwaysZoom: false, │ │ │ │ │ │ │ │ │ │ - } │ │ │ │ │ - return nodes; │ │ │ │ │ - }, │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: zoomOnClick │ │ │ │ │ + * {Boolean} Should we zoom when no box was dragged, i.e. the user only │ │ │ │ │ + * clicked? Default is true. │ │ │ │ │ + */ │ │ │ │ │ + zoomOnClick: true, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: parseAttributes │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * node - {} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} An attributes object. │ │ │ │ │ - * │ │ │ │ │ - * Notes: │ │ │ │ │ - * Assumes that attributes are direct child xml nodes of the passed node │ │ │ │ │ - * and contain only a single text node. │ │ │ │ │ + * Method: draw │ │ │ │ │ */ │ │ │ │ │ - parseAttributes: function(node) { │ │ │ │ │ - var attributes = {}; │ │ │ │ │ - if (node.nodeType == 1) { │ │ │ │ │ - var children = node.childNodes; │ │ │ │ │ - var n = children.length; │ │ │ │ │ - for (var i = 0; i < n; ++i) { │ │ │ │ │ - var child = children[i]; │ │ │ │ │ - if (child.nodeType == 1) { │ │ │ │ │ - var grandchildren = child.childNodes; │ │ │ │ │ - var name = (child.prefix) ? │ │ │ │ │ - child.nodeName.split(":")[1] : child.nodeName; │ │ │ │ │ - if (grandchildren.length == 0) { │ │ │ │ │ - attributes[name] = null; │ │ │ │ │ - } else if (grandchildren.length == 1) { │ │ │ │ │ - var grandchild = grandchildren[0]; │ │ │ │ │ - if (grandchild.nodeType == 3 || │ │ │ │ │ - grandchild.nodeType == 4) { │ │ │ │ │ - var value = grandchild.nodeValue.replace( │ │ │ │ │ - this.regExes.trimSpace, ""); │ │ │ │ │ - attributes[name] = value; │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ - return attributes; │ │ │ │ │ + draw: function() { │ │ │ │ │ + this.handler = new OpenLayers.Handler.Box(this, { │ │ │ │ │ + done: this.zoomBox │ │ │ │ │ + }, { │ │ │ │ │ + keyMask: this.keyMask │ │ │ │ │ + }); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: parseGeometry │ │ │ │ │ - * Parse the geometry and the feature bounds out of the node using │ │ │ │ │ - * Format.GML │ │ │ │ │ + * Method: zoomBox │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * node - {} │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Object} An object containing the geometry and the feature bounds │ │ │ │ │ + * position - {} or {} │ │ │ │ │ */ │ │ │ │ │ - parseGeometry: function(node) { │ │ │ │ │ - // we need to use the old Format.GML parser since we do not know the │ │ │ │ │ - // geometry name │ │ │ │ │ - if (!this.gmlFormat) { │ │ │ │ │ - this.gmlFormat = new OpenLayers.Format.GML(); │ │ │ │ │ - } │ │ │ │ │ - var feature = this.gmlFormat.parseFeature(node); │ │ │ │ │ - var geometry, bounds = null; │ │ │ │ │ - if (feature) { │ │ │ │ │ - geometry = feature.geometry && feature.geometry.clone(); │ │ │ │ │ - bounds = feature.bounds && feature.bounds.clone(); │ │ │ │ │ - feature.destroy(); │ │ │ │ │ + zoomBox: function(position) { │ │ │ │ │ + if (position instanceof OpenLayers.Bounds) { │ │ │ │ │ + var bounds, │ │ │ │ │ + targetCenterPx = position.getCenterPixel(); │ │ │ │ │ + if (!this.out) { │ │ │ │ │ + var minXY = this.map.getLonLatFromPixel({ │ │ │ │ │ + x: position.left, │ │ │ │ │ + y: position.bottom │ │ │ │ │ + }); │ │ │ │ │ + var maxXY = this.map.getLonLatFromPixel({ │ │ │ │ │ + x: position.right, │ │ │ │ │ + y: position.top │ │ │ │ │ + }); │ │ │ │ │ + bounds = new OpenLayers.Bounds(minXY.lon, minXY.lat, │ │ │ │ │ + maxXY.lon, maxXY.lat); │ │ │ │ │ + } else { │ │ │ │ │ + var pixWidth = position.right - position.left; │ │ │ │ │ + var pixHeight = position.bottom - position.top; │ │ │ │ │ + var zoomFactor = Math.min((this.map.size.h / pixHeight), │ │ │ │ │ + (this.map.size.w / pixWidth)); │ │ │ │ │ + var extent = this.map.getExtent(); │ │ │ │ │ + var center = this.map.getLonLatFromPixel(targetCenterPx); │ │ │ │ │ + var xmin = center.lon - (extent.getWidth() / 2) * zoomFactor; │ │ │ │ │ + var xmax = center.lon + (extent.getWidth() / 2) * zoomFactor; │ │ │ │ │ + var ymin = center.lat - (extent.getHeight() / 2) * zoomFactor; │ │ │ │ │ + var ymax = center.lat + (extent.getHeight() / 2) * zoomFactor; │ │ │ │ │ + bounds = new OpenLayers.Bounds(xmin, ymin, xmax, ymax); │ │ │ │ │ + } │ │ │ │ │ + // always zoom in/out │ │ │ │ │ + var lastZoom = this.map.getZoom(), │ │ │ │ │ + size = this.map.getSize(), │ │ │ │ │ + centerPx = { │ │ │ │ │ + x: size.w / 2, │ │ │ │ │ + y: size.h / 2 │ │ │ │ │ + }, │ │ │ │ │ + zoom = this.map.getZoomForExtent(bounds), │ │ │ │ │ + oldRes = this.map.getResolution(), │ │ │ │ │ + newRes = this.map.getResolutionForZoom(zoom); │ │ │ │ │ + if (oldRes == newRes) { │ │ │ │ │ + this.map.setCenter(this.map.getLonLatFromPixel(targetCenterPx)); │ │ │ │ │ + } else { │ │ │ │ │ + var zoomOriginPx = { │ │ │ │ │ + x: (oldRes * targetCenterPx.x - newRes * centerPx.x) / │ │ │ │ │ + (oldRes - newRes), │ │ │ │ │ + y: (oldRes * targetCenterPx.y - newRes * centerPx.y) / │ │ │ │ │ + (oldRes - newRes) │ │ │ │ │ + }; │ │ │ │ │ + this.map.zoomTo(zoom, zoomOriginPx); │ │ │ │ │ + } │ │ │ │ │ + if (lastZoom == this.map.getZoom() && this.alwaysZoom == true) { │ │ │ │ │ + this.map.zoomTo(lastZoom + (this.out ? -1 : 1)); │ │ │ │ │ + } │ │ │ │ │ + } else if (this.zoomOnClick) { // it's a pixel │ │ │ │ │ + if (!this.out) { │ │ │ │ │ + this.map.zoomTo(this.map.getZoom() + 1, position); │ │ │ │ │ + } else { │ │ │ │ │ + this.map.zoomTo(this.map.getZoom() - 1, position); │ │ │ │ │ + } │ │ │ │ │ } │ │ │ │ │ - return { │ │ │ │ │ - geometry: geometry, │ │ │ │ │ - bounds: bounds │ │ │ │ │ - }; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Format.WMSGetFeatureInfo" │ │ │ │ │ - │ │ │ │ │ + CLASS_NAME: "OpenLayers.Control.ZoomBox" │ │ │ │ │ }); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Format/WMSDescribeLayer.js │ │ │ │ │ + OpenLayers/Control/DragPan.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/Format/XML/VersionedOGC.js │ │ │ │ │ + * @requires OpenLayers/Control.js │ │ │ │ │ + * @requires OpenLayers/Handler/Drag.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Format.WMSDescribeLayer │ │ │ │ │ - * Read SLD WMS DescribeLayer response │ │ │ │ │ - * DescribeLayer is meant to couple WMS to WFS and WCS │ │ │ │ │ - * │ │ │ │ │ + * Class: OpenLayers.Control.DragPan │ │ │ │ │ + * The DragPan control pans the map with a drag of the mouse. │ │ │ │ │ + * │ │ │ │ │ * Inherits from: │ │ │ │ │ - * - │ │ │ │ │ + * - │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Format.WMSDescribeLayer = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, { │ │ │ │ │ +OpenLayers.Control.DragPan = OpenLayers.Class(OpenLayers.Control, { │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: type │ │ │ │ │ + * {OpenLayers.Control.TYPES} │ │ │ │ │ + */ │ │ │ │ │ + type: OpenLayers.Control.TYPE_TOOL, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: defaultVersion │ │ │ │ │ - * {String} Version number to assume if none found. Default is "1.1.1". │ │ │ │ │ + * Property: panned │ │ │ │ │ + * {Boolean} The map moved. │ │ │ │ │ */ │ │ │ │ │ - defaultVersion: "1.1.1", │ │ │ │ │ + panned: false, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Format.WMSDescribeLayer │ │ │ │ │ - * Create a new parser for WMS DescribeLayer responses. │ │ │ │ │ + * Property: interval │ │ │ │ │ + * {Integer} The number of milliseconds that should ellapse before │ │ │ │ │ + * panning the map again. Defaults to 0 milliseconds, which means that │ │ │ │ │ + * no separate cycle is used for panning. In most cases you won't want │ │ │ │ │ + * to change this value. For slow machines/devices larger values can be │ │ │ │ │ + * tried out. │ │ │ │ │ + */ │ │ │ │ │ + interval: 0, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: documentDrag │ │ │ │ │ + * {Boolean} If set to true, mouse dragging will continue even if the │ │ │ │ │ + * mouse cursor leaves the map viewport. Default is false. │ │ │ │ │ + */ │ │ │ │ │ + documentDrag: false, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Property: kinetic │ │ │ │ │ + * {} The OpenLayers.Kinetic object. │ │ │ │ │ + */ │ │ │ │ │ + kinetic: null, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: enableKinetic │ │ │ │ │ + * {Boolean} Set this option to enable "kinetic dragging". Can be │ │ │ │ │ + * set to true or to an object. If set to an object this │ │ │ │ │ + * object will be passed to the {} │ │ │ │ │ + * constructor. Defaults to true. │ │ │ │ │ + * To get kinetic dragging, ensure that OpenLayers/Kinetic.js is │ │ │ │ │ + * included in your build config. │ │ │ │ │ + */ │ │ │ │ │ + enableKinetic: true, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * APIProperty: kineticInterval │ │ │ │ │ + * {Integer} Interval in milliseconds between 2 steps in the "kinetic │ │ │ │ │ + * scrolling". Applies only if enableKinetic is set. Defaults │ │ │ │ │ + * to 10 milliseconds. │ │ │ │ │ + */ │ │ │ │ │ + kineticInterval: 10, │ │ │ │ │ + │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: draw │ │ │ │ │ + * Creates a Drag handler, using and │ │ │ │ │ + * as callbacks. │ │ │ │ │ + */ │ │ │ │ │ + draw: function() { │ │ │ │ │ + if (this.enableKinetic && OpenLayers.Kinetic) { │ │ │ │ │ + var config = { │ │ │ │ │ + interval: this.kineticInterval │ │ │ │ │ + }; │ │ │ │ │ + if (typeof this.enableKinetic === "object") { │ │ │ │ │ + config = OpenLayers.Util.extend(config, this.enableKinetic); │ │ │ │ │ + } │ │ │ │ │ + this.kinetic = new OpenLayers.Kinetic(config); │ │ │ │ │ + } │ │ │ │ │ + this.handler = new OpenLayers.Handler.Drag(this, { │ │ │ │ │ + "move": this.panMap, │ │ │ │ │ + "done": this.panMapDone, │ │ │ │ │ + "down": this.panMapStart │ │ │ │ │ + }, { │ │ │ │ │ + interval: this.interval, │ │ │ │ │ + documentDrag: this.documentDrag │ │ │ │ │ + }); │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: panMapStart │ │ │ │ │ + */ │ │ │ │ │ + panMapStart: function() { │ │ │ │ │ + if (this.kinetic) { │ │ │ │ │ + this.kinetic.begin(); │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: panMap │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * options - {Object} An optional object whose properties will be set on │ │ │ │ │ - * this instance. │ │ │ │ │ + * xy - {} Pixel of the mouse position │ │ │ │ │ */ │ │ │ │ │ + panMap: function(xy) { │ │ │ │ │ + if (this.kinetic) { │ │ │ │ │ + this.kinetic.update(xy); │ │ │ │ │ + } │ │ │ │ │ + this.panned = true; │ │ │ │ │ + this.map.pan( │ │ │ │ │ + this.handler.last.x - xy.x, │ │ │ │ │ + this.handler.last.y - xy.y, { │ │ │ │ │ + dragging: true, │ │ │ │ │ + animate: false │ │ │ │ │ + } │ │ │ │ │ + ); │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: read │ │ │ │ │ - * Read DescribeLayer data from a string, and return the response. │ │ │ │ │ - * The OGC currently defines 2 formats which are allowed for output, │ │ │ │ │ - * so we need to parse these 2 types │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * data - {String} or {DOMElement} data to read/parse. │ │ │ │ │ + * Method: panMapDone │ │ │ │ │ + * Finish the panning operation. Only call setCenter (through ) │ │ │ │ │ + * if the map has actually been moved. │ │ │ │ │ * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Array} Array of {} objects which have: │ │ │ │ │ - * - {String} owsType: WFS/WCS │ │ │ │ │ - * - {String} owsURL: the online resource │ │ │ │ │ - * - {String} typeName: the name of the typename on the service │ │ │ │ │ + * Parameters: │ │ │ │ │ + * xy - {} Pixel of the mouse position │ │ │ │ │ */ │ │ │ │ │ + panMapDone: function(xy) { │ │ │ │ │ + if (this.panned) { │ │ │ │ │ + var res = null; │ │ │ │ │ + if (this.kinetic) { │ │ │ │ │ + res = this.kinetic.end(xy); │ │ │ │ │ + } │ │ │ │ │ + this.map.pan( │ │ │ │ │ + this.handler.last.x - xy.x, │ │ │ │ │ + this.handler.last.y - xy.y, { │ │ │ │ │ + dragging: !!res, │ │ │ │ │ + animate: false │ │ │ │ │ + } │ │ │ │ │ + ); │ │ │ │ │ + if (res) { │ │ │ │ │ + var self = this; │ │ │ │ │ + this.kinetic.move(res, function(x, y, end) { │ │ │ │ │ + self.map.pan(x, y, { │ │ │ │ │ + dragging: !end, │ │ │ │ │ + animate: false │ │ │ │ │ + }); │ │ │ │ │ + }); │ │ │ │ │ + } │ │ │ │ │ + this.panned = false; │ │ │ │ │ + } │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Format.WMSDescribeLayer" │ │ │ │ │ - │ │ │ │ │ + CLASS_NAME: "OpenLayers.Control.DragPan" │ │ │ │ │ }); │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Format/Context.js │ │ │ │ │ + OpenLayers/Handler/MouseWheel.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/Format/XML/VersionedOGC.js │ │ │ │ │ + * @requires OpenLayers/Handler.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Format.Context │ │ │ │ │ - * Base class for both Format.WMC and Format.OWSContext │ │ │ │ │ - * │ │ │ │ │ + * Class: OpenLayers.Handler.MouseWheel │ │ │ │ │ + * Handler for wheel up/down events. │ │ │ │ │ + * │ │ │ │ │ * Inherits from: │ │ │ │ │ - * - │ │ │ │ │ + * - │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Format.Context = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, { │ │ │ │ │ +OpenLayers.Handler.MouseWheel = OpenLayers.Class(OpenLayers.Handler, { │ │ │ │ │ + /** │ │ │ │ │ + * Property: wheelListener │ │ │ │ │ + * {function} │ │ │ │ │ + */ │ │ │ │ │ + wheelListener: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: layerOptions │ │ │ │ │ - * {Object} Default options for layers created by the parser. These │ │ │ │ │ - * options are overridden by the options which are read from the │ │ │ │ │ - * capabilities document. │ │ │ │ │ + * Property: interval │ │ │ │ │ + * {Integer} In order to increase server performance, an interval (in │ │ │ │ │ + * milliseconds) can be set to reduce the number of up/down events │ │ │ │ │ + * called. If set, a new up/down event will not be set until the │ │ │ │ │ + * interval has passed. │ │ │ │ │ + * Defaults to 0, meaning no interval. │ │ │ │ │ */ │ │ │ │ │ - layerOptions: null, │ │ │ │ │ + interval: 0, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: layerParams │ │ │ │ │ - * {Object} Default parameters for layers created by the parser. This │ │ │ │ │ - * can be used e.g. to override DEFAULT_PARAMS for │ │ │ │ │ - * OpenLayers.Layer.WMS. │ │ │ │ │ + * Property: maxDelta │ │ │ │ │ + * {Integer} Maximum delta to collect before breaking from the current │ │ │ │ │ + * interval. In cumulative mode, this also limits the maximum delta │ │ │ │ │ + * returned from the handler. Default is Number.POSITIVE_INFINITY. │ │ │ │ │ */ │ │ │ │ │ - layerParams: null, │ │ │ │ │ + maxDelta: Number.POSITIVE_INFINITY, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Format.Context │ │ │ │ │ - * Create a new parser for Context documents. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} An optional object whose properties will be set on │ │ │ │ │ - * this instance. │ │ │ │ │ + * Property: delta │ │ │ │ │ + * {Integer} When interval is set, delta collects the mousewheel z-deltas │ │ │ │ │ + * of the events that occur within the interval. │ │ │ │ │ + * See also the cumulative option │ │ │ │ │ */ │ │ │ │ │ + delta: 0, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: read │ │ │ │ │ - * Read Context data from a string, and return an object with map │ │ │ │ │ - * properties and a list of layers. │ │ │ │ │ + * Property: cumulative │ │ │ │ │ + * {Boolean} When interval is set: true to collect all the mousewheel │ │ │ │ │ + * z-deltas, false to only record the delta direction (positive or │ │ │ │ │ + * negative) │ │ │ │ │ + */ │ │ │ │ │ + cumulative: true, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Constructor: OpenLayers.Handler.MouseWheel │ │ │ │ │ * │ │ │ │ │ * Parameters: │ │ │ │ │ - * data - {String} or {DOMElement} data to read/parse. │ │ │ │ │ - * options - {Object} The options object must contain a map property. If │ │ │ │ │ - * the map property is a string, it must be the id of a dom element │ │ │ │ │ - * where the new map will be placed. If the map property is an │ │ │ │ │ - * , the layers from the context document will be added │ │ │ │ │ - * to the map. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} A map based on the context. │ │ │ │ │ + * control - {} │ │ │ │ │ + * callbacks - {Object} An object containing a single function to be │ │ │ │ │ + * called when the drag operation is finished. │ │ │ │ │ + * The callback should expect to recieve a single │ │ │ │ │ + * argument, the point geometry. │ │ │ │ │ + * options - {Object} │ │ │ │ │ */ │ │ │ │ │ - read: function(data, options) { │ │ │ │ │ - var context = OpenLayers.Format.XML.VersionedOGC.prototype.read.apply(this, │ │ │ │ │ - arguments); │ │ │ │ │ - var map; │ │ │ │ │ - if (options && options.map) { │ │ │ │ │ - this.context = context; │ │ │ │ │ - if (options.map instanceof OpenLayers.Map) { │ │ │ │ │ - map = this.mergeContextToMap(context, options.map); │ │ │ │ │ - } else { │ │ │ │ │ - var mapOptions = options.map; │ │ │ │ │ - if (OpenLayers.Util.isElement(mapOptions) || │ │ │ │ │ - typeof mapOptions == "string") { │ │ │ │ │ - // we assume mapOptions references a div │ │ │ │ │ - // element │ │ │ │ │ - mapOptions = { │ │ │ │ │ - div: mapOptions │ │ │ │ │ - }; │ │ │ │ │ - } │ │ │ │ │ - map = this.contextToMap(context, mapOptions); │ │ │ │ │ - } │ │ │ │ │ - } else { │ │ │ │ │ - // not documented as part of the API, provided as a non-API option │ │ │ │ │ - map = context; │ │ │ │ │ - } │ │ │ │ │ - return map; │ │ │ │ │ + initialize: function(control, callbacks, options) { │ │ │ │ │ + OpenLayers.Handler.prototype.initialize.apply(this, arguments); │ │ │ │ │ + this.wheelListener = OpenLayers.Function.bindAsEventListener( │ │ │ │ │ + this.onWheelEvent, this │ │ │ │ │ + ); │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: getLayerFromContext │ │ │ │ │ - * Create a WMS layer from a layerContext object. │ │ │ │ │ - * │ │ │ │ │ + * Method: destroy │ │ │ │ │ + */ │ │ │ │ │ + destroy: function() { │ │ │ │ │ + OpenLayers.Handler.prototype.destroy.apply(this, arguments); │ │ │ │ │ + this.wheelListener = null; │ │ │ │ │ + }, │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Mouse ScrollWheel code thanks to http://adomas.org/javascript-mouse-wheel/ │ │ │ │ │ + */ │ │ │ │ │ + │ │ │ │ │ + /** │ │ │ │ │ + * Method: onWheelEvent │ │ │ │ │ + * Catch the wheel event and handle it xbrowserly │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * layerContext - {Object} An object representing a WMS layer. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} A WMS layer. │ │ │ │ │ + * e - {Event} │ │ │ │ │ */ │ │ │ │ │ - getLayerFromContext: function(layerContext) { │ │ │ │ │ - var i, len; │ │ │ │ │ - // fill initial options object from layerContext │ │ │ │ │ - var options = { │ │ │ │ │ - queryable: layerContext.queryable, //keep queryable for api compatibility │ │ │ │ │ - visibility: layerContext.visibility, │ │ │ │ │ - maxExtent: layerContext.maxExtent, │ │ │ │ │ - metadata: OpenLayers.Util.applyDefaults(layerContext.metadata, { │ │ │ │ │ - styles: layerContext.styles, │ │ │ │ │ - formats: layerContext.formats, │ │ │ │ │ - "abstract": layerContext["abstract"], │ │ │ │ │ - dataURL: layerContext.dataURL │ │ │ │ │ - }), │ │ │ │ │ - numZoomLevels: layerContext.numZoomLevels, │ │ │ │ │ - units: layerContext.units, │ │ │ │ │ - isBaseLayer: layerContext.isBaseLayer, │ │ │ │ │ - opacity: layerContext.opacity, │ │ │ │ │ - displayInLayerSwitcher: layerContext.displayInLayerSwitcher, │ │ │ │ │ - singleTile: layerContext.singleTile, │ │ │ │ │ - tileSize: (layerContext.tileSize) ? │ │ │ │ │ - new OpenLayers.Size( │ │ │ │ │ - layerContext.tileSize.width, │ │ │ │ │ - layerContext.tileSize.height │ │ │ │ │ - ) : undefined, │ │ │ │ │ - minScale: layerContext.minScale || layerContext.maxScaleDenominator, │ │ │ │ │ - maxScale: layerContext.maxScale || layerContext.minScaleDenominator, │ │ │ │ │ - srs: layerContext.srs, │ │ │ │ │ - dimensions: layerContext.dimensions, │ │ │ │ │ - metadataURL: layerContext.metadataURL │ │ │ │ │ - }; │ │ │ │ │ - if (this.layerOptions) { │ │ │ │ │ - OpenLayers.Util.applyDefaults(options, this.layerOptions); │ │ │ │ │ + onWheelEvent: function(e) { │ │ │ │ │ + │ │ │ │ │ + // make sure we have a map and check keyboard modifiers │ │ │ │ │ + if (!this.map || !this.checkModifiers(e)) { │ │ │ │ │ + return; │ │ │ │ │ } │ │ │ │ │ │ │ │ │ │ - var params = { │ │ │ │ │ - layers: layerContext.name, │ │ │ │ │ - transparent: layerContext.transparent, │ │ │ │ │ - version: layerContext.version │ │ │ │ │ - }; │ │ │ │ │ - if (layerContext.formats && layerContext.formats.length > 0) { │ │ │ │ │ - // set default value for params if current attribute is not positionned │ │ │ │ │ - params.format = layerContext.formats[0].value; │ │ │ │ │ - for (i = 0, len = layerContext.formats.length; i < len; i++) { │ │ │ │ │ - var format = layerContext.formats[i]; │ │ │ │ │ - if (format.current == true) { │ │ │ │ │ - params.format = format.value; │ │ │ │ │ - break; │ │ │ │ │ + // Ride up the element's DOM hierarchy to determine if it or any of │ │ │ │ │ + // its ancestors was: │ │ │ │ │ + // * specifically marked as scrollable (CSS overflow property) │ │ │ │ │ + // * one of our layer divs or a div marked as scrollable │ │ │ │ │ + // ('olScrollable' CSS class) │ │ │ │ │ + // * the map div │ │ │ │ │ + // │ │ │ │ │ + var overScrollableDiv = false; │ │ │ │ │ + var allowScroll = false; │ │ │ │ │ + var overMapDiv = false; │ │ │ │ │ + │ │ │ │ │ + var elem = OpenLayers.Event.element(e); │ │ │ │ │ + while ((elem != null) && !overMapDiv && !overScrollableDiv) { │ │ │ │ │ + │ │ │ │ │ + if (!overScrollableDiv) { │ │ │ │ │ + try { │ │ │ │ │ + var overflow; │ │ │ │ │ + if (elem.currentStyle) { │ │ │ │ │ + overflow = elem.currentStyle["overflow"]; │ │ │ │ │ + } else { │ │ │ │ │ + var style = │ │ │ │ │ + document.defaultView.getComputedStyle(elem, null); │ │ │ │ │ + overflow = style.getPropertyValue("overflow"); │ │ │ │ │ + } │ │ │ │ │ + overScrollableDiv = (overflow && │ │ │ │ │ + (overflow == "auto") || (overflow == "scroll")); │ │ │ │ │ + } catch (err) { │ │ │ │ │ + //sometimes when scrolling in a popup, this causes │ │ │ │ │ + // obscure browser error │ │ │ │ │ } │ │ │ │ │ } │ │ │ │ │ - } │ │ │ │ │ - if (layerContext.styles && layerContext.styles.length > 0) { │ │ │ │ │ - for (i = 0, len = layerContext.styles.length; i < len; i++) { │ │ │ │ │ - var style = layerContext.styles[i]; │ │ │ │ │ - if (style.current == true) { │ │ │ │ │ - // three style types to consider │ │ │ │ │ - // 1) linked SLD │ │ │ │ │ - // 2) inline SLD │ │ │ │ │ - // 3) named style │ │ │ │ │ - if (style.href) { │ │ │ │ │ - params.sld = style.href; │ │ │ │ │ - } else if (style.body) { │ │ │ │ │ - params.sld_body = style.body; │ │ │ │ │ - } else { │ │ │ │ │ - params.styles = style.name; │ │ │ │ │ + │ │ │ │ │ + if (!allowScroll) { │ │ │ │ │ + allowScroll = OpenLayers.Element.hasClass(elem, 'olScrollable'); │ │ │ │ │ + if (!allowScroll) { │ │ │ │ │ + for (var i = 0, len = this.map.layers.length; i < len; i++) { │ │ │ │ │ + // Are we in the layer div? Note that we have two cases │ │ │ │ │ + // here: one is to catch EventPane layers, which have a │ │ │ │ │ + // pane above the layer (layer.pane) │ │ │ │ │ + var layer = this.map.layers[i]; │ │ │ │ │ + if (elem == layer.div || elem == layer.pane) { │ │ │ │ │ + allowScroll = true; │ │ │ │ │ + break; │ │ │ │ │ + } │ │ │ │ │ } │ │ │ │ │ - break; │ │ │ │ │ } │ │ │ │ │ } │ │ │ │ │ - } │ │ │ │ │ - if (this.layerParams) { │ │ │ │ │ - OpenLayers.Util.applyDefaults(params, this.layerParams); │ │ │ │ │ - } │ │ │ │ │ + overMapDiv = (elem == this.map.div); │ │ │ │ │ │ │ │ │ │ - var layer = null; │ │ │ │ │ - var service = layerContext.service; │ │ │ │ │ - if (service == OpenLayers.Format.Context.serviceTypes.WFS) { │ │ │ │ │ - options.strategies = [new OpenLayers.Strategy.BBOX()]; │ │ │ │ │ - options.protocol = new OpenLayers.Protocol.WFS({ │ │ │ │ │ - url: layerContext.url, │ │ │ │ │ - // since we do not know featureNS, let the protocol │ │ │ │ │ - // determine it automagically using featurePrefix │ │ │ │ │ - featurePrefix: layerContext.name.split(":")[0], │ │ │ │ │ - featureType: layerContext.name.split(":").pop() │ │ │ │ │ - }); │ │ │ │ │ - layer = new OpenLayers.Layer.Vector( │ │ │ │ │ - layerContext.title || layerContext.name, │ │ │ │ │ - options │ │ │ │ │ - ); │ │ │ │ │ - } else if (service == OpenLayers.Format.Context.serviceTypes.KML) { │ │ │ │ │ - // use a vector layer with an HTTP Protcol and a Fixed strategy │ │ │ │ │ - options.strategies = [new OpenLayers.Strategy.Fixed()]; │ │ │ │ │ - options.protocol = new OpenLayers.Protocol.HTTP({ │ │ │ │ │ - url: layerContext.url, │ │ │ │ │ - format: new OpenLayers.Format.KML() │ │ │ │ │ - }); │ │ │ │ │ - layer = new OpenLayers.Layer.Vector( │ │ │ │ │ - layerContext.title || layerContext.name, │ │ │ │ │ - options │ │ │ │ │ - ); │ │ │ │ │ - } else if (service == OpenLayers.Format.Context.serviceTypes.GML) { │ │ │ │ │ - // use a vector layer with a HTTP Protocol and a Fixed strategy │ │ │ │ │ - options.strategies = [new OpenLayers.Strategy.Fixed()]; │ │ │ │ │ - options.protocol = new OpenLayers.Protocol.HTTP({ │ │ │ │ │ - url: layerContext.url, │ │ │ │ │ - format: new OpenLayers.Format.GML() │ │ │ │ │ - }); │ │ │ │ │ - layer = new OpenLayers.Layer.Vector( │ │ │ │ │ - layerContext.title || layerContext.name, │ │ │ │ │ - options │ │ │ │ │ - ); │ │ │ │ │ - } else if (layerContext.features) { │ │ │ │ │ - // inline GML or KML features │ │ │ │ │ - layer = new OpenLayers.Layer.Vector( │ │ │ │ │ - layerContext.title || layerContext.name, │ │ │ │ │ - options │ │ │ │ │ - ); │ │ │ │ │ - layer.addFeatures(layerContext.features); │ │ │ │ │ - } else if (layerContext.categoryLayer !== true) { │ │ │ │ │ - layer = new OpenLayers.Layer.WMS( │ │ │ │ │ - layerContext.title || layerContext.name, │ │ │ │ │ - layerContext.url, │ │ │ │ │ - params, │ │ │ │ │ - options │ │ │ │ │ - ); │ │ │ │ │ + elem = elem.parentNode; │ │ │ │ │ } │ │ │ │ │ - return layer; │ │ │ │ │ - }, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Method: getLayersFromContext │ │ │ │ │ - * Create an array of layers from an array of layerContext objects. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * layersContext - {Array(Object)} An array of objects representing layers. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {Array()} An array of layers. │ │ │ │ │ - */ │ │ │ │ │ - getLayersFromContext: function(layersContext) { │ │ │ │ │ - var layers = []; │ │ │ │ │ - for (var i = 0, len = layersContext.length; i < len; i++) { │ │ │ │ │ - var layer = this.getLayerFromContext(layersContext[i]); │ │ │ │ │ - if (layer !== null) { │ │ │ │ │ - layers.push(layer); │ │ │ │ │ + // Logic below is the following: │ │ │ │ │ + // │ │ │ │ │ + // If we are over a scrollable div or not over the map div: │ │ │ │ │ + // * do nothing (let the browser handle scrolling) │ │ │ │ │ + // │ │ │ │ │ + // otherwise │ │ │ │ │ + // │ │ │ │ │ + // If we are over the layer div or a 'olScrollable' div: │ │ │ │ │ + // * zoom/in out │ │ │ │ │ + // then │ │ │ │ │ + // * kill event (so as not to also scroll the page after zooming) │ │ │ │ │ + // │ │ │ │ │ + // otherwise │ │ │ │ │ + // │ │ │ │ │ + // Kill the event (dont scroll the page if we wheel over the │ │ │ │ │ + // layerswitcher or the pan/zoom control) │ │ │ │ │ + // │ │ │ │ │ + if (!overScrollableDiv && overMapDiv) { │ │ │ │ │ + if (allowScroll) { │ │ │ │ │ + var delta = 0; │ │ │ │ │ + │ │ │ │ │ + if (e.wheelDelta) { │ │ │ │ │ + delta = e.wheelDelta; │ │ │ │ │ + if (delta % 160 === 0) { │ │ │ │ │ + // opera have steps of 160 instead of 120 │ │ │ │ │ + delta = delta * 0.75; │ │ │ │ │ + } │ │ │ │ │ + delta = delta / 120; │ │ │ │ │ + } else if (e.detail) { │ │ │ │ │ + // detail in Firefox on OS X is 1/3 of Windows │ │ │ │ │ + // so force delta 1 / -1 │ │ │ │ │ + delta = -(e.detail / Math.abs(e.detail)); │ │ │ │ │ + } │ │ │ │ │ + this.delta += delta; │ │ │ │ │ + │ │ │ │ │ + window.clearTimeout(this._timeoutId); │ │ │ │ │ + if (this.interval && Math.abs(this.delta) < this.maxDelta) { │ │ │ │ │ + // store e because window.event might change during delay │ │ │ │ │ + var evt = OpenLayers.Util.extend({}, e); │ │ │ │ │ + this._timeoutId = window.setTimeout( │ │ │ │ │ + OpenLayers.Function.bind(function() { │ │ │ │ │ + this.wheelZoom(evt); │ │ │ │ │ + }, this), │ │ │ │ │ + this.interval │ │ │ │ │ + ); │ │ │ │ │ + } else { │ │ │ │ │ + this.wheelZoom(e); │ │ │ │ │ + } │ │ │ │ │ } │ │ │ │ │ + OpenLayers.Event.stop(e); │ │ │ │ │ } │ │ │ │ │ - return layers; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: contextToMap │ │ │ │ │ - * Create a map given a context object. │ │ │ │ │ - * │ │ │ │ │ + * Method: wheelZoom │ │ │ │ │ + * Given the wheel event, we carry out the appropriate zooming in or out, │ │ │ │ │ + * based on the 'wheelDelta' or 'detail' property of the event. │ │ │ │ │ + * │ │ │ │ │ * Parameters: │ │ │ │ │ - * context - {Object} The context object. │ │ │ │ │ - * options - {Object} Default map options. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} A map based on the context object. │ │ │ │ │ + * e - {Event} │ │ │ │ │ */ │ │ │ │ │ - contextToMap: function(context, options) { │ │ │ │ │ - options = OpenLayers.Util.applyDefaults({ │ │ │ │ │ - maxExtent: context.maxExtent, │ │ │ │ │ - projection: context.projection, │ │ │ │ │ - units: context.units │ │ │ │ │ - }, options); │ │ │ │ │ + wheelZoom: function(e) { │ │ │ │ │ + var delta = this.delta; │ │ │ │ │ + this.delta = 0; │ │ │ │ │ │ │ │ │ │ - if (options.maxExtent) { │ │ │ │ │ - options.maxResolution = │ │ │ │ │ - options.maxExtent.getWidth() / OpenLayers.Map.TILE_WIDTH; │ │ │ │ │ + if (delta) { │ │ │ │ │ + e.xy = this.map.events.getMousePosition(e); │ │ │ │ │ + if (delta < 0) { │ │ │ │ │ + this.callback("down", │ │ │ │ │ + [e, this.cumulative ? Math.max(-this.maxDelta, delta) : -1]); │ │ │ │ │ + } else { │ │ │ │ │ + this.callback("up", │ │ │ │ │ + [e, this.cumulative ? Math.min(this.maxDelta, delta) : 1]); │ │ │ │ │ + } │ │ │ │ │ } │ │ │ │ │ - │ │ │ │ │ - var metadata = { │ │ │ │ │ - contactInformation: context.contactInformation, │ │ │ │ │ - "abstract": context["abstract"], │ │ │ │ │ - keywords: context.keywords, │ │ │ │ │ - logo: context.logo, │ │ │ │ │ - descriptionURL: context.descriptionURL │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - options.metadata = metadata; │ │ │ │ │ - │ │ │ │ │ - var map = new OpenLayers.Map(options); │ │ │ │ │ - map.addLayers(this.getLayersFromContext(context.layersContext)); │ │ │ │ │ - map.setCenter( │ │ │ │ │ - context.bounds.getCenterLonLat(), │ │ │ │ │ - map.getZoomForExtent(context.bounds, true) │ │ │ │ │ - ); │ │ │ │ │ - return map; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: mergeContextToMap │ │ │ │ │ - * Add layers from a context object to a map. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * context - {Object} The context object. │ │ │ │ │ - * map - {} The map. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {} The same map with layers added. │ │ │ │ │ + * Method: activate │ │ │ │ │ */ │ │ │ │ │ - mergeContextToMap: function(context, map) { │ │ │ │ │ - map.addLayers(this.getLayersFromContext(context.layersContext)); │ │ │ │ │ - return map; │ │ │ │ │ + activate: function(evt) { │ │ │ │ │ + if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) { │ │ │ │ │ + //register mousewheel events specifically on the window and document │ │ │ │ │ + var wheelListener = this.wheelListener; │ │ │ │ │ + OpenLayers.Event.observe(window, "DOMMouseScroll", wheelListener); │ │ │ │ │ + OpenLayers.Event.observe(window, "mousewheel", wheelListener); │ │ │ │ │ + OpenLayers.Event.observe(document, "mousewheel", wheelListener); │ │ │ │ │ + return true; │ │ │ │ │ + } else { │ │ │ │ │ + return false; │ │ │ │ │ + } │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: write │ │ │ │ │ - * Write a context document given a map. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * obj - { | Object} A map or context object. │ │ │ │ │ - * options - {Object} Optional configuration object. │ │ │ │ │ - * │ │ │ │ │ - * Returns: │ │ │ │ │ - * {String} A context document string. │ │ │ │ │ + * Method: deactivate │ │ │ │ │ */ │ │ │ │ │ - write: function(obj, options) { │ │ │ │ │ - obj = this.toContext(obj); │ │ │ │ │ - return OpenLayers.Format.XML.VersionedOGC.prototype.write.apply(this, │ │ │ │ │ - arguments); │ │ │ │ │ + deactivate: function(evt) { │ │ │ │ │ + if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { │ │ │ │ │ + // unregister mousewheel events specifically on the window and document │ │ │ │ │ + var wheelListener = this.wheelListener; │ │ │ │ │ + OpenLayers.Event.stopObserving(window, "DOMMouseScroll", wheelListener); │ │ │ │ │ + OpenLayers.Event.stopObserving(window, "mousewheel", wheelListener); │ │ │ │ │ + OpenLayers.Event.stopObserving(document, "mousewheel", wheelListener); │ │ │ │ │ + return true; │ │ │ │ │ + } else { │ │ │ │ │ + return false; │ │ │ │ │ + } │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ - CLASS_NAME: "OpenLayers.Format.Context" │ │ │ │ │ + CLASS_NAME: "OpenLayers.Handler.MouseWheel" │ │ │ │ │ }); │ │ │ │ │ - │ │ │ │ │ -/** │ │ │ │ │ - * Constant: OpenLayers.Format.Context.serviceTypes │ │ │ │ │ - * Enumeration for service types │ │ │ │ │ - */ │ │ │ │ │ -OpenLayers.Format.Context.serviceTypes = { │ │ │ │ │ - "WMS": "urn:ogc:serviceType:WMS", │ │ │ │ │ - "WFS": "urn:ogc:serviceType:WFS", │ │ │ │ │ - "WCS": "urn:ogc:serviceType:WCS", │ │ │ │ │ - "GML": "urn:ogc:serviceType:GML", │ │ │ │ │ - "SLD": "urn:ogc:serviceType:SLD", │ │ │ │ │ - "FES": "urn:ogc:serviceType:FES", │ │ │ │ │ - "KML": "urn:ogc:serviceType:KML" │ │ │ │ │ -}; │ │ │ │ │ /* ====================================================================== │ │ │ │ │ - OpenLayers/Format/KML.js │ │ │ │ │ + OpenLayers/Handler/Click.js │ │ │ │ │ ====================================================================== */ │ │ │ │ │ │ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for │ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license. │ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the │ │ │ │ │ * full text of the license. */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * @requires OpenLayers/BaseTypes/Date.js │ │ │ │ │ - * @requires OpenLayers/Format/XML.js │ │ │ │ │ - * @requires OpenLayers/Feature/Vector.js │ │ │ │ │ - * @requires OpenLayers/Geometry/Point.js │ │ │ │ │ - * @requires OpenLayers/Geometry/LineString.js │ │ │ │ │ - * @requires OpenLayers/Geometry/Polygon.js │ │ │ │ │ - * @requires OpenLayers/Geometry/Collection.js │ │ │ │ │ - * @requires OpenLayers/Request/XMLHttpRequest.js │ │ │ │ │ - * @requires OpenLayers/Projection.js │ │ │ │ │ + * @requires OpenLayers/Handler.js │ │ │ │ │ */ │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Class: OpenLayers.Format.KML │ │ │ │ │ - * Read/Write KML. Create a new instance with the │ │ │ │ │ - * constructor. │ │ │ │ │ + * Class: OpenLayers.Handler.Click │ │ │ │ │ + * A handler for mouse clicks. The intention of this handler is to give │ │ │ │ │ + * controls more flexibility with handling clicks. Browsers trigger │ │ │ │ │ + * click events twice for a double-click. In addition, the mousedown, │ │ │ │ │ + * mousemove, mouseup sequence fires a click event. With this handler, │ │ │ │ │ + * controls can decide whether to ignore clicks associated with a double │ │ │ │ │ + * click. By setting a , controls can also ignore clicks │ │ │ │ │ + * that include a drag. Create a new instance with the │ │ │ │ │ + * constructor. │ │ │ │ │ * │ │ │ │ │ * Inherits from: │ │ │ │ │ - * - │ │ │ │ │ + * - │ │ │ │ │ */ │ │ │ │ │ -OpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, { │ │ │ │ │ - │ │ │ │ │ +OpenLayers.Handler.Click = OpenLayers.Class(OpenLayers.Handler, { │ │ │ │ │ /** │ │ │ │ │ - * Property: namespaces │ │ │ │ │ - * {Object} Mapping of namespace aliases to namespace URIs. │ │ │ │ │ + * APIProperty: delay │ │ │ │ │ + * {Number} Number of milliseconds between clicks before the event is │ │ │ │ │ + * considered a double-click. │ │ │ │ │ */ │ │ │ │ │ - namespaces: { │ │ │ │ │ - kml: "http://www.opengis.net/kml/2.2", │ │ │ │ │ - gx: "http://www.google.com/kml/ext/2.2" │ │ │ │ │ - }, │ │ │ │ │ + delay: 300, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: kmlns │ │ │ │ │ - * {String} KML Namespace to use. Defaults to 2.0 namespace. │ │ │ │ │ - */ │ │ │ │ │ - kmlns: "http://earth.google.com/kml/2.0", │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: placemarksDesc │ │ │ │ │ - * {String} Name of the placemarks. Default is "No description available". │ │ │ │ │ - */ │ │ │ │ │ - placemarksDesc: "No description available", │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: foldersName │ │ │ │ │ - * {String} Name of the folders. Default is "OpenLayers export". │ │ │ │ │ - * If set to null, no name element will be created. │ │ │ │ │ - */ │ │ │ │ │ - foldersName: "OpenLayers export", │ │ │ │ │ - │ │ │ │ │ - /** │ │ │ │ │ - * APIProperty: foldersDesc │ │ │ │ │ - * {String} Description of the folders. Default is "Exported on [date]." │ │ │ │ │ - * If set to null, no description element will be created. │ │ │ │ │ + * APIProperty: single │ │ │ │ │ + * {Boolean} Handle single clicks. Default is true. If false, clicks │ │ │ │ │ + * will not be reported. If true, single-clicks will be reported. │ │ │ │ │ */ │ │ │ │ │ - foldersDesc: "Exported on " + new Date(), │ │ │ │ │ + single: true, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: extractAttributes │ │ │ │ │ - * {Boolean} Extract attributes from KML. Default is true. │ │ │ │ │ - * Extracting styleUrls requires this to be set to true │ │ │ │ │ - * Note that currently only Data and SimpleData │ │ │ │ │ - * elements are handled. │ │ │ │ │ + * APIProperty: double │ │ │ │ │ + * {Boolean} Handle double-clicks. Default is false. │ │ │ │ │ */ │ │ │ │ │ - extractAttributes: true, │ │ │ │ │ + 'double': false, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: kvpAttributes │ │ │ │ │ - * {Boolean} Only used if extractAttributes is true. │ │ │ │ │ - * If set to true, attributes will be simple │ │ │ │ │ - * key-value pairs, compatible with other formats, │ │ │ │ │ - * Any displayName elements will be ignored. │ │ │ │ │ - * If set to false, attributes will be objects, │ │ │ │ │ - * retaining any displayName elements, but not │ │ │ │ │ - * compatible with other formats. Any CDATA in │ │ │ │ │ - * displayName will be read in as a string value. │ │ │ │ │ - * Default is false. │ │ │ │ │ + * APIProperty: pixelTolerance │ │ │ │ │ + * {Number} Maximum number of pixels between mouseup and mousedown for an │ │ │ │ │ + * event to be considered a click. Default is 0. If set to an │ │ │ │ │ + * integer value, clicks with a drag greater than the value will be │ │ │ │ │ + * ignored. This property can only be set when the handler is │ │ │ │ │ + * constructed. │ │ │ │ │ */ │ │ │ │ │ - kvpAttributes: false, │ │ │ │ │ + pixelTolerance: 0, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: extractStyles │ │ │ │ │ - * {Boolean} Extract styles from KML. Default is false. │ │ │ │ │ - * Extracting styleUrls also requires extractAttributes to be │ │ │ │ │ - * set to true │ │ │ │ │ + * APIProperty: dblclickTolerance │ │ │ │ │ + * {Number} Maximum distance in pixels between clicks for a sequence of │ │ │ │ │ + * events to be considered a double click. Default is 13. If the │ │ │ │ │ + * distance between two clicks is greater than this value, a double- │ │ │ │ │ + * click will not be fired. │ │ │ │ │ */ │ │ │ │ │ - extractStyles: false, │ │ │ │ │ + dblclickTolerance: 13, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: extractTracks │ │ │ │ │ - * {Boolean} Extract gx:Track elements from Placemark elements. Default │ │ │ │ │ - * is false. If true, features will be generated for all points in │ │ │ │ │ - * all gx:Track elements. Features will have a when (Date) attribute │ │ │ │ │ - * based on when elements in the track. If tracks include angle │ │ │ │ │ - * elements, features will have heading, tilt, and roll attributes. │ │ │ │ │ - * If track point coordinates have three values, features will have │ │ │ │ │ - * an altitude attribute with the third coordinate value. │ │ │ │ │ + * APIProperty: stopSingle │ │ │ │ │ + * {Boolean} Stop other listeners from being notified of clicks. Default │ │ │ │ │ + * is false. If true, any listeners registered before this one for │ │ │ │ │ + * click or rightclick events will not be notified. │ │ │ │ │ */ │ │ │ │ │ - extractTracks: false, │ │ │ │ │ + stopSingle: false, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: trackAttributes │ │ │ │ │ - * {Array} If is true, points within gx:Track elements will │ │ │ │ │ - * be parsed as features with when, heading, tilt, and roll attributes. │ │ │ │ │ - * Any additional attribute names can be provided in . │ │ │ │ │ + * APIProperty: stopDouble │ │ │ │ │ + * {Boolean} Stop other listeners from being notified of double-clicks. │ │ │ │ │ + * Default is false. If true, any click listeners registered before │ │ │ │ │ + * this one will not be notified of *any* double-click events. │ │ │ │ │ + * │ │ │ │ │ + * The one caveat with stopDouble is that given a map with two click │ │ │ │ │ + * handlers, one with stopDouble true and the other with stopSingle │ │ │ │ │ + * true, the stopSingle handler should be activated last to get │ │ │ │ │ + * uniform cross-browser performance. Since IE triggers one click │ │ │ │ │ + * with a dblclick and FF triggers two, if a stopSingle handler is │ │ │ │ │ + * activated first, all it gets in IE is a single click when the │ │ │ │ │ + * second handler stops propagation on the dblclick. │ │ │ │ │ */ │ │ │ │ │ - trackAttributes: null, │ │ │ │ │ + stopDouble: false, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: internalns │ │ │ │ │ - * {String} KML Namespace to use -- defaults to the namespace of the │ │ │ │ │ - * Placemark node being parsed, but falls back to kmlns. │ │ │ │ │ + * Property: timerId │ │ │ │ │ + * {Number} The id of the timeout waiting to clear the . │ │ │ │ │ */ │ │ │ │ │ - internalns: null, │ │ │ │ │ + timerId: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: features │ │ │ │ │ - * {Array} Array of features │ │ │ │ │ - * │ │ │ │ │ + * Property: down │ │ │ │ │ + * {Object} Object that store relevant information about the last │ │ │ │ │ + * mousedown or touchstart. Its 'xy' OpenLayers.Pixel property gives │ │ │ │ │ + * the average location of the mouse/touch event. Its 'touches' │ │ │ │ │ + * property records clientX/clientY of each touches. │ │ │ │ │ */ │ │ │ │ │ - features: null, │ │ │ │ │ + down: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: styles │ │ │ │ │ - * {Object} Storage of style objects │ │ │ │ │ - * │ │ │ │ │ + * Property: last │ │ │ │ │ + * {Object} Object that store relevant information about the last │ │ │ │ │ + * mousemove or touchmove. Its 'xy' OpenLayers.Pixel property gives │ │ │ │ │ + * the average location of the mouse/touch event. Its 'touches' │ │ │ │ │ + * property records clientX/clientY of each touches. │ │ │ │ │ */ │ │ │ │ │ - styles: null, │ │ │ │ │ + last: null, │ │ │ │ │ │ │ │ │ │ - /** │ │ │ │ │ - * Property: styleBaseUrl │ │ │ │ │ - * {String} │ │ │ │ │ + /** │ │ │ │ │ + * Property: first │ │ │ │ │ + * {Object} When waiting for double clicks, this object will store │ │ │ │ │ + * information about the first click in a two click sequence. │ │ │ │ │ */ │ │ │ │ │ - styleBaseUrl: "", │ │ │ │ │ + first: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Property: fetched │ │ │ │ │ - * {Object} Storage of KML URLs that have been fetched before │ │ │ │ │ - * in order to prevent reloading them. │ │ │ │ │ + * Property: rightclickTimerId │ │ │ │ │ + * {Number} The id of the right mouse timeout waiting to clear the │ │ │ │ │ + * . │ │ │ │ │ */ │ │ │ │ │ - fetched: null, │ │ │ │ │ + rightclickTimerId: null, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIProperty: maxDepth │ │ │ │ │ - * {Integer} Maximum depth for recursive loading external KML URLs │ │ │ │ │ - * Defaults to 0: do no external fetching │ │ │ │ │ + * Constructor: OpenLayers.Handler.Click │ │ │ │ │ + * Create a new click handler. │ │ │ │ │ + * │ │ │ │ │ + * Parameters: │ │ │ │ │ + * control - {} The control that is making use of │ │ │ │ │ + * this handler. If a handler is being used without a control, the │ │ │ │ │ + * handler's setMap method must be overridden to deal properly with │ │ │ │ │ + * the map. │ │ │ │ │ + * callbacks - {Object} An object with keys corresponding to callbacks │ │ │ │ │ + * that will be called by the handler. The callbacks should │ │ │ │ │ + * expect to recieve a single argument, the click event. │ │ │ │ │ + * Callbacks for 'click' and 'dblclick' are supported. │ │ │ │ │ + * options - {Object} Optional object whose properties will be set on the │ │ │ │ │ + * handler. │ │ │ │ │ */ │ │ │ │ │ - maxDepth: 0, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Constructor: OpenLayers.Format.KML │ │ │ │ │ - * Create a new parser for KML. │ │ │ │ │ + * Method: touchstart │ │ │ │ │ + * Handle touchstart. │ │ │ │ │ * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * options - {Object} An optional object whose properties will be set on │ │ │ │ │ - * this instance. │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Continue propagating this event. │ │ │ │ │ */ │ │ │ │ │ - initialize: function(options) { │ │ │ │ │ - // compile regular expressions once instead of every time they are used │ │ │ │ │ - this.regExes = { │ │ │ │ │ - trimSpace: (/^\s*|\s*$/g), │ │ │ │ │ - removeSpace: (/\s*/g), │ │ │ │ │ - splitSpace: (/\s+/), │ │ │ │ │ - trimComma: (/\s*,\s*/g), │ │ │ │ │ - kmlColor: (/(\w{2})(\w{2})(\w{2})(\w{2})/), │ │ │ │ │ - kmlIconPalette: (/root:\/\/icons\/palette-(\d+)(\.\w+)/), │ │ │ │ │ - straightBracket: (/\$\[(.*?)\]/g) │ │ │ │ │ - }; │ │ │ │ │ - // KML coordinates are always in longlat WGS84 │ │ │ │ │ - this.externalProjection = new OpenLayers.Projection("EPSG:4326"); │ │ │ │ │ - │ │ │ │ │ - OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); │ │ │ │ │ + touchstart: function(evt) { │ │ │ │ │ + this.startTouch(); │ │ │ │ │ + this.down = this.getEventInfo(evt); │ │ │ │ │ + this.last = this.getEventInfo(evt); │ │ │ │ │ + return true; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * APIMethod: read │ │ │ │ │ - * Read data from a string, and return a list of features. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * data - {String} or {DOMElement} data to read/parse. │ │ │ │ │ + * Method: touchmove │ │ │ │ │ + * Store position of last move, because touchend event can have │ │ │ │ │ + * an empty "touches" property. │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Array()} List of features. │ │ │ │ │ + * {Boolean} Continue propagating this event. │ │ │ │ │ */ │ │ │ │ │ - read: function(data) { │ │ │ │ │ - this.features = []; │ │ │ │ │ - this.styles = {}; │ │ │ │ │ - this.fetched = {}; │ │ │ │ │ - │ │ │ │ │ - // Set default options │ │ │ │ │ - var options = { │ │ │ │ │ - depth: 0, │ │ │ │ │ - styleBaseUrl: this.styleBaseUrl │ │ │ │ │ - }; │ │ │ │ │ - │ │ │ │ │ - return this.parseData(data, options); │ │ │ │ │ + touchmove: function(evt) { │ │ │ │ │ + this.last = this.getEventInfo(evt); │ │ │ │ │ + return true; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: parseData │ │ │ │ │ - * Read data from a string, and return a list of features. │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * data - {String} or {DOMElement} data to read/parse. │ │ │ │ │ - * options - {Object} Hash of options │ │ │ │ │ + * Method: touchend │ │ │ │ │ + * Correctly set event xy property, and add lastTouches to have │ │ │ │ │ + * touches property from last touchstart or touchmove │ │ │ │ │ * │ │ │ │ │ * Returns: │ │ │ │ │ - * {Array()} List of features. │ │ │ │ │ + * {Boolean} Continue propagating this event. │ │ │ │ │ */ │ │ │ │ │ - parseData: function(data, options) { │ │ │ │ │ - if (typeof data == "string") { │ │ │ │ │ - data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // Loop throught the following node types in this order and │ │ │ │ │ - // process the nodes found │ │ │ │ │ - var types = ["Link", "NetworkLink", "Style", "StyleMap", "Placemark"]; │ │ │ │ │ - for (var i = 0, len = types.length; i < len; ++i) { │ │ │ │ │ - var type = types[i]; │ │ │ │ │ - │ │ │ │ │ - var nodes = this.getElementsByTagNameNS(data, "*", type); │ │ │ │ │ - │ │ │ │ │ - // skip to next type if no nodes are found │ │ │ │ │ - if (nodes.length == 0) { │ │ │ │ │ - continue; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - switch (type.toLowerCase()) { │ │ │ │ │ - │ │ │ │ │ - // Fetch external links │ │ │ │ │ - case "link": │ │ │ │ │ - case "networklink": │ │ │ │ │ - this.parseLinks(nodes, options); │ │ │ │ │ - break; │ │ │ │ │ - │ │ │ │ │ - // parse style information │ │ │ │ │ - case "style": │ │ │ │ │ - if (this.extractStyles) { │ │ │ │ │ - this.parseStyles(nodes, options); │ │ │ │ │ - } │ │ │ │ │ - break; │ │ │ │ │ - case "stylemap": │ │ │ │ │ - if (this.extractStyles) { │ │ │ │ │ - this.parseStyleMaps(nodes, options); │ │ │ │ │ - } │ │ │ │ │ - break; │ │ │ │ │ - │ │ │ │ │ - // parse features │ │ │ │ │ - case "placemark": │ │ │ │ │ - this.parseFeatures(nodes, options); │ │ │ │ │ - break; │ │ │ │ │ - } │ │ │ │ │ + touchend: function(evt) { │ │ │ │ │ + // touchstart may not have been allowed to propagate │ │ │ │ │ + if (this.down) { │ │ │ │ │ + evt.xy = this.last.xy; │ │ │ │ │ + evt.lastTouches = this.last.touches; │ │ │ │ │ + this.handleSingle(evt); │ │ │ │ │ + this.down = null; │ │ │ │ │ } │ │ │ │ │ + return true; │ │ │ │ │ + }, │ │ │ │ │ │ │ │ │ │ - return this.features; │ │ │ │ │ + /** │ │ │ │ │ + * Method: mousedown │ │ │ │ │ + * Handle mousedown. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Continue propagating this event. │ │ │ │ │ + */ │ │ │ │ │ + mousedown: function(evt) { │ │ │ │ │ + this.down = this.getEventInfo(evt); │ │ │ │ │ + this.last = this.getEventInfo(evt); │ │ │ │ │ + return true; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: parseLinks │ │ │ │ │ - * Finds URLs of linked KML documents and fetches them │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * nodes - {Array} of {DOMElement} data to read/parse. │ │ │ │ │ - * options - {Object} Hash of options │ │ │ │ │ + * Method: mouseup │ │ │ │ │ + * Handle mouseup. Installed to support collection of right mouse events. │ │ │ │ │ * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Continue propagating this event. │ │ │ │ │ */ │ │ │ │ │ - parseLinks: function(nodes, options) { │ │ │ │ │ - │ │ │ │ │ - // Fetch external links and │ │ │ │ │ - // Don't do anything if we have reached our maximum depth for recursion │ │ │ │ │ - if (options.depth >= this.maxDepth) { │ │ │ │ │ - return false; │ │ │ │ │ - } │ │ │ │ │ - │ │ │ │ │ - // increase depth │ │ │ │ │ - var newOptions = OpenLayers.Util.extend({}, options); │ │ │ │ │ - newOptions.depth++; │ │ │ │ │ + mouseup: function(evt) { │ │ │ │ │ + var propagate = true; │ │ │ │ │ │ │ │ │ │ - for (var i = 0, len = nodes.length; i < len; i++) { │ │ │ │ │ - var href = this.parseProperty(nodes[i], "*", "href"); │ │ │ │ │ - if (href && !this.fetched[href]) { │ │ │ │ │ - this.fetched[href] = true; // prevent reloading the same urls │ │ │ │ │ - var data = this.fetchLink(href); │ │ │ │ │ - if (data) { │ │ │ │ │ - this.parseData(data, newOptions); │ │ │ │ │ - } │ │ │ │ │ - } │ │ │ │ │ + // Collect right mouse clicks from the mouseup │ │ │ │ │ + // IE - ignores the second right click in mousedown so using │ │ │ │ │ + // mouseup instead │ │ │ │ │ + if (this.checkModifiers(evt) && this.control.handleRightClicks && │ │ │ │ │ + OpenLayers.Event.isRightClick(evt)) { │ │ │ │ │ + propagate = this.rightclick(evt); │ │ │ │ │ } │ │ │ │ │ │ │ │ │ │ + return propagate; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: fetchLink │ │ │ │ │ - * Fetches a URL and returns the result │ │ │ │ │ - * │ │ │ │ │ - * Parameters: │ │ │ │ │ - * href - {String} url to be fetched │ │ │ │ │ - * │ │ │ │ │ + * Method: rightclick │ │ │ │ │ + * Handle rightclick. For a dblrightclick, we get two clicks so we need │ │ │ │ │ + * to always register for dblrightclick to properly handle single │ │ │ │ │ + * clicks. │ │ │ │ │ + * │ │ │ │ │ + * Returns: │ │ │ │ │ + * {Boolean} Continue propagating this event. │ │ │ │ │ */ │ │ │ │ │ - fetchLink: function(href) { │ │ │ │ │ - var request = OpenLayers.Request.GET({ │ │ │ │ │ - url: href, │ │ │ │ │ - async: false │ │ │ │ │ - }); │ │ │ │ │ - if (request) { │ │ │ │ │ - return request.responseText; │ │ │ │ │ + rightclick: function(evt) { │ │ │ │ │ + if (this.passesTolerance(evt)) { │ │ │ │ │ + if (this.rightclickTimerId != null) { │ │ │ │ │ + //Second click received before timeout this must be │ │ │ │ │ + // a double click │ │ │ │ │ + this.clearTimer(); │ │ │ │ │ + this.callback('dblrightclick', [evt]); │ │ │ │ │ + return !this.stopDouble; │ │ │ │ │ + } else { │ │ │ │ │ + //Set the rightclickTimerId, send evt only if double is │ │ │ │ │ + // true else trigger single │ │ │ │ │ + var clickEvent = this['double'] ? │ │ │ │ │ + OpenLayers.Util.extend({}, evt) : │ │ │ │ │ + this.callback('rightclick', [evt]); │ │ │ │ │ + │ │ │ │ │ + var delayedRightCall = OpenLayers.Function.bind( │ │ │ │ │ + this.delayedRightCall, │ │ │ │ │ + this, │ │ │ │ │ + clickEvent │ │ │ │ │ + ); │ │ │ │ │ + this.rightclickTimerId = window.setTimeout( │ │ │ │ │ + delayedRightCall, this.delay │ │ │ │ │ + ); │ │ │ │ │ + } │ │ │ │ │ } │ │ │ │ │ + return !this.stopSingle; │ │ │ │ │ }, │ │ │ │ │ │ │ │ │ │ /** │ │ │ │ │ - * Method: parseStyles │ │ │ │ │ - * Parses