From e30f267181d990947e67909de4809fa941698c85 Mon Sep 17 00:00:00 2001 From: Chris Schlaeger Date: Sat, 17 Oct 2015 21:36:38 +0200 Subject: Upgrading openlayers to 3.x --- misc/openlayers/OpenLayers.mobile.debug.js | 41831 --------------------------- 1 file changed, 41831 deletions(-) delete mode 100644 misc/openlayers/OpenLayers.mobile.debug.js (limited to 'misc/openlayers/OpenLayers.mobile.debug.js') diff --git a/misc/openlayers/OpenLayers.mobile.debug.js b/misc/openlayers/OpenLayers.mobile.debug.js deleted file mode 100644 index 5cb37cd..0000000 --- a/misc/openlayers/OpenLayers.mobile.debug.js +++ /dev/null @@ -1,41831 +0,0 @@ -/* - - OpenLayers.js -- OpenLayers Map Viewer Library - - Copyright (c) 2006-2013 by OpenLayers Contributors - Published under the 2-clause BSD license. - See http://openlayers.org/dev/license.txt for the full text of the license, and http://openlayers.org/dev/authors.txt for full list of contributors. - - Includes compressed code under the following licenses: - - (For uncompressed versions of the code used, please see the - OpenLayers Github repository: ) - -*/ - -/** - * Contains XMLHttpRequest.js - * Copyright 2007 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 - */ - -/** - * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is - * Copyright (c) 2006, Yahoo! Inc. - * All rights reserved. - * - * Redistribution and use of this software in source and binary forms, with or - * without modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Yahoo! Inc. nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission of Yahoo! Inc. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * 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. - */ -/* ====================================================================== - 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. */ - -var OpenLayers = { - /** - * Constant: VERSION_NUMBER - */ - VERSION_NUMBER: "Release 2.13.1", - - /** - * Constant: singleFile - * TODO: remove this in 3.0 when we stop supporting build profiles that - * include OpenLayers.js - */ - singleFile: true, - - /** - * Method: _getScriptLocation - * Return the path to this script. This is also implemented in - * OpenLayers.js - * - * Returns: - * {String} Path to this script - */ - _getScriptLocation: (function() { - var r = new RegExp("(^|(.*?\\/))(OpenLayers[^\\/]*?\\.js)(\\?|$)"), - s = document.getElementsByTagName('script'), - src, m, l = ""; - for(var i=0, len=s.length; i - * - * (end code) - * - * Please remember that when your OpenLayers script is not named - * "OpenLayers.js" you will have to make sure that the default theme is - * loaded into the page by including an appropriate -tag, - * e.g.: - * - * (code) - * - * (end code) - */ - ImgPath : '' -}; -/* ====================================================================== - 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. */ - -/** - * @requires OpenLayers/SingleFile.js - */ - -/** - * Header: OpenLayers Base Types - * OpenLayers custom string, number and function functions are described here. - */ - -/** - * Namespace: OpenLayers.String - * Contains convenience functions for string manipulation. - */ -OpenLayers.String = { - - /** - * APIFunction: startsWith - * Test whether a string starts with another string. - * - * Parameters: - * str - {String} The string to test. - * sub - {String} The substring to look for. - * - * Returns: - * {Boolean} The first string starts with the second. - */ - startsWith: function(str, sub) { - return (str.indexOf(sub) == 0); - }, - - /** - * APIFunction: contains - * Test whether a string contains another string. - * - * Parameters: - * str - {String} The string to test. - * sub - {String} The substring to look for. - * - * Returns: - * {Boolean} The first string contains the second. - */ - contains: function(str, sub) { - return (str.indexOf(sub) != -1); - }, - - /** - * APIFunction: trim - * Removes leading and trailing whitespace characters from a string. - * - * Parameters: - * str - {String} The (potentially) space padded string. This string is not - * modified. - * - * Returns: - * {String} A trimmed version of the string with all leading and - * trailing spaces removed. - */ - trim: function(str) { - return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }, - - /** - * APIFunction: camelize - * Camel-case a hyphenated string. - * Ex. "chicken-head" becomes "chickenHead", and - * "-chicken-head" becomes "ChickenHead". - * - * Parameters: - * str - {String} The string to be camelized. The original is not modified. - * - * Returns: - * {String} The string, camelized - */ - camelize: function(str) { - var oStringList = str.split('-'); - var camelizedString = oStringList[0]; - for (var i=1, len=oStringList.length; i replacement = context[a]; - // 1 -> replacement = context[a][b]; - // 2 -> replacement = context[a][b][c]; - var subs = match.split(/\.+/); - for (var i=0; i< subs.length; i++) { - if (i == 0) { - replacement = context; - } - if (replacement === undefined) { - break; - } - replacement = replacement[subs[i]]; - } - - if(typeof replacement == "function") { - replacement = args ? - replacement.apply(null, args) : - replacement(); - } - - // If replacement is undefined, return the string 'undefined'. - // This is a workaround for a bugs in browsers not properly - // dealing with non-participating groups in regular expressions: - // http://blog.stevenlevithan.com/archives/npcg-javascript - if (typeof replacement == 'undefined') { - return 'undefined'; - } else { - return replacement; - } - }; - - return template.replace(OpenLayers.String.tokenRegEx, replacer); - }, - - /** - * Property: tokenRegEx - * Used to find tokens in a string. - * Examples: ${a}, ${a.b.c}, ${a-b}, ${5} - */ - tokenRegEx: /\$\{([\w.]+?)\}/g, - - /** - * Property: numberRegEx - * Used to test strings as numbers. - */ - numberRegEx: /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/, - - /** - * APIFunction: isNumeric - * Determine whether a string contains only a numeric value. - * - * Examples: - * (code) - * OpenLayers.String.isNumeric("6.02e23") // true - * OpenLayers.String.isNumeric("12 dozen") // false - * OpenLayers.String.isNumeric("4") // true - * OpenLayers.String.isNumeric(" 4 ") // false - * (end) - * - * Returns: - * {Boolean} String contains only a number. - */ - isNumeric: function(value) { - return OpenLayers.String.numberRegEx.test(value); - }, - - /** - * APIFunction: numericIf - * Converts a string that appears to be a numeric value into a number. - * - * Parameters: - * value - {String} - * trimWhitespace - {Boolean} - * - * Returns: - * {Number|String} a Number if the passed value is a number, a String - * otherwise. - */ - numericIf: function(value, trimWhitespace) { - var originalValue = value; - if (trimWhitespace === true && value != null && value.replace) { - value = value.replace(/^\s*|\s*$/g, ""); - } - return OpenLayers.String.isNumeric(value) ? parseFloat(value) : originalValue; - } - -}; - -/** - * Namespace: OpenLayers.Number - * Contains convenience functions for manipulating numbers. - */ -OpenLayers.Number = { - - /** - * Property: decimalSeparator - * Decimal separator to use when formatting numbers. - */ - decimalSeparator: ".", - - /** - * Property: thousandsSeparator - * Thousands separator to use when formatting numbers. - */ - thousandsSeparator: ",", - - /** - * APIFunction: limitSigDigs - * Limit the number of significant digits on a float. - * - * Parameters: - * num - {Float} - * sig - {Integer} - * - * Returns: - * {Float} The number, rounded to the specified number of significant - * digits. - */ - limitSigDigs: function(num, sig) { - var fig = 0; - if (sig > 0) { - fig = parseFloat(num.toPrecision(sig)); - } - return fig; - }, - - /** - * APIFunction: format - * Formats a number for output. - * - * Parameters: - * num - {Float} - * dec - {Integer} Number of decimal places to round to. - * Defaults to 0. Set to null to leave decimal places unchanged. - * tsep - {String} Thousands separator. - * Default is ",". - * dsep - {String} Decimal separator. - * Default is ".". - * - * Returns: - * {String} A string representing the formatted number. - */ - format: function(num, dec, tsep, dsep) { - dec = (typeof dec != "undefined") ? dec : 0; - tsep = (typeof tsep != "undefined") ? tsep : - OpenLayers.Number.thousandsSeparator; - dsep = (typeof dsep != "undefined") ? dsep : - OpenLayers.Number.decimalSeparator; - - if (dec != null) { - num = parseFloat(num.toFixed(dec)); - } - - var parts = num.toString().split("."); - if (parts.length == 1 && dec == null) { - // integer where we do not want to touch the decimals - dec = 0; - } - - var integer = parts[0]; - if (tsep) { - var thousands = /(-?[0-9]+)([0-9]{3})/; - while(thousands.test(integer)) { - integer = integer.replace(thousands, "$1" + tsep + "$2"); - } - } - - var str; - if (dec == 0) { - str = integer; - } else { - var rem = parts.length > 1 ? parts[1] : "0"; - if (dec != null) { - rem = rem + new Array(dec - rem.length + 1).join("0"); - } - str = integer + dsep + rem; - } - return str; - }, - - /** - * Method: zeroPad - * Create a zero padded string optionally with a radix for casting numbers. - * - * Parameters: - * num - {Number} The number to be zero padded. - * len - {Number} The length of the string to be returned. - * radix - {Number} An integer between 2 and 36 specifying the base to use - * for representing numeric values. - */ - zeroPad: function(num, len, radix) { - var str = num.toString(radix || 10); - while (str.length < len) { - str = "0" + str; - } - return str; - } -}; - -/** - * Namespace: OpenLayers.Function - * Contains convenience functions for function manipulation. - */ -OpenLayers.Function = { - /** - * APIFunction: bind - * Bind a function to an object. Method to easily create closures with - * 'this' altered. - * - * Parameters: - * func - {Function} Input function. - * object - {Object} The object to bind to the input function (as this). - * - * Returns: - * {Function} A closure with 'this' set to the passed in object. - */ - bind: function(func, object) { - // create a reference to all arguments past the second one - var args = Array.prototype.slice.apply(arguments, [2]); - return function() { - // Push on any additional arguments from the actual function call. - // These will come after those sent to the bind call. - var newArgs = args.concat( - Array.prototype.slice.apply(arguments, [0]) - ); - return func.apply(object, newArgs); - }; - }, - - /** - * APIFunction: bindAsEventListener - * Bind a function to an object, and configure it to receive the event - * object as first parameter when called. - * - * Parameters: - * func - {Function} Input function to serve as an event listener. - * object - {Object} A reference to this. - * - * Returns: - * {Function} - */ - bindAsEventListener: function(func, object) { - return function(event) { - return func.call(object, event || window.event); - }; - }, - - /** - * APIFunction: False - * A simple function to that just does "return false". We use this to - * avoid attaching anonymous functions to DOM event handlers, which - * causes "issues" on IE<8. - * - * Usage: - * document.onclick = OpenLayers.Function.False; - * - * Returns: - * {Boolean} - */ - False : function() { - return false; - }, - - /** - * APIFunction: True - * A simple function to that just does "return true". We use this to - * avoid attaching anonymous functions to DOM event handlers, which - * causes "issues" on IE<8. - * - * Usage: - * document.onclick = OpenLayers.Function.True; - * - * Returns: - * {Boolean} - */ - True : function() { - return true; - }, - - /** - * APIFunction: Void - * A reusable function that returns ``undefined``. - * - * Returns: - * {undefined} - */ - Void: function() {} - -}; - -/** - * Namespace: OpenLayers.Array - * Contains convenience functions for array manipulation. - */ -OpenLayers.Array = { - - /** - * APIMethod: filter - * Filter an array. Provides the functionality of the - * Array.prototype.filter extension to the ECMA-262 standard. Where - * available, Array.prototype.filter will be used. - * - * Based on well known example from http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter - * - * Parameters: - * array - {Array} The array to be filtered. This array is not mutated. - * Elements added to this array by the callback will not be visited. - * callback - {Function} A function that is called for each element in - * the array. If this function returns true, the element will be - * included in the return. The function will be called with three - * arguments: the element in the array, the index of that element, and - * the array itself. If the optional caller parameter is specified - * the callback will be called with this set to caller. - * caller - {Object} Optional object to be set as this when the callback - * is called. - * - * Returns: - * {Array} An array of elements from the passed in array for which the - * callback returns true. - */ - filter: function(array, callback, caller) { - var selected = []; - if (Array.prototype.filter) { - selected = array.filter(callback, caller); - } else { - var len = array.length; - if (typeof callback != "function") { - throw new TypeError(); - } - for(var i=0; i 1) { - var newArgs = [C, P].concat( - Array.prototype.slice.call(arguments).slice(1, len-1), F); - OpenLayers.inherit.apply(null, newArgs); - } else { - C.prototype = F; - } - return C; -}; - -/** - * Function: OpenLayers.inherit - * - * Parameters: - * C - {Object} the class that inherits - * P - {Object} the superclass to inherit from - * - * In addition to the mandatory C and P parameters, an arbitrary number of - * objects can be passed, which will extend C. - */ -OpenLayers.inherit = function(C, P) { - var F = function() {}; - F.prototype = P.prototype; - C.prototype = new F; - var i, l, o; - for(i=2, l=arguments.length; i} A cached center location. This should not be - * accessed directly. Use instead. - */ - centerLonLat: null, - - /** - * Constructor: OpenLayers.Bounds - * Construct a new bounds object. Coordinates can either be passed as four - * arguments, or as a single argument. - * - * Parameters (four arguments): - * left - {Number} The left bounds of the box. Note that for width - * calculations, this is assumed to be less than the right value. - * bottom - {Number} The bottom bounds of the box. Note that for height - * calculations, this is assumed to be less than the top value. - * right - {Number} The right bounds. - * top - {Number} The top bounds. - * - * Parameters (single argument): - * bounds - {Array(Number)} [left, bottom, right, top] - */ - initialize: function(left, bottom, right, top) { - if (OpenLayers.Util.isArray(left)) { - top = left[3]; - right = left[2]; - bottom = left[1]; - left = left[0]; - } - if (left != null) { - this.left = OpenLayers.Util.toFloat(left); - } - if (bottom != null) { - this.bottom = OpenLayers.Util.toFloat(bottom); - } - if (right != null) { - this.right = OpenLayers.Util.toFloat(right); - } - if (top != null) { - this.top = OpenLayers.Util.toFloat(top); - } - }, - - /** - * Method: clone - * Create a cloned instance of this bounds. - * - * Returns: - * {} A fresh copy of the bounds - */ - clone:function() { - return new OpenLayers.Bounds(this.left, this.bottom, - this.right, this.top); - }, - - /** - * Method: equals - * Test a two bounds for equivalence. - * - * Parameters: - * bounds - {} - * - * Returns: - * {Boolean} The passed-in bounds object has the same left, - * right, top, bottom components as this. Note that if bounds - * passed in is null, returns false. - */ - equals:function(bounds) { - var equals = false; - if (bounds != null) { - equals = ((this.left == bounds.left) && - (this.right == bounds.right) && - (this.top == bounds.top) && - (this.bottom == bounds.bottom)); - } - return equals; - }, - - /** - * APIMethod: toString - * Returns a string representation of the bounds object. - * - * Returns: - * {String} String representation of bounds object. - */ - toString:function() { - return [this.left, this.bottom, this.right, this.top].join(","); - }, - - /** - * APIMethod: toArray - * Returns an array representation of the bounds object. - * - * Returns an array of left, bottom, right, top properties, or -- when the - * optional parameter is true -- an array of the bottom, left, top, - * right properties. - * - * Parameters: - * reverseAxisOrder - {Boolean} Should we reverse the axis order? - * - * Returns: - * {Array} array of left, bottom, right, top - */ - toArray: function(reverseAxisOrder) { - if (reverseAxisOrder === true) { - return [this.bottom, this.left, this.top, this.right]; - } else { - return [this.left, this.bottom, this.right, this.top]; - } - }, - - /** - * APIMethod: toBBOX - * Returns a boundingbox-string representation of the bounds object. - * - * Parameters: - * decimal - {Integer} How many significant digits in the bbox coords? - * Default is 6 - * reverseAxisOrder - {Boolean} Should we reverse the axis order? - * - * Returns: - * {String} Simple String representation of bounds object. - * (e.g. "5,42,10,45") - */ - toBBOX:function(decimal, reverseAxisOrder) { - if (decimal== null) { - decimal = 6; - } - var mult = Math.pow(10, decimal); - var xmin = Math.round(this.left * mult) / mult; - var ymin = Math.round(this.bottom * mult) / mult; - var xmax = Math.round(this.right * mult) / mult; - var ymax = Math.round(this.top * mult) / mult; - if (reverseAxisOrder === true) { - return ymin + "," + xmin + "," + ymax + "," + xmax; - } else { - return xmin + "," + ymin + "," + xmax + "," + ymax; - } - }, - - /** - * APIMethod: toGeometry - * Create a new polygon geometry based on this bounds. - * - * Returns: - * {} A new polygon with the coordinates - * of this bounds. - */ - toGeometry: function() { - return new OpenLayers.Geometry.Polygon([ - new OpenLayers.Geometry.LinearRing([ - new OpenLayers.Geometry.Point(this.left, this.bottom), - new OpenLayers.Geometry.Point(this.right, this.bottom), - new OpenLayers.Geometry.Point(this.right, this.top), - new OpenLayers.Geometry.Point(this.left, this.top) - ]) - ]); - }, - - /** - * APIMethod: getWidth - * Returns the width of the bounds. - * - * Returns: - * {Float} The width of the bounds (right minus left). - */ - getWidth:function() { - return (this.right - this.left); - }, - - /** - * APIMethod: getHeight - * Returns the height of the bounds. - * - * Returns: - * {Float} The height of the bounds (top minus bottom). - */ - getHeight:function() { - return (this.top - this.bottom); - }, - - /** - * APIMethod: getSize - * Returns an object of the bounds. - * - * Returns: - * {} The size of the bounds. - */ - getSize:function() { - return new OpenLayers.Size(this.getWidth(), this.getHeight()); - }, - - /** - * APIMethod: getCenterPixel - * Returns the object which represents the center of the - * bounds. - * - * Returns: - * {} The center of the bounds in pixel space. - */ - getCenterPixel:function() { - return new OpenLayers.Pixel( (this.left + this.right) / 2, - (this.bottom + this.top) / 2); - }, - - /** - * APIMethod: getCenterLonLat - * Returns the object which represents the center of the - * bounds. - * - * Returns: - * {} The center of the bounds in map space. - */ - getCenterLonLat:function() { - if(!this.centerLonLat) { - this.centerLonLat = new OpenLayers.LonLat( - (this.left + this.right) / 2, (this.bottom + this.top) / 2 - ); - } - return this.centerLonLat; - }, - - /** - * APIMethod: scale - * Scales the bounds around a pixel or lonlat. Note that the new - * bounds may return non-integer properties, even if a pixel - * is passed. - * - * Parameters: - * ratio - {Float} - * origin - { or } - * Default is center. - * - * Returns: - * {} A new bounds that is scaled by ratio - * from origin. - */ - scale: function(ratio, origin){ - if(origin == null){ - origin = this.getCenterLonLat(); - } - - var origx,origy; - - // get origin coordinates - if(origin.CLASS_NAME == "OpenLayers.LonLat"){ - origx = origin.lon; - origy = origin.lat; - } else { - origx = origin.x; - origy = origin.y; - } - - var left = (this.left - origx) * ratio + origx; - var bottom = (this.bottom - origy) * ratio + origy; - var right = (this.right - origx) * ratio + origx; - var top = (this.top - origy) * ratio + origy; - - return new OpenLayers.Bounds(left, bottom, right, top); - }, - - /** - * APIMethod: add - * Shifts the coordinates of the bound by the given horizontal and vertical - * deltas. - * - * (start code) - * var bounds = new OpenLayers.Bounds(0, 0, 10, 10); - * bounds.toString(); - * // => "0,0,10,10" - * - * bounds.add(-1.5, 4).toString(); - * // => "-1.5,4,8.5,14" - * (end) - * - * This method will throw a TypeError if it is passed null as an argument. - * - * Parameters: - * x - {Float} horizontal delta - * y - {Float} vertical delta - * - * Returns: - * {} A new bounds whose coordinates are the same as - * this, but shifted by the passed-in x and y values. - */ - add:function(x, y) { - if ( (x == null) || (y == null) ) { - throw new TypeError('Bounds.add cannot receive null values'); - } - return new OpenLayers.Bounds(this.left + x, this.bottom + y, - this.right + x, this.top + y); - }, - - /** - * APIMethod: extend - * Extend the bounds to include the , - * or specified. - * - * Please note that this function assumes that left < right and - * bottom < top. - * - * Parameters: - * object - {, or - * } The object to be included in the new bounds - * object. - */ - extend:function(object) { - if (object) { - switch(object.CLASS_NAME) { - case "OpenLayers.LonLat": - this.extendXY(object.lon, object.lat); - break; - case "OpenLayers.Geometry.Point": - this.extendXY(object.x, object.y); - break; - - case "OpenLayers.Bounds": - // clear cached center location - this.centerLonLat = null; - - if ( (this.left == null) || (object.left < this.left)) { - this.left = object.left; - } - if ( (this.bottom == null) || (object.bottom < this.bottom) ) { - this.bottom = object.bottom; - } - if ( (this.right == null) || (object.right > this.right) ) { - this.right = object.right; - } - if ( (this.top == null) || (object.top > this.top) ) { - this.top = object.top; - } - break; - } - } - }, - - /** - * APIMethod: extendXY - * Extend the bounds to include the XY coordinate specified. - * - * Parameters: - * x - {number} The X part of the the coordinate. - * y - {number} The Y part of the the coordinate. - */ - extendXY:function(x, y) { - // clear cached center location - this.centerLonLat = null; - - if ((this.left == null) || (x < this.left)) { - this.left = x; - } - if ((this.bottom == null) || (y < this.bottom)) { - this.bottom = y; - } - if ((this.right == null) || (x > this.right)) { - this.right = x; - } - if ((this.top == null) || (y > this.top)) { - this.top = y; - } - }, - - /** - * APIMethod: containsLonLat - * Returns whether the bounds object contains the given . - * - * Parameters: - * ll - {|Object} OpenLayers.LonLat or an - * object with a 'lon' and 'lat' properties. - * options - {Object} Optional parameters - * - * Acceptable options: - * inclusive - {Boolean} Whether or not to include the border. - * Default is true. - * worldBounds - {} If a worldBounds is provided, the - * ll will be considered as contained if it exceeds the world bounds, - * but can be wrapped around the dateline so it is contained by this - * bounds. - * - * Returns: - * {Boolean} The passed-in lonlat is within this bounds. - */ - containsLonLat: function(ll, options) { - if (typeof options === "boolean") { - options = {inclusive: options}; - } - options = options || {}; - var contains = this.contains(ll.lon, ll.lat, options.inclusive), - worldBounds = options.worldBounds; - if (worldBounds && !contains) { - var worldWidth = worldBounds.getWidth(); - var worldCenterX = (worldBounds.left + worldBounds.right) / 2; - var worldsAway = Math.round((ll.lon - worldCenterX) / worldWidth); - contains = this.containsLonLat({ - lon: ll.lon - worldsAway * worldWidth, - lat: ll.lat - }, {inclusive: options.inclusive}); - } - return contains; - }, - - /** - * APIMethod: containsPixel - * Returns whether the bounds object contains the given . - * - * Parameters: - * px - {} - * inclusive - {Boolean} Whether or not to include the border. Default is - * true. - * - * Returns: - * {Boolean} The passed-in pixel is within this bounds. - */ - containsPixel:function(px, inclusive) { - return this.contains(px.x, px.y, inclusive); - }, - - /** - * APIMethod: contains - * Returns whether the bounds object contains the given x and y. - * - * Parameters: - * x - {Float} - * y - {Float} - * inclusive - {Boolean} Whether or not to include the border. Default is - * true. - * - * Returns: - * {Boolean} Whether or not the passed-in coordinates are within this - * bounds. - */ - contains:function(x, y, inclusive) { - //set default - if (inclusive == null) { - inclusive = true; - } - - if (x == null || y == null) { - return false; - } - - x = OpenLayers.Util.toFloat(x); - y = OpenLayers.Util.toFloat(y); - - var contains = false; - if (inclusive) { - contains = ((x >= this.left) && (x <= this.right) && - (y >= this.bottom) && (y <= this.top)); - } else { - contains = ((x > this.left) && (x < this.right) && - (y > this.bottom) && (y < this.top)); - } - return contains; - }, - - /** - * APIMethod: intersectsBounds - * Determine whether the target bounds intersects this bounds. Bounds are - * considered intersecting if any of their edges intersect or if one - * bounds contains the other. - * - * Parameters: - * bounds - {} The target bounds. - * options - {Object} Optional parameters. - * - * Acceptable options: - * inclusive - {Boolean} Treat coincident borders as intersecting. Default - * is true. If false, bounds that do not overlap but only touch at the - * border will not be considered as intersecting. - * worldBounds - {} If a worldBounds is provided, two - * bounds will be considered as intersecting if they intersect when - * shifted to within the world bounds. This applies only to bounds that - * cross or are completely outside the world bounds. - * - * Returns: - * {Boolean} The passed-in bounds object intersects this bounds. - */ - intersectsBounds:function(bounds, options) { - if (typeof options === "boolean") { - options = {inclusive: options}; - } - options = options || {}; - if (options.worldBounds) { - var self = this.wrapDateLine(options.worldBounds); - bounds = bounds.wrapDateLine(options.worldBounds); - } else { - self = this; - } - if (options.inclusive == null) { - options.inclusive = true; - } - var intersects = false; - var mightTouch = ( - self.left == bounds.right || - self.right == bounds.left || - self.top == bounds.bottom || - self.bottom == bounds.top - ); - - // if the two bounds only touch at an edge, and inclusive is false, - // then the bounds don't *really* intersect. - if (options.inclusive || !mightTouch) { - // otherwise, if one of the boundaries even partially contains another, - // inclusive of the edges, then they do intersect. - var inBottom = ( - ((bounds.bottom >= self.bottom) && (bounds.bottom <= self.top)) || - ((self.bottom >= bounds.bottom) && (self.bottom <= bounds.top)) - ); - var inTop = ( - ((bounds.top >= self.bottom) && (bounds.top <= self.top)) || - ((self.top > bounds.bottom) && (self.top < bounds.top)) - ); - var inLeft = ( - ((bounds.left >= self.left) && (bounds.left <= self.right)) || - ((self.left >= bounds.left) && (self.left <= bounds.right)) - ); - var inRight = ( - ((bounds.right >= self.left) && (bounds.right <= self.right)) || - ((self.right >= bounds.left) && (self.right <= bounds.right)) - ); - intersects = ((inBottom || inTop) && (inLeft || inRight)); - } - // document me - if (options.worldBounds && !intersects) { - var world = options.worldBounds; - var width = world.getWidth(); - var selfCrosses = !world.containsBounds(self); - var boundsCrosses = !world.containsBounds(bounds); - if (selfCrosses && !boundsCrosses) { - bounds = bounds.add(-width, 0); - intersects = self.intersectsBounds(bounds, {inclusive: options.inclusive}); - } else if (boundsCrosses && !selfCrosses) { - self = self.add(-width, 0); - intersects = bounds.intersectsBounds(self, {inclusive: options.inclusive}); - } - } - return intersects; - }, - - /** - * APIMethod: containsBounds - * Returns whether the bounds object contains the given . - * - * bounds - {} The target bounds. - * partial - {Boolean} If any of the target corners is within this bounds - * consider the bounds contained. Default is false. If false, the - * entire target bounds must be contained within this bounds. - * inclusive - {Boolean} Treat shared edges as contained. Default is - * true. - * - * Returns: - * {Boolean} The passed-in bounds object is contained within this bounds. - */ - containsBounds:function(bounds, partial, inclusive) { - if (partial == null) { - partial = false; - } - if (inclusive == null) { - inclusive = true; - } - var bottomLeft = this.contains(bounds.left, bounds.bottom, inclusive); - var bottomRight = this.contains(bounds.right, bounds.bottom, inclusive); - var topLeft = this.contains(bounds.left, bounds.top, inclusive); - var topRight = this.contains(bounds.right, bounds.top, inclusive); - - return (partial) ? (bottomLeft || bottomRight || topLeft || topRight) - : (bottomLeft && bottomRight && topLeft && topRight); - }, - - /** - * APIMethod: determineQuadrant - * Returns the the quadrant ("br", "tr", "tl", "bl") in which the given - * lies. - * - * Parameters: - * lonlat - {} - * - * Returns: - * {String} The quadrant ("br" "tr" "tl" "bl") of the bounds in which the - * coordinate lies. - */ - determineQuadrant: function(lonlat) { - - var quadrant = ""; - var center = this.getCenterLonLat(); - - quadrant += (lonlat.lat < center.lat) ? "b" : "t"; - quadrant += (lonlat.lon < center.lon) ? "l" : "r"; - - return quadrant; - }, - - /** - * APIMethod: transform - * Transform the Bounds object from source to dest. - * - * Parameters: - * source - {} Source projection. - * dest - {} Destination projection. - * - * Returns: - * {} Itself, for use in chaining operations. - */ - transform: function(source, dest) { - // clear cached center location - this.centerLonLat = null; - var ll = OpenLayers.Projection.transform( - {'x': this.left, 'y': this.bottom}, source, dest); - var lr = OpenLayers.Projection.transform( - {'x': this.right, 'y': this.bottom}, source, dest); - var ul = OpenLayers.Projection.transform( - {'x': this.left, 'y': this.top}, source, dest); - var ur = OpenLayers.Projection.transform( - {'x': this.right, 'y': this.top}, source, dest); - this.left = Math.min(ll.x, ul.x); - this.bottom = Math.min(ll.y, lr.y); - this.right = Math.max(lr.x, ur.x); - this.top = Math.max(ul.y, ur.y); - return this; - }, - - /** - * APIMethod: wrapDateLine - * Wraps the bounds object around the dateline. - * - * Parameters: - * maxExtent - {} - * options - {Object} Some possible options are: - * - * Allowed Options: - * leftTolerance - {float} Allow for a margin of error - * with the 'left' value of this - * bound. - * Default is 0. - * rightTolerance - {float} Allow for a margin of error - * with the 'right' value of - * this bound. - * Default is 0. - * - * Returns: - * {} A copy of this bounds, but wrapped around the - * "dateline" (as specified by the borders of - * maxExtent). Note that this function only returns - * a different bounds value if this bounds is - * *entirely* outside of the maxExtent. If this - * bounds straddles the dateline (is part in/part - * out of maxExtent), the returned bounds will always - * cross the left edge of the given maxExtent. - *. - */ - wrapDateLine: function(maxExtent, options) { - options = options || {}; - - var leftTolerance = options.leftTolerance || 0; - var rightTolerance = options.rightTolerance || 0; - - var newBounds = this.clone(); - - if (maxExtent) { - var width = maxExtent.getWidth(); - - //shift right? - while (newBounds.left < maxExtent.left && - newBounds.right - rightTolerance <= maxExtent.left ) { - newBounds = newBounds.add(width, 0); - } - - //shift left? - while (newBounds.left + leftTolerance >= maxExtent.right && - newBounds.right > maxExtent.right ) { - newBounds = newBounds.add(-width, 0); - } - - // crosses right only? force left - var newLeft = newBounds.left + leftTolerance; - if (newLeft < maxExtent.right && newLeft > maxExtent.left && - newBounds.right - rightTolerance > maxExtent.right) { - newBounds = newBounds.add(-width, 0); - } - } - - return newBounds; - }, - - CLASS_NAME: "OpenLayers.Bounds" -}); - -/** - * APIFunction: fromString - * Alternative constructor that builds a new OpenLayers.Bounds from a - * parameter string. - * - * (begin code) - * OpenLayers.Bounds.fromString("5,42,10,45"); - * // => equivalent to ... - * new OpenLayers.Bounds(5, 42, 10, 45); - * (end) - * - * Parameters: - * str - {String} Comma-separated bounds string. (e.g. "5,42,10,45") - * reverseAxisOrder - {Boolean} Does the string use reverse axis order? - * - * Returns: - * {} New bounds object built from the - * passed-in String. - */ -OpenLayers.Bounds.fromString = function(str, reverseAxisOrder) { - var bounds = str.split(","); - return OpenLayers.Bounds.fromArray(bounds, reverseAxisOrder); -}; - -/** - * APIFunction: fromArray - * Alternative constructor that builds a new OpenLayers.Bounds from an array. - * - * (begin code) - * OpenLayers.Bounds.fromArray( [5, 42, 10, 45] ); - * // => equivalent to ... - * new OpenLayers.Bounds(5, 42, 10, 45); - * (end) - * - * Parameters: - * bbox - {Array(Float)} Array of bounds values (e.g. [5,42,10,45]) - * reverseAxisOrder - {Boolean} Does the array use reverse axis order? - * - * Returns: - * {} New bounds object built from the passed-in Array. - */ -OpenLayers.Bounds.fromArray = function(bbox, reverseAxisOrder) { - return reverseAxisOrder === true ? - new OpenLayers.Bounds(bbox[1], bbox[0], bbox[3], bbox[2]) : - new OpenLayers.Bounds(bbox[0], bbox[1], bbox[2], bbox[3]); -}; - -/** - * APIFunction: fromSize - * Alternative constructor that builds a new OpenLayers.Bounds from a size. - * - * (begin code) - * OpenLayers.Bounds.fromSize( new OpenLayers.Size(10, 20) ); - * // => equivalent to ... - * new OpenLayers.Bounds(0, 20, 10, 0); - * (end) - * - * Parameters: - * size - { or Object} or an object with - * both 'w' and 'h' properties. - * - * Returns: - * {} New bounds object built from the passed-in size. - */ -OpenLayers.Bounds.fromSize = function(size) { - return new OpenLayers.Bounds(0, - size.h, - size.w, - 0); -}; - -/** - * Function: oppositeQuadrant - * Get the opposite quadrant for a given quadrant string. - * - * (begin code) - * OpenLayers.Bounds.oppositeQuadrant( "tl" ); - * // => "br" - * - * OpenLayers.Bounds.oppositeQuadrant( "tr" ); - * // => "bl" - * (end) - * - * Parameters: - * quadrant - {String} two character quadrant shortstring - * - * Returns: - * {String} The opposing quadrant ("br" "tr" "tl" "bl"). For Example, if - * you pass in "bl" it returns "tr", if you pass in "br" it - * returns "tl", etc. - */ -OpenLayers.Bounds.oppositeQuadrant = function(quadrant) { - var opp = ""; - - 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"lon=5,lat=42") - */ - toString:function() { - return ("lon=" + this.lon + ",lat=" + this.lat); - }, - - /** - * APIMethod: toShortString - * - * Returns: - * {String} Shortened String representation of OpenLayers.LonLat object. - * (e.g. "5, 42") - */ - toShortString:function() { - return (this.lon + ", " + this.lat); - }, - - /** - * APIMethod: clone - * - * Returns: - * {} New OpenLayers.LonLat object with the same lon - * and lat values - */ - clone:function() { - return new OpenLayers.LonLat(this.lon, this.lat); - }, - - /** - * APIMethod: add - * - * Parameters: - * lon - {Float} - * lat - {Float} - * - * Returns: - * {} A new OpenLayers.LonLat object with the lon and - * lat passed-in added to this's. - */ - add:function(lon, lat) { - if ( (lon == null) || (lat == null) ) { - throw new TypeError('LonLat.add cannot receive null values'); - } - return new OpenLayers.LonLat(this.lon + OpenLayers.Util.toFloat(lon), - this.lat + OpenLayers.Util.toFloat(lat)); - }, - - /** - * APIMethod: equals - * - * Parameters: - * ll - {} - * - * Returns: - * {Boolean} Boolean value indicating whether the passed-in - * object has the same lon and lat - * components as this. - * Note: if ll passed in is null, returns false - */ - equals:function(ll) { - var equals = false; - if (ll != null) { - equals = ((this.lon == ll.lon && this.lat == ll.lat) || - (isNaN(this.lon) && isNaN(this.lat) && isNaN(ll.lon) && isNaN(ll.lat))); - } - return equals; - }, - - /** - * APIMethod: transform - * Transform the LonLat object from source to dest. This transformation is - * *in place*: if you want a *new* lonlat, use .clone() first. - * - * Parameters: - * source - {} Source projection. - * dest - {} Destination projection. - * - * Returns: - * {} Itself, for use in chaining operations. - */ - transform: function(source, dest) { - var point = OpenLayers.Projection.transform( - {'x': this.lon, 'y': this.lat}, source, dest); - this.lon = point.x; - this.lat = point.y; - return this; - }, - - /** - * APIMethod: wrapDateLine - * - * Parameters: - * maxExtent - {} - * - * Returns: - * {} A copy of this lonlat, but wrapped around the - * "dateline" (as specified by the borders of - * maxExtent) - */ - wrapDateLine: function(maxExtent) { - - var newLonLat = this.clone(); - - if (maxExtent) { - //shift right? - while (newLonLat.lon < maxExtent.left) { - newLonLat.lon += maxExtent.getWidth(); - } - - //shift left? - while (newLonLat.lon > maxExtent.right) { - newLonLat.lon -= maxExtent.getWidth(); - } - } - - return newLonLat; - }, - - CLASS_NAME: "OpenLayers.LonLat" -}); - -/** - * Function: fromString - * Alternative constructor that builds a new from a - * parameter string - * - * Parameters: - * str - {String} Comma-separated Lon,Lat coordinate string. - * (e.g. "5,40") - * - * Returns: - * {} New object built from the - * passed-in String. - */ -OpenLayers.LonLat.fromString = function(str) { - var pair = str.split(","); - return new OpenLayers.LonLat(pair[0], pair[1]); -}; - -/** - * Function: fromArray - * Alternative constructor that builds a new from an - * array of two numbers that represent lon- and lat-values. - * - * Parameters: - * arr - {Array(Float)} Array of lon/lat values (e.g. [5,-42]) - * - * Returns: - * {} New object built from the - * passed-in array. - */ -OpenLayers.LonLat.fromArray = function(arr) { - var gotArr = OpenLayers.Util.isArray(arr), - lon = gotArr && arr[0], - lat = gotArr && arr[1]; - return new OpenLayers.LonLat(lon, lat); -}; -/* ====================================================================== - OpenLayers/BaseTypes/Pixel.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.Pixel - * This class represents a screen coordinate, in x and y coordinates - */ -OpenLayers.Pixel = OpenLayers.Class({ - - /** - * APIProperty: x - * {Number} The x coordinate - */ - x: 0.0, - - /** - * APIProperty: y - * {Number} The y coordinate - */ - y: 0.0, - - /** - * Constructor: OpenLayers.Pixel - * Create a new OpenLayers.Pixel instance - * - * Parameters: - * x - {Number} The x coordinate - * y - {Number} The y coordinate - * - * Returns: - * An instance of OpenLayers.Pixel - */ - initialize: function(x, y) { - this.x = parseFloat(x); - this.y = parseFloat(y); - }, - - /** - * Method: toString - * Cast this object into a string - * - * Returns: - * {String} The string representation of Pixel. ex: "x=200.4,y=242.2" - */ - toString:function() { - return ("x=" + this.x + ",y=" + this.y); - }, - - /** - * APIMethod: clone - * Return a clone of this pixel object - * - * Returns: - * {} A clone pixel - */ - clone:function() { - return new OpenLayers.Pixel(this.x, this.y); - }, - - /** - * APIMethod: equals - * Determine whether one pixel is equivalent to another - * - * Parameters: - * px - {|Object} An OpenLayers.Pixel or an object with - * a 'x' and 'y' properties. - * - * Returns: - * {Boolean} The point passed in as parameter is equal to this. Note that - * if px passed in is null, returns false. - */ - equals:function(px) { - var equals = false; - if (px != null) { - equals = ((this.x == px.x && this.y == px.y) || - (isNaN(this.x) && isNaN(this.y) && isNaN(px.x) && isNaN(px.y))); - } - return equals; - }, - - /** - * APIMethod: distanceTo - * Returns the distance to the pixel point passed in as a parameter. - * - * Parameters: - * px - {} - * - * Returns: - * {Float} The pixel point passed in as parameter to calculate the - * distance to. - */ - distanceTo:function(px) { - return Math.sqrt( - Math.pow(this.x - px.x, 2) + - Math.pow(this.y - px.y, 2) - ); - }, - - /** - * APIMethod: add - * - * Parameters: - * x - {Integer} - * y - {Integer} - * - * Returns: - * {} A new Pixel with this pixel's x&y augmented by the - * values passed in. - */ - add:function(x, y) { - if ( (x == null) || (y == null) ) { - throw new TypeError('Pixel.add cannot receive null values'); - } - return new OpenLayers.Pixel(this.x + x, this.y + y); - }, - - /** - * APIMethod: offset - * - * Parameters - * px - {|Object} An OpenLayers.Pixel or an object with - * a 'x' and 'y' properties. - * - * Returns: - * {} A new Pixel with this pixel's x&y augmented by the - * x&y values of the pixel passed in. - */ - offset:function(px) { - var newPx = this.clone(); - if (px) { - newPx = this.add(px.x, px.y); - } - return newPx; - }, - - CLASS_NAME: "OpenLayers.Pixel" -}); -/* ====================================================================== - OpenLayers/BaseTypes/Size.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.Size - * Instances of this class represent a width/height pair - */ -OpenLayers.Size = OpenLayers.Class({ - - /** - * APIProperty: w - * {Number} width - */ - w: 0.0, - - /** - * APIProperty: h - * {Number} height - */ - h: 0.0, - - - /** - * Constructor: OpenLayers.Size - * Create an instance of OpenLayers.Size - * - * Parameters: - * w - {Number} width - * h - {Number} height - */ - initialize: function(w, h) { - this.w = parseFloat(w); - this.h = parseFloat(h); - }, - - /** - * Method: toString - * Return the string representation of a size object - * - * Returns: - * {String} The string representation of OpenLayers.Size object. - * (e.g. "w=55,h=66") - */ - toString:function() { - return ("w=" + this.w + ",h=" + this.h); - }, - - /** - * APIMethod: clone - * Create a clone of this size object - * - * Returns: - * {} A new OpenLayers.Size object with the same w and h - * values - */ - clone:function() { - return new OpenLayers.Size(this.w, this.h); - }, - - /** - * - * APIMethod: equals - * Determine where this size is equal to another - * - * Parameters: - * sz - {|Object} An OpenLayers.Size or an object with - * a 'w' and 'h' properties. - * - * Returns: - * {Boolean} The passed in size has the same h and w properties as this one. - * Note that if sz passed in is null, returns false. - */ - equals:function(sz) { - var equals = false; - if (sz != null) { - equals = ((this.w == sz.w && this.h == sz.h) || - (isNaN(this.w) && isNaN(this.h) && isNaN(sz.w) && isNaN(sz.h))); - } - 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 method to set this value and the method to - * retrieve it. - */ - code: null, - - /** - * APIProperty: defaultCode - * {String} Default language to use when a specific language can't be - * found. Default is "en". - */ - defaultCode: "en", - - /** - * APIFunction: getCode - * Get the current language code. - * - * Returns: - * {String} The current language code. - */ - getCode: function() { - if(!OpenLayers.Lang.code) { - OpenLayers.Lang.setCode(); - } - return OpenLayers.Lang.code; - }, - - /** - * APIFunction: setCode - * Set the language code for string translation. This code is used by - * the method. - * - * Parameters: - * code - {String} These codes follow the IETF recommendations at - * http://www.ietf.org/rfc/rfc3066.txt. If no value is set, the - * browser's language setting will be tested. If no - * dictionary exists for the code, the - * will be used. - */ - setCode: function(code) { - var lang; - if(!code) { - code = (OpenLayers.BROWSER_NAME == "msie") ? - navigator.userLanguage : navigator.language; - } - var parts = code.split('-'); - parts[0] = parts[0].toLowerCase(); - if(typeof OpenLayers.Lang[parts[0]] == "object") { - lang = parts[0]; - } - - // check for regional extensions - if(parts[1]) { - var testLang = parts[0] + '-' + parts[1].toUpperCase(); - if(typeof OpenLayers.Lang[testLang] == "object") { - lang = testLang; - } - } - if(!lang) { - OpenLayers.Console.warn( - 'Failed to find OpenLayers.Lang.' + parts.join("-") + - ' dictionary, falling back to default language' - ); - lang = OpenLayers.Lang.defaultCode; - } - - OpenLayers.Lang.code = lang; - }, - - /** - * APIMethod: translate - * Looks up a key from a dictionary based on the current language string. - * The value of will be used to determine the appropriate - * dictionary. Dictionaries are stored in . - * - * Parameters: - * key - {String} The key for an i18n string value in the dictionary. - * context - {Object} Optional context to be used with - * . - * - * Returns: - * {String} A internationalized string. - */ - translate: function(key, context) { - var dictionary = OpenLayers.Lang[OpenLayers.Lang.getCode()]; - var message = dictionary && dictionary[key]; - if(!message) { - // Message not found, fall back to message key - message = key; - } - if(context) { - message = OpenLayers.String.format(message, context); - } - return message; - } - -}; - - -/** - * APIMethod: OpenLayers.i18n - * Alias for . Looks up a key from a dictionary - * based on the current language string. The value of - * will be used to determine the appropriate - * dictionary. Dictionaries are stored in . - * - * Parameters: - * key - {String} The key for an i18n string value in the dictionary. - * context - {Object} Optional context to be used with - * . - * - * Returns: - * {String} A internationalized string. - */ -OpenLayers.i18n = OpenLayers.Lang.translate; -/* ====================================================================== - OpenLayers/Util.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.js - * @requires OpenLayers/BaseTypes/Bounds.js - * @requires OpenLayers/BaseTypes/Element.js - * @requires OpenLayers/BaseTypes/LonLat.js - * @requires OpenLayers/BaseTypes/Pixel.js - * @requires OpenLayers/BaseTypes/Size.js - * @requires OpenLayers/Lang.js - */ - -/** - * Namespace: Util - */ -OpenLayers.Util = OpenLayers.Util || {}; - -/** - * Function: getElement - * This is the old $() from prototype - * - * Parameters: - * e - {String or DOMElement or Window} - * - * Returns: - * {Array(DOMElement) or DOMElement} - */ -OpenLayers.Util.getElement = function() { - var elements = []; - - for (var i=0, len=arguments.length; i= 0; i--) { - if(array[i] == item) { - array.splice(i,1); - //break;more than once?? - } - } - return array; -}; - -/** - * Function: indexOf - * Seems to exist already in FF, but not in MOZ. - * - * Parameters: - * array - {Array} - * obj - {*} - * - * Returns: - * {Integer} The index at which the first object was found in the array. - * If not found, returns -1. - */ -OpenLayers.Util.indexOf = function(array, obj) { - // use the build-in function if available. - if (typeof array.indexOf == "function") { - return array.indexOf(obj); - } else { - for (var i = 0, len = array.length; i < len; i++) { - if (array[i] == obj) { - return i; - } - } - return -1; - } -}; - - -/** - * Property: dotless - * {RegExp} - * Compiled regular expression to match dots ("."). This is used for replacing - * dots in identifiers. Because object identifiers are frequently used for - * DOM element identifiers by the library, we avoid using dots to make for - * more sensible CSS selectors. - * - * TODO: Use a module pattern to avoid bloating the API with stuff like this. - */ -OpenLayers.Util.dotless = /\./g; - -/** - * Function: modifyDOMElement - * - * Modifies many properties of a DOM element all at once. Passing in - * null to an individual parameter will avoid setting the attribute. - * - * Parameters: - * element - {DOMElement} DOM element to modify. - * id - {String} The element id attribute to set. Note that dots (".") will be - * replaced with underscore ("_") in setting the element id. - * px - {|Object} The element left and top position, - * OpenLayers.Pixel or an object with - * a 'x' and 'y' properties. - * sz - {|Object} The element width and height, - * OpenLayers.Size or an object with a - * 'w' and 'h' properties. - * position - {String} The position attribute. eg: absolute, - * relative, etc. - * border - {String} The style.border attribute. eg: - * solid black 2px - * overflow - {String} The style.overview attribute. - * opacity - {Float} Fractional value (0.0 - 1.0) - */ -OpenLayers.Util.modifyDOMElement = function(element, id, px, sz, position, - border, overflow, opacity) { - - if (id) { - element.id = id.replace(OpenLayers.Util.dotless, "_"); - } - if (px) { - element.style.left = px.x + "px"; - element.style.top = px.y + "px"; - } - if (sz) { - element.style.width = sz.w + "px"; - element.style.height = sz.h + "px"; - } - if (position) { - element.style.position = position; - } - if (border) { - element.style.border = border; - } - if (overflow) { - element.style.overflow = overflow; - } - if (parseFloat(opacity) >= 0.0 && parseFloat(opacity) < 1.0) { - element.style.filter = 'alpha(opacity=' + (opacity * 100) + ')'; - element.style.opacity = opacity; - } else if (parseFloat(opacity) == 1.0) { - element.style.filter = ''; - element.style.opacity = ''; - } -}; - -/** - * Function: createDiv - * Creates a new div and optionally set some standard attributes. - * Null may be passed to each parameter if you do not wish to - * set a particular attribute. - * Note - zIndex is NOT set on the resulting div. - * - * Parameters: - * id - {String} An identifier for this element. If no id is - * passed an identifier will be created - * automatically. Note that dots (".") will be replaced with - * underscore ("_") when generating ids. - * px - {|Object} The element left and top position, - * OpenLayers.Pixel or an object with - * a 'x' and 'y' properties. - * sz - {|Object} The element width and height, - * OpenLayers.Size or an object with a - * 'w' and 'h' properties. - * imgURL - {String} A url pointing to an image to use as a - * background image. - * position - {String} The style.position value. eg: absolute, - * relative etc. - * border - {String} The the style.border value. - * eg: 2px solid black - * overflow - {String} The style.overflow value. Eg. hidden - * opacity - {Float} Fractional value (0.0 - 1.0) - * - * Returns: - * {DOMElement} A DOM Div created with the specified attributes. - */ -OpenLayers.Util.createDiv = function(id, px, sz, imgURL, position, - border, overflow, opacity) { - - var dom = document.createElement('div'); - - if (imgURL) { - dom.style.backgroundImage = 'url(' + imgURL + ')'; - } - - //set generic properties - if (!id) { - id = OpenLayers.Util.createUniqueID("OpenLayersDiv"); - } - if (!position) { - position = "absolute"; - } - OpenLayers.Util.modifyDOMElement(dom, id, px, sz, position, - border, overflow, opacity); - - return dom; -}; - -/** - * Function: createImage - * Creates an img element with specific attribute values. - * - * Parameters: - * id - {String} The id field for the img. If none assigned one will be - * automatically generated. - * px - {|Object} The element left and top position, - * OpenLayers.Pixel or an object with - * a 'x' and 'y' properties. - * sz - {|Object} The element width and height, - * OpenLayers.Size or an object with a - * 'w' and 'h' properties. - * imgURL - {String} The url to use as the image source. - * position - {String} The style.position value. - * border - {String} The border to place around the image. - * opacity - {Float} Fractional value (0.0 - 1.0) - * delayDisplay - {Boolean} If true waits until the image has been - * loaded. - * - * Returns: - * {DOMElement} A DOM Image created with the specified attributes. - */ -OpenLayers.Util.createImage = function(id, px, sz, imgURL, position, border, - opacity, delayDisplay) { - - var image = document.createElement("img"); - - //set generic properties - if (!id) { - id = OpenLayers.Util.createUniqueID("OpenLayersDiv"); - } - if (!position) { - position = "relative"; - } - OpenLayers.Util.modifyDOMElement(image, id, px, sz, position, - border, null, opacity); - - if (delayDisplay) { - image.style.display = "none"; - function display() { - image.style.display = ""; - OpenLayers.Event.stopObservingElement(image); - } - OpenLayers.Event.observe(image, "load", display); - OpenLayers.Event.observe(image, "error", display); - } - - //set special properties - image.style.alt = id; - image.galleryImg = "no"; - if (imgURL) { - image.src = imgURL; - } - - return image; -}; - -/** - * Property: IMAGE_RELOAD_ATTEMPTS - * {Integer} How many times should we try to reload an image before giving up? - * Default is 0 - */ -OpenLayers.IMAGE_RELOAD_ATTEMPTS = 0; - -/** - * Property: alphaHackNeeded - * {Boolean} true if the png alpha hack is necessary and possible, false otherwise. - */ -OpenLayers.Util.alphaHackNeeded = null; - -/** - * Function: alphaHack - * Checks whether it's necessary (and possible) to use the png alpha - * hack which allows alpha transparency for png images under Internet - * Explorer. - * - * Returns: - * {Boolean} true if the png alpha hack is necessary and possible, false otherwise. - */ -OpenLayers.Util.alphaHack = function() { - if (OpenLayers.Util.alphaHackNeeded == null) { - var arVersion = navigator.appVersion.split("MSIE"); - var version = parseFloat(arVersion[1]); - var filter = false; - - // IEs4Lin dies when trying to access document.body.filters, because - // the property is there, but requires a DLL that can't be provided. This - // means that we need to wrap this in a try/catch so that this can - // continue. - - try { - filter = !!(document.body.filters); - } catch (e) {} - - OpenLayers.Util.alphaHackNeeded = (filter && - (version >= 5.5) && (version < 7)); - } - return OpenLayers.Util.alphaHackNeeded; -}; - -/** - * Function: modifyAlphaImageDiv - * - * Parameters: - * div - {DOMElement} Div containing Alpha-adjusted Image - * id - {String} - * px - {|Object} OpenLayers.Pixel or an object with - * a 'x' and 'y' properties. - * sz - {|Object} OpenLayers.Size or an object with - * a 'w' and 'h' properties. - * imgURL - {String} - * position - {String} - * border - {String} - * sizing - {String} 'crop', 'scale', or 'image'. Default is "scale" - * opacity - {Float} Fractional value (0.0 - 1.0) - */ -OpenLayers.Util.modifyAlphaImageDiv = function(div, id, px, sz, imgURL, - position, border, sizing, - opacity) { - - OpenLayers.Util.modifyDOMElement(div, id, px, sz, position, - null, null, opacity); - - var img = div.childNodes[0]; - - if (imgURL) { - img.src = imgURL; - } - OpenLayers.Util.modifyDOMElement(img, div.id + "_innerImage", null, sz, - "relative", border); - - if (OpenLayers.Util.alphaHack()) { - if(div.style.display != "none") { - div.style.display = "inline-block"; - } - if (sizing == null) { - sizing = "scale"; - } - - div.style.filter = "progid:DXImageTransform.Microsoft" + - ".AlphaImageLoader(src='" + img.src + "', " + - "sizingMethod='" + sizing + "')"; - if (parseFloat(div.style.opacity) >= 0.0 && - parseFloat(div.style.opacity) < 1.0) { - div.style.filter += " alpha(opacity=" + div.style.opacity * 100 + ")"; - } - - img.style.filter = "alpha(opacity=0)"; - } -}; - -/** - * Function: createAlphaImageDiv - * - * Parameters: - * id - {String} - * px - {|Object} OpenLayers.Pixel or an object with - * a 'x' and 'y' properties. - * sz - {|Object} OpenLayers.Size or an object with - * a 'w' and 'h' properties. - * imgURL - {String} - * position - {String} - * border - {String} - * sizing - {String} 'crop', 'scale', or 'image'. Default is "scale" - * opacity - {Float} Fractional value (0.0 - 1.0) - * delayDisplay - {Boolean} If true waits until the image has been - * loaded. - * - * Returns: - * {DOMElement} A DOM Div created with a DOM Image inside it. If the hack is - * needed for transparency in IE, it is added. - */ -OpenLayers.Util.createAlphaImageDiv = function(id, px, sz, imgURL, - position, border, sizing, - opacity, delayDisplay) { - - var div = OpenLayers.Util.createDiv(); - var img = OpenLayers.Util.createImage(null, null, null, null, null, null, - null, delayDisplay); - img.className = "olAlphaImg"; - div.appendChild(img); - - OpenLayers.Util.modifyAlphaImageDiv(div, id, px, sz, imgURL, position, - border, sizing, opacity); - - return div; -}; - - -/** - * Function: upperCaseObject - * Creates a new hashtable and copies over all the keys from the - * passed-in object, but storing them under an uppercased - * version of the key at which they were stored. - * - * Parameters: - * object - {Object} - * - * Returns: - * {Object} A new Object with all the same keys but uppercased - */ -OpenLayers.Util.upperCaseObject = function (object) { - var uObject = {}; - for (var key in object) { - uObject[key.toUpperCase()] = object[key]; - } - return uObject; -}; - -/** - * Function: applyDefaults - * Takes an object and copies any properties that don't exist from - * another properties, by analogy with OpenLayers.Util.extend() from - * Prototype.js. - * - * Parameters: - * to - {Object} The destination object. - * from - {Object} The source object. Any properties of this object that - * are undefined in the to object will be set on the to object. - * - * Returns: - * {Object} A reference to the to object. Note that the to argument is modified - * in place and returned by this function. - */ -OpenLayers.Util.applyDefaults = function (to, from) { - to = to || {}; - /* - * FF/Windows < 2.0.0.13 reports "Illegal operation on WrappedNative - * prototype object" when calling hawOwnProperty if the source object is an - * instance of window.Event. - */ - var fromIsEvt = typeof window.Event == "function" - && from instanceof window.Event; - - for (var key in from) { - if (to[key] === undefined || - (!fromIsEvt && from.hasOwnProperty - && from.hasOwnProperty(key) && !to.hasOwnProperty(key))) { - to[key] = from[key]; - } - } - /** - * IE doesn't include the toString property when iterating over an object's - * properties with the for(property in object) syntax. Explicitly check if - * the source has its own toString property. - */ - if(!fromIsEvt && from && from.hasOwnProperty - && from.hasOwnProperty('toString') && !to.hasOwnProperty('toString')) { - to.toString = from.toString; - } - - return to; -}; - -/** - * Function: getParameterString - * - * Parameters: - * params - {Object} - * - * Returns: - * {String} A concatenation of the properties of an object in - * http parameter notation. - * (ex. "key1=value1&key2=value2&key3=value3") - * If a parameter is actually a list, that parameter will then - * be set to a comma-seperated list of values (foo,bar) instead - * of being URL escaped (foo%3Abar). - */ -OpenLayers.Util.getParameterString = function(params) { - var paramsArray = []; - - for (var key in params) { - var value = params[key]; - if ((value != null) && (typeof value != 'function')) { - var encodedValue; - if (typeof value == 'object' && value.constructor == Array) { - /* value is an array; encode items and separate with "," */ - var encodedItemArray = []; - var item; - for (var itemIndex=0, len=value.length; itemIndex} (or any object with both .lat, .lon properties) - * p2 - {} (or any object with both .lat, .lon properties) - * - * Returns: - * {Float} The distance (in km) between the two input points as measured on an - * ellipsoid. Note that the input point objects must be in geographic - * coordinates (decimal degrees) and the return distance is in kilometers. - */ -OpenLayers.Util.distVincenty = function(p1, p2) { - var ct = OpenLayers.Util.VincentyConstants; - var a = ct.a, b = ct.b, f = ct.f; - - var L = OpenLayers.Util.rad(p2.lon - p1.lon); - var U1 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p1.lat))); - var U2 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p2.lat))); - var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1); - var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2); - var lambda = L, lambdaP = 2*Math.PI; - var iterLimit = 20; - while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) { - var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda); - var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) + - (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda)); - if (sinSigma==0) { - return 0; // co-incident points - } - var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda; - var sigma = Math.atan2(sinSigma, cosSigma); - var alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma); - var cosSqAlpha = Math.cos(alpha) * Math.cos(alpha); - var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha; - var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha)); - lambdaP = lambda; - lambda = L + (1-C) * f * Math.sin(alpha) * - (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM))); - } - if (iterLimit==0) { - return NaN; // formula failed to converge - } - var uSq = cosSqAlpha * (a*a - b*b) / (b*b); - var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq))); - var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq))); - var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)- - B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM))); - var s = b*A*(sigma-deltaSigma); - var d = s.toFixed(3)/1000; // round to 1mm precision - return d; -}; - -/** - * APIFunction: destinationVincenty - * Calculate destination point given start point lat/long (numeric degrees), - * bearing (numeric degrees) & distance (in m). - * Adapted from Chris Veness work, see - * http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html - * - * Parameters: - * lonlat - {} (or any object with both .lat, .lon - * properties) The start point. - * brng - {Float} The bearing (degrees). - * dist - {Float} The ground distance (meters). - * - * Returns: - * {} The destination point. - */ -OpenLayers.Util.destinationVincenty = function(lonlat, brng, dist) { - var u = OpenLayers.Util; - var ct = u.VincentyConstants; - var a = ct.a, b = ct.b, f = ct.f; - - var lon1 = lonlat.lon; - var lat1 = lonlat.lat; - - var s = dist; - var alpha1 = u.rad(brng); - var sinAlpha1 = Math.sin(alpha1); - var cosAlpha1 = Math.cos(alpha1); - - var tanU1 = (1-f) * Math.tan(u.rad(lat1)); - var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1; - var sigma1 = Math.atan2(tanU1, cosAlpha1); - var sinAlpha = cosU1 * sinAlpha1; - var cosSqAlpha = 1 - sinAlpha*sinAlpha; - var uSq = cosSqAlpha * (a*a - b*b) / (b*b); - var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq))); - var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq))); - - var sigma = s / (b*A), sigmaP = 2*Math.PI; - while (Math.abs(sigma-sigmaP) > 1e-12) { - var cos2SigmaM = Math.cos(2*sigma1 + sigma); - var sinSigma = Math.sin(sigma); - var cosSigma = Math.cos(sigma); - var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)- - B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM))); - sigmaP = sigma; - sigma = s / (b*A) + deltaSigma; - } - - var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1; - var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1, - (1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp)); - var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1); - var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha)); - var L = lambda - (1-C) * f * sinAlpha * - (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM))); - - var revAz = Math.atan2(sinAlpha, -tmp); // final bearing - - return new OpenLayers.LonLat(lon1+u.deg(L), u.deg(lat2)); -}; - -/** - * Function: getParameters - * Parse the parameters from a URL or from the current page itself into a - * JavaScript Object. Note that parameter values with commas are separated - * out into an Array. - * - * Parameters: - * url - {String} Optional url used to extract the query string. - * If url is null or is not supplied, query string is taken - * from the page location. - * options - {Object} Additional options. Optional. - * - * Valid options: - * splitArgs - {Boolean} Split comma delimited params into arrays? Default is - * true. - * - * Returns: - * {Object} An object of key/value pairs from the query string. - */ -OpenLayers.Util.getParameters = function(url, options) { - options = options || {}; - // if no url specified, take it from the location bar - url = (url === null || url === undefined) ? window.location.href : url; - - //parse out parameters portion of url string - var paramsString = ""; - if (OpenLayers.String.contains(url, '?')) { - var start = url.indexOf('?') + 1; - var end = OpenLayers.String.contains(url, "#") ? - url.indexOf('#') : url.length; - paramsString = url.substring(start, end); - } - - var parameters = {}; - var pairs = paramsString.split(/[&;]/); - for(var i=0, len=pairs.length; i 1.0) ? (1.0 / scale) - : scale; - return normScale; -}; - -/** - * Function: getResolutionFromScale - * - * Parameters: - * scale - {Float} - * units - {String} Index into OpenLayers.INCHES_PER_UNIT hashtable. - * Default is degrees - * - * Returns: - * {Float} The corresponding resolution given passed-in scale and unit - * parameters. If the given scale is falsey, the returned resolution will - * be undefined. - */ -OpenLayers.Util.getResolutionFromScale = function (scale, units) { - var resolution; - if (scale) { - if (units == null) { - units = "degrees"; - } - var normScale = OpenLayers.Util.normalizeScale(scale); - resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units] - * OpenLayers.DOTS_PER_INCH); - } - return resolution; -}; - -/** - * Function: getScaleFromResolution - * - * Parameters: - * resolution - {Float} - * units - {String} Index into OpenLayers.INCHES_PER_UNIT hashtable. - * Default is degrees - * - * Returns: - * {Float} The corresponding scale given passed-in resolution and unit - * parameters. - */ -OpenLayers.Util.getScaleFromResolution = function (resolution, units) { - - if (units == null) { - units = "degrees"; - } - - var scale = resolution * OpenLayers.INCHES_PER_UNIT[units] * - OpenLayers.DOTS_PER_INCH; - return scale; -}; - -/** - * Function: pagePosition - * Calculates the position of an element on the page (see - * http://code.google.com/p/doctype/wiki/ArticlePageOffset) - * - * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is - * Copyright (c) 2006, Yahoo! Inc. - * All rights reserved. - * - * Redistribution and use of this software in source and binary forms, with or - * without modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of Yahoo! Inc. nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission of Yahoo! Inc. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * 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. - * - * Parameters: - * forElement - {DOMElement} - * - * Returns: - * {Array} two item array, Left value then Top value. - */ -OpenLayers.Util.pagePosition = function(forElement) { - // NOTE: If element is hidden (display none or disconnected or any the - // ancestors are hidden) we get (0,0) by default but we still do the - // accumulation of scroll position. - - var pos = [0, 0]; - var viewportElement = OpenLayers.Util.getViewportElement(); - if (!forElement || forElement == window || forElement == viewportElement) { - // viewport is always at 0,0 as that defined the coordinate system for - // this function - this avoids special case checks in the code below - return pos; - } - - // Gecko browsers normally use getBoxObjectFor to calculate the position. - // When invoked for an element with an implicit absolute position though it - // can be off by one. Therefore the recursive implementation is used in - // those (relatively rare) cases. - var BUGGY_GECKO_BOX_OBJECT = - OpenLayers.IS_GECKO && document.getBoxObjectFor && - OpenLayers.Element.getStyle(forElement, 'position') == 'absolute' && - (forElement.style.top == '' || forElement.style.left == ''); - - var parent = null; - var box; - - if (forElement.getBoundingClientRect) { // IE - box = forElement.getBoundingClientRect(); - var scrollTop = window.pageYOffset || viewportElement.scrollTop; - var scrollLeft = window.pageXOffset || viewportElement.scrollLeft; - - pos[0] = box.left + scrollLeft; - pos[1] = box.top + scrollTop; - - } else if (document.getBoxObjectFor && !BUGGY_GECKO_BOX_OBJECT) { // gecko - // Gecko ignores the scroll values for ancestors, up to 1.9. See: - // https://bugzilla.mozilla.org/show_bug.cgi?id=328881 and - // https://bugzilla.mozilla.org/show_bug.cgi?id=330619 - - box = document.getBoxObjectFor(forElement); - var vpBox = document.getBoxObjectFor(viewportElement); - pos[0] = box.screenX - vpBox.screenX; - pos[1] = box.screenY - vpBox.screenY; - - } else { // safari/opera - pos[0] = forElement.offsetLeft; - pos[1] = forElement.offsetTop; - parent = forElement.offsetParent; - if (parent != forElement) { - while (parent) { - pos[0] += parent.offsetLeft; - pos[1] += parent.offsetTop; - parent = parent.offsetParent; - } - } - - var browser = OpenLayers.BROWSER_NAME; - - // opera & (safari absolute) incorrectly account for body offsetTop - if (browser == "opera" || (browser == "safari" && - OpenLayers.Element.getStyle(forElement, 'position') == 'absolute')) { - pos[1] -= document.body.offsetTop; - } - - // accumulate the scroll positions for everything but the body element - parent = forElement.offsetParent; - while (parent && parent != document.body) { - pos[0] -= parent.scrollLeft; - // see https://bugs.opera.com/show_bug.cgi?id=249965 - if (browser != "opera" || parent.tagName != 'TR') { - pos[1] -= parent.scrollTop; - } - parent = parent.offsetParent; - } - } - - return pos; -}; - -/** - * Function: getViewportElement - * Returns die viewport element of the document. The viewport element is - * usually document.documentElement, except in IE,where it is either - * document.body or document.documentElement, depending on the document's - * compatibility mode (see - * http://code.google.com/p/doctype/wiki/ArticleClientViewportElement) - * - * Returns: - * {DOMElement} - */ -OpenLayers.Util.getViewportElement = function() { - var viewportElement = arguments.callee.viewportElement; - if (viewportElement == undefined) { - viewportElement = (OpenLayers.BROWSER_NAME == "msie" && - document.compatMode != 'CSS1Compat') ? document.body : - document.documentElement; - arguments.callee.viewportElement = viewportElement; - } - return viewportElement; -}; - -/** - * Function: isEquivalentUrl - * Test two URLs for equivalence. - * - * Setting 'ignoreCase' allows for case-independent comparison. - * - * Comparison is based on: - * - Protocol - * - Host (evaluated without the port) - * - Port (set 'ignorePort80' to ignore "80" values) - * - Hash ( set 'ignoreHash' to disable) - * - Pathname (for relative <-> absolute comparison) - * - Arguments (so they can be out of order) - * - * Parameters: - * url1 - {String} - * url2 - {String} - * options - {Object} Allows for customization of comparison: - * 'ignoreCase' - Default is True - * 'ignorePort80' - Default is True - * 'ignoreHash' - Default is True - * - * Returns: - * {Boolean} Whether or not the two URLs are equivalent - */ -OpenLayers.Util.isEquivalentUrl = function(url1, url2, options) { - options = options || {}; - - OpenLayers.Util.applyDefaults(options, { - ignoreCase: true, - ignorePort80: true, - ignoreHash: true, - splitArgs: false - }); - - var urlObj1 = OpenLayers.Util.createUrlObject(url1, options); - var urlObj2 = OpenLayers.Util.createUrlObject(url2, options); - - //compare all keys except for "args" (treated below) - for(var key in urlObj1) { - if(key !== "args") { - if(urlObj1[key] != urlObj2[key]) { - return false; - } - } - } - - // compare search args - irrespective of order - for(var key in urlObj1.args) { - if(urlObj1.args[key] != urlObj2.args[key]) { - return false; - } - delete urlObj2.args[key]; - } - // urlObj2 shouldn't have any args left - for(var key in urlObj2.args) { - return false; - } - - return true; -}; - -/** - * Function: createUrlObject - * - * Parameters: - * url - {String} - * options - {Object} A hash of options. - * - * Valid options: - * ignoreCase - {Boolean} lowercase url, - * ignorePort80 - {Boolean} don't include explicit port if port is 80, - * ignoreHash - {Boolean} Don't include part of url after the hash (#). - * splitArgs - {Boolean} Split comma delimited params into arrays? Default is - * true. - * - * Returns: - * {Object} An object with separate url, a, port, host, and args parsed out - * and ready for comparison - */ -OpenLayers.Util.createUrlObject = function(url, options) { - options = options || {}; - - // deal with relative urls first - if(!(/^\w+:\/\//).test(url)) { - var loc = window.location; - var port = loc.port ? ":" + loc.port : ""; - var fullUrl = loc.protocol + "//" + loc.host.split(":").shift() + port; - if(url.indexOf("/") === 0) { - // full pathname - url = fullUrl + url; - } else { - // relative to current path - var parts = loc.pathname.split("/"); - parts.pop(); - url = fullUrl + parts.join("/") + "/" + url; - } - } - - if (options.ignoreCase) { - url = url.toLowerCase(); - } - - var a = document.createElement('a'); - a.href = url; - - var urlObject = {}; - - //host (without port) - urlObject.host = a.host.split(":").shift(); - - //protocol - urlObject.protocol = a.protocol; - - //port (get uniform browser behavior with port 80 here) - if(options.ignorePort80) { - urlObject.port = (a.port == "80" || a.port == "0") ? "" : a.port; - } else { - urlObject.port = (a.port == "" || a.port == "0") ? "80" : a.port; - } - - //hash - urlObject.hash = (options.ignoreHash || a.hash === "#") ? "" : a.hash; - - //args - var queryString = a.search; - if (!queryString) { - var qMark = url.indexOf("?"); - queryString = (qMark != -1) ? url.substr(qMark) : ""; - } - urlObject.args = OpenLayers.Util.getParameters(queryString, - {splitArgs: options.splitArgs}); - - // pathname - // - // This is a workaround for Internet Explorer where - // window.location.pathname has a leading "/", but - // a.pathname has no leading "/". - urlObject.pathname = (a.pathname.charAt(0) == "/") ? a.pathname : "/" + a.pathname; - - return urlObject; -}; - -/** - * Function: removeTail - * Takes a url and removes everything after the ? and # - * - * Parameters: - * url - {String} The url to process - * - * Returns: - * {String} The string with all queryString and Hash removed - */ -OpenLayers.Util.removeTail = function(url) { - var head = null; - - var qMark = url.indexOf("?"); - var hashMark = url.indexOf("#"); - - if (qMark == -1) { - head = (hashMark != -1) ? url.substr(0,hashMark) : url; - } else { - head = (hashMark != -1) ? url.substr(0,Math.min(qMark, hashMark)) - : url.substr(0, qMark); - } - return head; -}; - -/** - * Constant: IS_GECKO - * {Boolean} True if the userAgent reports the browser to use the Gecko engine - */ -OpenLayers.IS_GECKO = (function() { - var ua = navigator.userAgent.toLowerCase(); - return ua.indexOf("webkit") == -1 && ua.indexOf("gecko") != -1; -})(); - -/** - * Constant: CANVAS_SUPPORTED - * {Boolean} True if canvas 2d is supported. - */ -OpenLayers.CANVAS_SUPPORTED = (function() { - var elem = document.createElement('canvas'); - return !!(elem.getContext && elem.getContext('2d')); -})(); - -/** - * Constant: BROWSER_NAME - * {String} - * A substring of the navigator.userAgent property. Depending on the userAgent - * property, this will be the empty string or one of the following: - * * "opera" -- Opera - * * "msie" -- Internet Explorer - * * "safari" -- Safari - * * "firefox" -- Firefox - * * "mozilla" -- Mozilla - */ -OpenLayers.BROWSER_NAME = (function() { - var name = ""; - var ua = navigator.userAgent.toLowerCase(); - if (ua.indexOf("opera") != -1) { - name = "opera"; - } else if (ua.indexOf("msie") != -1) { - name = "msie"; - } else if (ua.indexOf("safari") != -1) { - name = "safari"; - } else if (ua.indexOf("mozilla") != -1) { - if (ua.indexOf("firefox") != -1) { - name = "firefox"; - } else { - name = "mozilla"; - } - } - return name; -})(); - -/** - * Function: getBrowserName - * - * Returns: - * {String} A string which specifies which is the current - * browser in which we are running. - * - * Currently-supported browser detection and codes: - * * 'opera' -- Opera - * * 'msie' -- Internet Explorer - * * 'safari' -- Safari - * * 'firefox' -- Firefox - * * 'mozilla' -- Mozilla - * - * If we are unable to property identify the browser, we - * return an empty string. - */ -OpenLayers.Util.getBrowserName = function() { - return OpenLayers.BROWSER_NAME; -}; - -/** - * Method: getRenderedDimensions - * Renders the contentHTML offscreen to determine actual dimensions for - * popup sizing. As we need layout to determine dimensions the content - * is rendered -9999px to the left and absolute to ensure the - * scrollbars do not flicker - * - * Parameters: - * contentHTML - * size - {} If either the 'w' or 'h' properties is - * specified, we fix that dimension of the div to be measured. This is - * useful in the case where we have a limit in one dimension and must - * therefore meaure the flow in the other dimension. - * options - {Object} - * - * Allowed Options: - * displayClass - {String} Optional parameter. A CSS class name(s) string - * to provide the CSS context of the rendered content. - * containerElement - {DOMElement} Optional parameter. Insert the HTML to - * this node instead of the body root when calculating dimensions. - * - * Returns: - * {} - */ -OpenLayers.Util.getRenderedDimensions = function(contentHTML, size, options) { - - var w, h; - - // create temp container div with restricted size - var container = document.createElement("div"); - container.style.visibility = "hidden"; - - var containerElement = (options && options.containerElement) - ? options.containerElement : document.body; - - // Opera and IE7 can't handle a node with position:aboslute if it inherits - // position:absolute from a parent. - var parentHasPositionAbsolute = false; - var superContainer = null; - var parent = containerElement; - while (parent && parent.tagName.toLowerCase()!="body") { - var parentPosition = OpenLayers.Element.getStyle(parent, "position"); - if(parentPosition == "absolute") { - parentHasPositionAbsolute = true; - break; - } else if (parentPosition && parentPosition != "static") { - break; - } - parent = parent.parentNode; - } - if(parentHasPositionAbsolute && (containerElement.clientHeight === 0 || - containerElement.clientWidth === 0) ){ - superContainer = document.createElement("div"); - superContainer.style.visibility = "hidden"; - superContainer.style.position = "absolute"; - superContainer.style.overflow = "visible"; - superContainer.style.width = document.body.clientWidth + "px"; - superContainer.style.height = document.body.clientHeight + "px"; - superContainer.appendChild(container); - } - container.style.position = "absolute"; - - //fix a dimension, if specified. - if (size) { - if (size.w) { - w = size.w; - container.style.width = w + "px"; - } else if (size.h) { - h = size.h; - container.style.height = h + "px"; - } - } - - //add css classes, if specified - if (options && options.displayClass) { - container.className = options.displayClass; - } - - // create temp content div and assign content - var content = document.createElement("div"); - content.innerHTML = contentHTML; - - // we need overflow visible when calculating the size - content.style.overflow = "visible"; - if (content.childNodes) { - for (var i=0, l=content.childNodes.length; i= 60) { - coordinateseconds -= 60; - coordinateminutes += 1; - if( coordinateminutes >= 60) { - coordinateminutes -= 60; - coordinatedegrees += 1; - } - } - - if( coordinatedegrees < 10 ) { - coordinatedegrees = "0" + coordinatedegrees; - } - var str = coordinatedegrees + "\u00B0"; - - if (dmsOption.indexOf('dm') >= 0) { - if( coordinateminutes < 10 ) { - coordinateminutes = "0" + coordinateminutes; - } - str += coordinateminutes + "'"; - - if (dmsOption.indexOf('dms') >= 0) { - if( coordinateseconds < 10 ) { - coordinateseconds = "0" + coordinateseconds; - } - str += coordinateseconds + '"'; - } - } - - if (axis == "lon") { - str += coordinate < 0 ? OpenLayers.i18n("W") : OpenLayers.i18n("E"); - } else { - str += coordinate < 0 ? OpenLayers.i18n("S") : OpenLayers.i18n("N"); - } - return str; -}; - -/* ====================================================================== - 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 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 when a button was - * clicked. Buttons are detected by the "olButton" class. - * - * This event type makes sure that button clicks do not interfere with other - * events that are registered on the same . - * - * Event types provided by this extension: - * - *buttonclick* Triggered when a button is clicked. Listeners receive an - * object with a *buttonElement* property referencing the dom element of - * the clicked button, and an *buttonXY* property with the click position - * relative to the button. - */ -OpenLayers.Events.buttonclick = OpenLayers.Class({ - - /** - * Property: target - * {} The events instance that the buttonclick event will - * be triggered on. - */ - target: null, - - /** - * Property: events - * {Array} Events to observe and conditionally stop from propagating when - * an element with the olButton class (or its olAlphaImg child) is - * clicked. - */ - events: [ - 'mousedown', 'mouseup', 'click', 'dblclick', - 'touchstart', 'touchmove', 'touchend', 'keydown' - ], - - /** - * Property: startRegEx - * {RegExp} Regular expression to test Event.type for events that start - * a buttonclick sequence. - */ - startRegEx: /^mousedown|touchstart$/, - - /** - * Property: cancelRegEx - * {RegExp} Regular expression to test Event.type for events that cancel - * a buttonclick sequence. - */ - cancelRegEx: /^touchmove$/, - - /** - * Property: completeRegEx - * {RegExp} Regular expression to test Event.type for events that complete - * a buttonclick sequence. - */ - completeRegEx: /^mouseup|touchend$/, - - /** - * Property: startEvt - * {Event} The event that started the click sequence - */ - - /** - * Constructor: OpenLayers.Events.buttonclick - * Construct a buttonclick event type. Applications are not supposed to - * create instances of this class - they are created on demand by - * instances. - * - * Parameters: - * target - {} The events instance that the buttonclick - * event will be triggered on. - */ - initialize: function(target) { - this.target = target; - for (var i=this.events.length-1; i>=0; --i) { - this.target.register(this.events[i], this, this.buttonClick, { - extension: true - }); - } - }, - - /** - * Method: destroy - */ - destroy: function() { - for (var i=this.events.length-1; i>=0; --i) { - this.target.unregister(this.events[i], this, this.buttonClick); - } - delete this.target; - }, - - /** - * Method: getPressedButton - * Get the pressed button, if any. Returns undefined if no button - * was pressed. - * - * Arguments: - * element - {DOMElement} The event target. - * - * Returns: - * {DOMElement} The button element, or undefined. - */ - getPressedButton: function(element) { - var depth = 3, // limit the search depth - button; - do { - if(OpenLayers.Element.hasClass(element, "olButton")) { - // hit! - button = element; - break; - } - element = element.parentNode; - } while(--depth > 0 && element); - return button; - }, - - /** - * Method: ignore - * Check for event target elements that should be ignored by OpenLayers. - * - * Parameters: - * element - {DOMElement} The event target. - */ - ignore: function(element) { - var depth = 3, - ignore = false; - do { - if (element.nodeName.toLowerCase() === 'a') { - ignore = true; - break; - } - element = element.parentNode; - } while (--depth > 0 && element); - return ignore; - }, - - /** - * Method: buttonClick - * Check if a button was clicked, and fire the buttonclick event - * - * Parameters: - * evt - {Event} - */ - buttonClick: function(evt) { - var propagate = true, - element = OpenLayers.Event.element(evt); - if (element && (OpenLayers.Event.isLeftClick(evt) || !~evt.type.indexOf("mouse"))) { - // was a button pressed? - var button = this.getPressedButton(element); - if (button) { - if (evt.type === "keydown") { - switch (evt.keyCode) { - case OpenLayers.Event.KEY_RETURN: - case OpenLayers.Event.KEY_SPACE: - this.target.triggerEvent("buttonclick", { - buttonElement: button - }); - OpenLayers.Event.stop(evt); - propagate = false; - break; - } - } else if (this.startEvt) { - if (this.completeRegEx.test(evt.type)) { - var pos = OpenLayers.Util.pagePosition(button); - var viewportElement = OpenLayers.Util.getViewportElement(); - var scrollTop = window.pageYOffset || viewportElement.scrollTop; - var scrollLeft = window.pageXOffset || viewportElement.scrollLeft; - pos[0] = pos[0] - scrollLeft; - pos[1] = pos[1] - scrollTop; - - this.target.triggerEvent("buttonclick", { - buttonElement: button, - buttonXY: { - x: this.startEvt.clientX - pos[0], - y: this.startEvt.clientY - pos[1] - } - }); - } - if (this.cancelRegEx.test(evt.type)) { - delete this.startEvt; - } - OpenLayers.Event.stop(evt); - propagate = false; - } - if (this.startRegEx.test(evt.type)) { - this.startEvt = evt; - OpenLayers.Event.stop(evt); - propagate = false; - } - } else { - propagate = !this.ignore(OpenLayers.Event.element(evt)); - delete this.startEvt; - } - } - return propagate; - } - -}); -/* ====================================================================== - 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/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= 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/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)} An array of geometries to add - */ - addComponents: function(components){ - if(!(OpenLayers.Util.isArray(components))) { - components = [components]; - } - for(var i=0, len=components.length; i} 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. - * - * 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} 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} 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 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} 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} Center point for the rotation - */ - rotate: function(angle, origin) { - for(var i=0, len=this.components.length; i} 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} 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} 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} - * dest - {} - * - * Returns: - * {} - */ - transform: function(source, dest) { - if (source && dest) { - for (var i=0, len=this.components.length; i} 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 - */ -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/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} 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 - */ -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 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 0) { - // sort intersections along segment - var xDir = seg.x1 < seg.x2 ? 1 : -1; - var yDir = seg.y1 < seg.y2 ? 1 : -1; - result = { - lines: lines, - points: intersections.sort(function(p1, p2) { - return (xDir * p1.x - xDir * p2.x) || (yDir * p1.y - yDir * p2.y); - }) - }; - } - return result; - }, - - /** - * Method: split - * Use this geometry (the source) to attempt to split a target geometry. - * - * Parameters: - * target - {} The target geometry. - * options - {Object} Properties of this object will be used to determine - * how the split is conducted. - * - * Valid options: - * mutual - {Boolean} Split the source geometry in addition to the target - * geometry. Default is false. - * edge - {Boolean} Allow splitting when only edges intersect. Default is - * true. If false, a vertex on the source 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 an existing vertex on the source - * will be assumed to occur at the vertex. - * - * Returns: - * {Array} A list of geometries (of this same type as the target) that - * result from splitting the target with the source geometry. The - * source and target geometry will remain unmodified. If no split - * results, null will be returned. If mutual is true and a split - * results, return will be an array of two arrays - the first will be - * all geometries that result from splitting the source geometry and - * the second will be all geometries that result from splitting the - * target geometry. - */ - split: function(target, options) { - var results = null; - var mutual = options && options.mutual; - var sourceSplit, targetSplit, sourceParts, targetParts; - if(target instanceof OpenLayers.Geometry.LineString) { - var verts = this.getVertices(); - var vert1, vert2, seg, splits, lines, point; - var points = []; - sourceParts = []; - for(var i=0, stop=verts.length-2; i<=stop; ++i) { - vert1 = verts[i]; - vert2 = verts[i+1]; - seg = { - x1: vert1.x, y1: vert1.y, - x2: vert2.x, y2: vert2.y - }; - targetParts = targetParts || [target]; - if(mutual) { - points.push(vert1.clone()); - } - for(var j=0; j 0) { - lines.unshift(j, 1); - Array.prototype.splice.apply(targetParts, lines); - j += lines.length - 2; - } - if(mutual) { - for(var k=0, len=splits.points.length; k 0 && points.length > 0) { - points.push(vert2.clone()); - sourceParts.push(new OpenLayers.Geometry.LineString(points)); - } - } else { - results = target.splitWith(this, options); - } - if(targetParts && targetParts.length > 1) { - targetSplit = true; - } else { - targetParts = []; - } - if(sourceParts && sourceParts.length > 1) { - sourceSplit = true; - } else { - sourceParts = []; - } - if(targetSplit || sourceSplit) { - if(mutual) { - results = [sourceParts, targetParts]; - } else { - results = targetParts; - } - } - return results; - }, - - /** - * Method: splitWith - * Split this geometry (the target) with the given geometry (the source). - * - * Parameters: - * geometry - {} A geometry used to split this - * geometry (the source). - * options - {Object} Properties of this object will be used to determine - * how the split is conducted. - * - * Valid options: - * mutual - {Boolean} Split the source geometry in addition to the target - * geometry. Default is false. - * edge - {Boolean} Allow splitting when only edges intersect. Default is - * true. If false, a vertex on the source 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 an existing vertex on the source - * will be assumed to occur at the vertex. - * - * Returns: - * {Array} A list of geometries (of this same type as the target) that - * result from splitting the target with the source geometry. The - * source and target geometry will remain unmodified. If no split - * results, null will be returned. If mutual is true and a split - * results, return will be an array of two arrays - the first will be - * all geometries that result from splitting the source geometry and - * the second will be all geometries that result from splitting the - * target geometry. - */ - splitWith: function(geometry, options) { - return geometry.split(this, 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) { - var vertices; - if(nodes === true) { - vertices = [ - this.components[0], - this.components[this.components.length-1] - ]; - } else if (nodes === false) { - vertices = this.components.slice(1, this.components.length-1); - } else { - vertices = this.components.slice(); - } - return vertices; - }, - - /** - * 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 result, best = {}; - var min = Number.POSITIVE_INFINITY; - if(geometry instanceof OpenLayers.Geometry.Point) { - var segs = this.getSortedSegments(); - var x = geometry.x; - var y = geometry.y; - var seg; - for(var i=0, len=segs.length; i x && ((y > seg.y1 && y < seg.y2) || (y < seg.y1 && y > seg.y2))) { - break; - } - } - } - if(details) { - best = { - distance: best.distance, - x0: best.x, y0: best.y, - x1: x, y1: y - }; - } else { - best = best.distance; - } - } else if(geometry instanceof OpenLayers.Geometry.LineString) { - var segs0 = this.getSortedSegments(); - var segs1 = geometry.getSortedSegments(); - var seg0, seg1, intersection, x0, y0; - var len1 = segs1.length; - var interOptions = {point: true}; - outer: for(var i=0, len=segs0.length; i maxDistance) { - maxDistance = distance; - indexFarthest = index; - } - } - - if (maxDistance > tolerance && indexFarthest != firstPoint) { - //Add the largest point that exceeds the tolerance - pointIndexsToKeep.push(indexFarthest); - douglasPeuckerReduction(points, firstPoint, indexFarthest, tolerance); - douglasPeuckerReduction(points, indexFarthest, lastPoint, tolerance); - } - }; - - /** - * Private function calculating the perpendicular distance - * TODO: check whether OpenLayers.Geometry.LineString::distanceTo() is faster or slower - */ - var perpendicularDistance = function(point1, point2, point){ - //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)| *Area of triangle - //Base = v((x1-x2)²+(x1-x2)²) *Base of Triangle* - //Area = .5*Base*H *Solve for height - //Height = Area/.5/Base - - var area = Math.abs(0.5 * (point1.x * point2.y + point2.x * point.y + point.x * point1.y - point2.x * point1.y - point.x * point2.y - point1.x * point.y)); - var bottom = Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2)); - var height = area / bottom * 2; - - return height; - }; - - var firstPoint = 0; - var lastPoint = points.length - 1; - var pointIndexsToKeep = []; - - //Add the first and last index to the keepers - pointIndexsToKeep.push(firstPoint); - pointIndexsToKeep.push(lastPoint); - - //The first and the last point cannot be the same - while (points[firstPoint].equals(points[lastPoint])) { - lastPoint--; - //Addition: the first point not equal to first point in the LineString is kept as well - pointIndexsToKeep.push(lastPoint); - } - - douglasPeuckerReduction(points, firstPoint, lastPoint, tolerance); - var returnPoints = []; - pointIndexsToKeep.sort(compareNumbers); - for (var index = 0; index < pointIndexsToKeep.length; index++) { - returnPoints.push(points[pointIndexsToKeep[index]]); - } - return new OpenLayers.Geometry.LineString(returnPoints); - - } - else { - return this; - } - }, - - CLASS_NAME: "OpenLayers.Geometry.LineString" -}); -/* ====================================================================== - OpenLayers/Geometry/LinearRing.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/LineString.js - */ - -/** - * Class: OpenLayers.Geometry.LinearRing - * - * A Linear Ring is a special LineString which is closed. It closes itself - * automatically on every addPoint/removePoint by adding a copy of the first - * point as the last point. - * - * Also, as it is the first in the line family to close itself, a getArea() - * function is defined to calculate the enclosed area of the linearRing - * - * Inherits: - * - - */ -OpenLayers.Geometry.LinearRing = OpenLayers.Class( - OpenLayers.Geometry.LineString, { - - /** - * 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.LinearRing - * Linear rings are constructed with an array of points. This array - * can represent a closed or open ring. If the ring is open (the last - * point does not equal the first point), the constructor will close - * the ring. If the ring is already closed (the last point does equal - * the first point), it will be left closed. - * - * Parameters: - * points - {Array()} points - */ - - /** - * APIMethod: addComponent - * Adds a point to geometry components. If the point is to be added to - * the end of the components array and it is the same as the last point - * already in that array, the duplicate point is not added. This has - * the effect of closing the ring if it is not already closed, and - * doing the right thing if it is already closed. This behavior can - * be overridden by calling the method with a non-null index as the - * second argument. - * - * Parameters: - * point - {} - * index - {Integer} Index into the array to insert the component - * - * Returns: - * {Boolean} Was the Point successfully added? - */ - addComponent: function(point, index) { - var added = false; - - //remove last point - var lastPoint = this.components.pop(); - - // given an index, add the point - // without an index only add non-duplicate points - if(index != null || !point.equals(lastPoint)) { - added = OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, - arguments); - } - - //append copy of first point - var firstPoint = this.components[0]; - OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, - [firstPoint]); - - return added; - }, - - /** - * APIMethod: removeComponent - * Removes a point from geometry components. - * - * Parameters: - * point - {} - * - * Returns: - * {Boolean} The component was removed. - */ - removeComponent: function(point) { - var removed = this.components && (this.components.length > 3); - if (removed) { - //remove last point - this.components.pop(); - - //remove our point - OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this, - arguments); - //append copy of first point - var firstPoint = this.components[0]; - OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, - [firstPoint]); - } - return removed; - }, - - /** - * 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} Center point for the rotation - */ - rotate: function(angle, origin) { - for(var i=0, len=this.components.length; i} 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, len=this.components.length; i} - * dest - {} - * - * Returns: - * {} - */ - transform: function(source, dest) { - if (source && dest) { - for (var i=0, len=this.components.length; i} The centroid of the collection - */ - getCentroid: function() { - if (this.components) { - var len = this.components.length; - if (len > 0 && len <= 2) { - return this.components[0].clone(); - } else if (len > 2) { - var sumX = 0.0; - var sumY = 0.0; - var x0 = this.components[0].x; - var y0 = this.components[0].y; - var area = -1 * this.getArea(); - if (area != 0) { - for (var i = 0; i < len - 1; i++) { - var b = this.components[i]; - var c = this.components[i+1]; - sumX += (b.x + c.x - 2 * x0) * ((b.x - x0) * (c.y - y0) - (c.x - x0) * (b.y - y0)); - sumY += (b.y + c.y - 2 * y0) * ((b.x - x0) * (c.y - y0) - (c.x - x0) * (b.y - y0)); - } - var x = x0 + sumX / (6 * area); - var y = y0 + sumY / (6 * area); - } else { - for (var i = 0; i < len - 1; i++) { - sumX += this.components[i].x; - sumY += this.components[i].y; - } - var x = sumX / (len - 1); - var y = sumY / (len - 1); - } - return new OpenLayers.Geometry.Point(x, y); - } else { - return null; - } - } - }, - - /** - * APIMethod: getArea - * Note - The area is positive if the ring is oriented CW, otherwise - * it will be negative. - * - * Returns: - * {Float} The signed area for a ring. - */ - getArea: function() { - var area = 0.0; - if ( this.components && (this.components.length > 2)) { - var sum = 0.0; - for (var i=0, len=this.components.length; i} 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 signed geodesic area of the polygon in square - * meters. - */ - getGeodesicArea: function(projection) { - var ring = this; // so we can work with a clone if needed - if(projection) { - var gg = new OpenLayers.Projection("EPSG:4326"); - if(!gg.equals(projection)) { - ring = this.clone().transform(projection, gg); - } - } - var area = 0.0; - var len = ring.components && ring.components.length; - if(len > 2) { - var p1, p2; - for(var i=0; i} - * - * Returns: - * {Boolean | Number} The point is inside the linear ring. Returns 1 if - * the point is coincident with an edge. Returns boolean otherwise. - */ - containsPoint: function(point) { - var approx = OpenLayers.Number.limitSigDigs; - var digs = 14; - var px = approx(point.x, digs); - var py = approx(point.y, digs); - function getX(y, x1, y1, x2, y2) { - return (y - y2) * ((x2 - x1) / (y2 - y1)) + x2; - } - var numSeg = this.components.length - 1; - var start, end, x1, y1, x2, y2, cx, cy; - var crosses = 0; - for(var i=0; i= x1 && px <= x2) || // right or vert - x1 >= x2 && (px <= x1 && px >= x2)) { // left or vert - // point on edge - crosses = -1; - break; - } - } - // ignore other horizontal edges - continue; - } - cx = approx(getX(py, x1, y1, x2, y2), digs); - if(cx == px) { - // point on line - if(y1 < y2 && (py >= y1 && py <= y2) || // upward - y1 > y2 && (py <= y1 && py >= y2)) { // downward - // point on edge - crosses = -1; - break; - } - } - if(cx <= px) { - // no crossing to the right - continue; - } - if(x1 != x2 && (cx < Math.min(x1, x2) || cx > Math.max(x1, x2))) { - // no crossing - continue; - } - if(y1 < y2 && (py >= y1 && py < y2) || // upward - y1 > y2 && (py < y1 && py >= y2)) { // downward - ++crosses; - } - } - var contained = (crosses == -1) ? - // on edge - 1 : - // even (out) or odd (in) - !!(crosses & 1); - - return contained; - }, - - /** - * 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.containsPoint(geometry); - } else if(geometry.CLASS_NAME == "OpenLayers.Geometry.LineString") { - intersect = geometry.intersects(this); - } else if(geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") { - intersect = OpenLayers.Geometry.LineString.prototype.intersects.apply( - this, [geometry] - ); - } else { - // check for component intersections - for(var i=0, len=geometry.components.length; i transform-origin - * or WebkitTransformOrigin -> -webkit-transform-origin - * - * Parameters: - * prefixedDom - {String} The property to convert - * - * Returns: - * {String} The CSS property - */ - function domToCss(prefixedDom) { - if (!prefixedDom) { return null; } - return prefixedDom. - replace(/([A-Z])/g, function(c) { return "-" + c.toLowerCase(); }). - replace(/^ms-/, "-ms-"); - } - - /** - * APIMethod: css - * Detect which property is used for a CSS property - * - * Parameters: - * property - {String} The standard (unprefixed) CSS property name - * - * Returns: - * {String} The standard CSS property, prefixed property or null if not - * supported - */ - function css(property) { - if (cssCache[property] === undefined) { - var domProperty = property. - replace(/(-[\s\S])/g, function(c) { return c.charAt(1).toUpperCase(); }); - var prefixedDom = style(domProperty); - cssCache[property] = domToCss(prefixedDom); - } - return cssCache[property]; - } - - /** - * APIMethod: js - * Detect which property is used for a JS property/method - * - * Parameters: - * obj - {Object} The object to test on - * property - {String} The standard (unprefixed) JS property name - * - * Returns: - * {String} The standard JS property, prefixed property or null if not - * supported - */ - function js(obj, property) { - if (jsCache[property] === undefined) { - var tmpProp, - i = 0, - l = VENDOR_PREFIXES.length, - prefix, - isStyleObj = (typeof obj.cssText !== "undefined"); - - jsCache[property] = null; - for(; i in series for some - * duration. - * - * Parameters: - * callback - {Function} The function to be called at the next animation frame. - * duration - {Number} Optional duration for the loop. If not provided, the - * animation loop will execute indefinitely. - * element - {DOMElement} Optional element that visually bounds the animation. - * - * Returns: - * {Number} Identifier for the animation loop. Used to stop animations with - * . - */ - function start(callback, duration, element) { - duration = duration > 0 ? duration : Number.POSITIVE_INFINITY; - var id = ++counter; - var start = +new Date; - loops[id] = function() { - if (loops[id] && +new Date - start <= duration) { - callback(); - if (loops[id]) { - requestFrame(loops[id], element); - } - } else { - delete loops[id]; - } - }; - requestFrame(loops[id], element); - return id; - } - - /** - * Function: stop - * Terminates an animation loop started with . - * - * Parameters: - * id - {Number} Identifier returned from . - */ - function stop(id) { - delete loops[id]; - } - - return { - isNative: isNative, - requestFrame: requestFrame, - start: start, - stop: stop - }; - -})(window); -/* ====================================================================== - 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. */ - -/** - * @requires OpenLayers/BaseTypes/Class.js - * @requires OpenLayers/Animation.js - */ - -/** - * Namespace: OpenLayers.Tween - */ -OpenLayers.Tween = OpenLayers.Class({ - - /** - * APIProperty: easing - * {(Function)} Easing equation used for the animation - * Defaultly set to OpenLayers.Easing.Expo.easeOut - */ - easing: null, - - /** - * APIProperty: begin - * {Object} Values to start the animation with - */ - begin: null, - - /** - * APIProperty: finish - * {Object} Values to finish the animation with - */ - finish: null, - - /** - * APIProperty: duration - * {int} duration of the tween (number of steps) - */ - duration: null, - - /** - * APIProperty: callbacks - * {Object} An object with start, eachStep and done properties whose values - * are functions to be call during the animation. They are passed the - * current computed value as argument. - */ - callbacks: null, - - /** - * Property: time - * {int} Step counter - */ - time: null, - - /** - * APIProperty: minFrameRate - * {Number} The minimum framerate for animations in frames per second. After - * each step, the time spent in the animation is compared to the calculated - * time at this frame rate. If the animation runs longer than the calculated - * time, the next step is skipped. Default is 30. - */ - minFrameRate: null, - - /** - * Property: startTime - * {Number} The timestamp of the first execution step. Used for skipping - * frames - */ - startTime: null, - - /** - * Property: animationId - * {int} Loop id returned by OpenLayers.Animation.start - */ - animationId: null, - - /** - * Property: playing - * {Boolean} Tells if the easing is currently playing - */ - playing: false, - - /** - * Constructor: OpenLayers.Tween - * Creates a Tween. - * - * Parameters: - * easing - {(Function)} easing function method to use - */ - initialize: function(easing) { - this.easing = (easing) ? easing : OpenLayers.Easing.Expo.easeOut; - }, - - /** - * APIMethod: start - * Plays the Tween, and calls the callback method on each step - * - * Parameters: - * begin - {Object} values to start the animation with - * finish - {Object} values to finish the animation with - * duration - {int} duration of the tween (number of steps) - * options - {Object} hash of options (callbacks (start, eachStep, done), - * minFrameRate) - */ - start: function(begin, finish, duration, options) { - this.playing = true; - this.begin = begin; - this.finish = finish; - this.duration = duration; - this.callbacks = options.callbacks; - this.minFrameRate = options.minFrameRate || 30; - this.time = 0; - this.startTime = new Date().getTime(); - OpenLayers.Animation.stop(this.animationId); - this.animationId = null; - if (this.callbacks && this.callbacks.start) { - this.callbacks.start.call(this, this.begin); - } - this.animationId = OpenLayers.Animation.start( - OpenLayers.Function.bind(this.play, this) - ); - }, - - /** - * APIMethod: stop - * Stops the Tween, and calls the done callback - * Doesn't do anything if animation is already finished - */ - stop: function() { - if (!this.playing) { - return; - } - - if (this.callbacks && this.callbacks.done) { - this.callbacks.done.call(this, this.finish); - } - OpenLayers.Animation.stop(this.animationId); - this.animationId = null; - this.playing = false; - }, - - /** - * Method: play - * Calls the appropriate easing method - */ - play: function() { - var value = {}; - for (var i in this.begin) { - var b = this.begin[i]; - var f = this.finish[i]; - if (b == null || f == null || isNaN(b) || isNaN(f)) { - throw new TypeError('invalid value for Tween'); - } - - var c = f - b; - value[i] = this.easing.apply(this, [this.time, b, c, this.duration]); - } - this.time++; - - if (this.callbacks && this.callbacks.eachStep) { - // skip frames if frame rate drops below threshold - if ((new Date().getTime() - this.startTime) / this.time <= 1000 / this.minFrameRate) { - this.callbacks.eachStep.call(this, value); - } - } - - if (this.time > this.duration) { - this.stop(); - } - }, - - /** - * Create empty functions for all easing methods. - */ - CLASS_NAME: "OpenLayers.Tween" -}); - -/** - * Namespace: OpenLayers.Easing - * - * Credits: - * Easing Equations by Robert Penner, - */ -OpenLayers.Easing = { - /** - * Create empty functions for all easing methods. - */ - CLASS_NAME: "OpenLayers.Easing" -}; - -/** - * Namespace: OpenLayers.Easing.Linear - */ -OpenLayers.Easing.Linear = { - - /** - * Function: easeIn - * - * Parameters: - * t - {Float} time - * b - {Float} beginning position - * c - {Float} total change - * d - {Float} duration of the transition - * - * Returns: - * {Float} - */ - easeIn: function(t, b, c, d) { - return c*t/d + b; - }, - - /** - * Function: easeOut - * - * Parameters: - * t - {Float} time - * b - {Float} beginning position - * c - {Float} total change - * d - {Float} duration of the transition - * - * Returns: - * {Float} - */ - easeOut: function(t, b, c, d) { - return c*t/d + b; - }, - - /** - * Function: easeInOut - * - * Parameters: - * t - {Float} time - * b - {Float} beginning position - * c - {Float} total change - * d - {Float} duration of the transition - * - * Returns: - * {Float} - */ - easeInOut: function(t, b, c, d) { - return c*t/d + b; - }, - - CLASS_NAME: "OpenLayers.Easing.Linear" -}; - -/** - * Namespace: OpenLayers.Easing.Expo - */ -OpenLayers.Easing.Expo = { - - /** - * Function: easeIn - * - * Parameters: - * t - {Float} time - * b - {Float} beginning position - * c - {Float} total change - * d - {Float} duration of the transition - * - * Returns: - * {Float} - */ - easeIn: function(t, b, c, d) { - return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; - }, - - /** - * Function: easeOut - * - * Parameters: - * t - {Float} time - * b - {Float} beginning position - * c - {Float} total change - * d - {Float} duration of the transition - * - * Returns: - * {Float} - */ - easeOut: function(t, b, c, d) { - return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; - }, - - /** - * Function: easeInOut - * - * Parameters: - * t - {Float} time - * b - {Float} beginning position - * c - {Float} total change - * d - {Float} duration of the transition - * - * Returns: - * {Float} - */ - easeInOut: function(t, b, c, d) { - if (t==0) return b; - if (t==d) return b+c; - if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; - return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; - }, - - CLASS_NAME: "OpenLayers.Easing.Expo" -}; - -/** - * Namespace: OpenLayers.Easing.Quad - */ -OpenLayers.Easing.Quad = { - - /** - * Function: easeIn - * - * Parameters: - * t - {Float} time - * b - {Float} beginning position - * c - {Float} total change - * d - {Float} duration of the transition - * - * Returns: - * {Float} - */ - easeIn: function(t, b, c, d) { - return c*(t/=d)*t + b; - }, - - /** - * Function: easeOut - * - * Parameters: - * t - {Float} time - * b - {Float} beginning position - * c - {Float} total change - * d - {Float} duration of the transition - * - * Returns: - * {Float} - */ - easeOut: function(t, b, c, d) { - return -c *(t/=d)*(t-2) + b; - }, - - /** - * Function: easeInOut - * - * Parameters: - * t - {Float} time - * b - {Float} beginning position - * c - {Float} total change - * d - {Float} duration of the transition - * - * Returns: - * {Float} - */ - easeInOut: function(t, b, c, d) { - if ((t/=d/2) < 1) return c/2*t*t + b; - return -c/2 * ((--t)*(t-2) - 1) + b; - }, - - CLASS_NAME: "OpenLayers.Easing.Quad" -}; -/* ====================================================================== - 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/BaseTypes/Class.js - * @requires OpenLayers/Util.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. - */ -OpenLayers.Projection = OpenLayers.Class({ - - /** - * Property: proj - * {Object} Proj4js.Proj instance. - */ - proj: null, - - /** - * Property: projCode - * {String} - */ - projCode: null, - - /** - * 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: - * 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. - */ - getCode: function() { - return this.proj ? this.proj.srsCode : this.projCode; - }, - - /** - * 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; - }, - - /** - * 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=0; --i) { - map(mercator[i], geographic); - } - for (i=geographic.length-1; i>=0; --i) { - map(geographic[i], mercator); - } - -})(); -/* ====================================================================== - OpenLayers/Map.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/Util/vendorPrefix.js - * @requires OpenLayers/Events.js - * @requires OpenLayers/Tween.js - * @requires OpenLayers/Projection.js - */ - -/** - * Class: OpenLayers.Map - * Instances of OpenLayers.Map are interactive maps embedded in a web page. - * Create a new map with the constructor. - * - * On their own maps do not provide much functionality. To extend a map - * it's necessary to add controls () and - * layers () to the map. - */ -OpenLayers.Map = OpenLayers.Class({ - - /** - * Constant: Z_INDEX_BASE - * {Object} Base z-indexes for different classes of thing - */ - Z_INDEX_BASE: { - BaseLayer: 100, - Overlay: 325, - Feature: 725, - Popup: 750, - Control: 1000 - }, - - /** - * APIProperty: events - * {} - * - * Register a listener for a particular event with the following syntax: - * (code) - * map.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 map.events.object. - * element - {DOMElement} A reference to map.events.element. - * - * Browser events have the following additional properties: - * xy - {} The pixel location of the event (relative - * to the the map viewport). - * - * Supported map event types: - * preaddlayer - triggered before a layer has been added. The event - * object will include a *layer* property that references the layer - * to be added. When a listener returns "false" the adding will be - * aborted. - * addlayer - triggered after a layer has been added. The event object - * will include a *layer* property that references the added layer. - * preremovelayer - triggered before a layer has been removed. The event - * object will include a *layer* property that references the layer - * to be removed. When a listener returns "false" the removal will be - * aborted. - * removelayer - triggered after a layer has been removed. The event - * object will include a *layer* property that references the removed - * layer. - * changelayer - triggered after a layer name change, order change, - * opacity change, params change, visibility change (actual visibility, - * not the layer's visibility property) or attribution change (due to - * extent change). Listeners will receive an event object with *layer* - * and *property* properties. The *layer* property will be a reference - * to the changed layer. The *property* property will be a key to the - * changed property (name, order, opacity, params, visibility or - * attribution). - * movestart - triggered after the start of a drag, pan, or zoom. The event - * object may include a *zoomChanged* property that tells whether the - * zoom has changed. - * move - triggered after each drag, pan, or zoom - * moveend - triggered after a drag, pan, or zoom completes - * zoomend - triggered after a zoom completes - * mouseover - triggered after mouseover the map - * mouseout - triggered after mouseout the map - * mousemove - triggered after mousemove the map - * changebaselayer - triggered after the base layer changes - * updatesize - triggered after the method was executed - */ - - /** - * Property: id - * {String} Unique identifier for the map - */ - id: null, - - /** - * Property: fractionalZoom - * {Boolean} For a base layer that supports it, allow the map resolution - * to be set to a value between one of the values in the resolutions - * array. Default is false. - * - * When fractionalZoom is set to true, it is possible to zoom to - * an arbitrary extent. This requires a base layer from a source - * that supports requests for arbitrary extents (i.e. not cached - * tiles on a regular lattice). This means that fractionalZoom - * will not work with commercial layers (Google, Yahoo, VE), layers - * using TileCache, or any other pre-cached data sources. - * - * If you are using fractionalZoom, then you should also use - * instead of layer.resolutions[zoom] as the - * former works for non-integer zoom levels. - */ - fractionalZoom: false, - - /** - * APIProperty: events - * {} An events object that handles all - * events on the map - */ - events: null, - - /** - * APIProperty: allOverlays - * {Boolean} Allow the map to function with "overlays" only. Defaults to - * false. If true, the lowest layer in the draw order will act as - * the base layer. In addition, if set to true, all layers will - * have isBaseLayer set to false when they are added to the map. - * - * Note: - * If you set map.allOverlays to true, then you *cannot* use - * map.setBaseLayer or layer.setIsBaseLayer. With allOverlays true, - * the lowest layer in the draw layer is the base layer. So, to change - * the base layer, use or to set the layer - * index to 0. - */ - allOverlays: false, - - /** - * APIProperty: div - * {DOMElement|String} The element that contains the map (or an id for - * that element). If the constructor is called - * with two arguments, this should be provided as the first argument. - * Alternatively, the map constructor can be called with the options - * object as the only argument. In this case (one argument), a - * div property may or may not be provided. If the div property - * is not provided, the map can be rendered to a container later - * using the method. - * - * Note: - * If you are calling after map construction, do not use - * auto. Instead, divide your by your - * maximum expected dimension. - */ - div: null, - - /** - * Property: dragging - * {Boolean} The map is currently being dragged. - */ - dragging: false, - - /** - * Property: size - * {} Size of the main div (this.div) - */ - size: null, - - /** - * Property: viewPortDiv - * {HTMLDivElement} The element that represents the map viewport - */ - viewPortDiv: null, - - /** - * Property: layerContainerOrigin - * {} The lonlat at which the later container was - * re-initialized (on-zoom) - */ - layerContainerOrigin: null, - - /** - * Property: layerContainerDiv - * {HTMLDivElement} The element that contains the layers. - */ - layerContainerDiv: null, - - /** - * APIProperty: layers - * {Array()} Ordered list of layers in the map - */ - layers: null, - - /** - * APIProperty: controls - * {Array()} List of controls associated with the map. - * - * If not provided in the map options at construction, the map will - * by default be given the following controls if present in the build: - * - or - * - or - * - - * - - */ - controls: null, - - /** - * Property: popups - * {Array()} List of popups associated with the map - */ - popups: null, - - /** - * APIProperty: baseLayer - * {} The currently selected base layer. This determines - * min/max zoom level, projection, etc. - */ - baseLayer: null, - - /** - * Property: center - * {} The current center of the map - */ - center: null, - - /** - * Property: resolution - * {Float} The resolution of the map. - */ - resolution: null, - - /** - * Property: zoom - * {Integer} The current zoom level of the map - */ - zoom: 0, - - /** - * Property: panRatio - * {Float} The ratio of the current extent within - * which panning will tween. - */ - panRatio: 1.5, - - /** - * APIProperty: options - * {Object} The options object passed to the class constructor. Read-only. - */ - options: null, - - // Options - - /** - * APIProperty: tileSize - * {} Set in the map options to override the default tile - * size for this map. - */ - tileSize: null, - - /** - * APIProperty: projection - * {String} Set in the map options to specify the default projection - * for layers added to this map. When using a projection other than EPSG:4326 - * (CRS:84, Geographic) or EPSG:3857 (EPSG:900913, Web Mercator), - * also set maxExtent, maxResolution or resolutions. Default is "EPSG:4326". - * Note that the projection of the map is usually determined - * by that of the current baseLayer (see and ). - */ - projection: "EPSG:4326", - - /** - * APIProperty: units - * {String} The map units. Possible values are 'degrees' (or 'dd'), 'm', - * 'ft', 'km', 'mi', 'inches'. Normally taken from the projection. - * Only required if both map and layers do not define a projection, - * or if they define a projection which does not define units - */ - units: null, - - /** - * APIProperty: resolutions - * {Array(Float)} A list of map resolutions (map units per pixel) in - * descending order. If this is not set in the layer constructor, it - * will be set based on other resolution related properties - * (maxExtent, maxResolution, maxScale, etc.). - */ - resolutions: null, - - /** - * APIProperty: maxResolution - * {Float} Required if you are not displaying the whole world on a tile - * with the size specified in . - */ - maxResolution: null, - - /** - * APIProperty: minResolution - * {Float} - */ - minResolution: null, - - /** - * APIProperty: maxScale - * {Float} - */ - maxScale: null, - - /** - * APIProperty: minScale - * {Float} - */ - minScale: null, - - /** - * APIProperty: maxExtent - * {|Array} If provided as an array, the array - * should consist of four values (left, bottom, right, top). - * The maximum extent for the map. - * Default depends on projection; if this is one of those defined in OpenLayers.Projection.defaults - * (EPSG:4326 or web mercator), maxExtent will be set to the value defined there; - * else, defaults to null. - * To restrict user panning and zooming of the map, use instead. - * The value for will change calculations for tile URLs. - */ - maxExtent: null, - - /** - * APIProperty: minExtent - * {|Array} If provided as an array, the array - * should consist of four values (left, bottom, right, top). - * The minimum extent for the map. Defaults to null. - */ - minExtent: null, - - /** - * APIProperty: restrictedExtent - * {|Array} If provided as an array, the array - * should consist of four values (left, bottom, right, top). - * Limit map navigation to this extent where possible. - * If a non-null restrictedExtent is set, panning will be restricted - * to the given bounds. In addition, zooming to a resolution that - * displays more than the restricted extent will center the map - * on the restricted extent. If you wish to limit the zoom level - * or resolution, use maxResolution. - */ - restrictedExtent: null, - - /** - * APIProperty: numZoomLevels - * {Integer} Number of zoom levels for the map. Defaults to 16. Set a - * different value in the map options if needed. - */ - numZoomLevels: 16, - - /** - * APIProperty: theme - * {String} Relative path to a CSS file from which to load theme styles. - * Specify null in the map options (e.g. {theme: null}) if you - * want to get cascading style declarations - by putting links to - * stylesheets or style declarations directly in your page. - */ - theme: null, - - /** - * APIProperty: displayProjection - * {} Requires proj4js support for projections other - * than EPSG:4326 or EPSG:900913/EPSG:3857. Projection used by - * several controls to display data to user. If this property is set, - * it will be set on any control which has a null displayProjection - * property at the time the control is added to the map. - */ - displayProjection: null, - - /** - * APIProperty: tileManager - * {|Object} By default, and if the build contains - * TileManager.js, the map will use the TileManager to queue image requests - * and to cache tile image elements. To create a map without a TileManager - * configure the map with tileManager: null. To create a TileManager with - * non-default options, supply the options instead or alternatively supply - * an instance of {}. - */ - - /** - * APIProperty: fallThrough - * {Boolean} Should OpenLayers allow events on the map to fall through to - * other elements on the page, or should it swallow them? (#457) - * Default is to swallow. - */ - fallThrough: false, - - /** - * APIProperty: autoUpdateSize - * {Boolean} Should OpenLayers automatically update the size of the map - * when the resize event is fired. Default is true. - */ - autoUpdateSize: true, - - /** - * 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, - - /** - * Property: panTween - * {} Animated panning tween object, see panTo() - */ - panTween: null, - - /** - * APIProperty: panMethod - * {Function} The Easing function to be used for tweening. Default is - * OpenLayers.Easing.Expo.easeOut. Setting this to 'null' turns off - * animated panning. - */ - panMethod: OpenLayers.Easing.Expo.easeOut, - - /** - * Property: panDuration - * {Integer} The number of steps to be passed to the - * OpenLayers.Tween.start() method when the map is - * panned. - * Default is 50. - */ - panDuration: 50, - - /** - * Property: zoomTween - * {} Animated zooming tween object, see zoomTo() - */ - zoomTween: null, - - /** - * APIProperty: zoomMethod - * {Function} The Easing function to be used for tweening. Default is - * OpenLayers.Easing.Quad.easeOut. Setting this to 'null' turns off - * animated zooming. - */ - zoomMethod: OpenLayers.Easing.Quad.easeOut, - - /** - * Property: zoomDuration - * {Integer} The number of steps to be passed to the - * OpenLayers.Tween.start() method when the map is zoomed. - * Default is 20. - */ - zoomDuration: 20, - - /** - * Property: paddingForPopups - * {} Outside margin of the popup. Used to prevent - * the popup from getting too close to the map border. - */ - paddingForPopups : null, - - /** - * Property: layerContainerOriginPx - * {Object} Cached object representing the layer container origin (in pixels). - */ - layerContainerOriginPx: null, - - /** - * Property: minPx - * {Object} An object with a 'x' and 'y' values that is the lower - * left of maxExtent in viewport pixel space. - * Used to verify in moveByPx that the new location we're moving to - * is valid. It is also used in the getLonLatFromViewPortPx function - * of Layer. - */ - minPx: null, - - /** - * Property: maxPx - * {Object} An object with a 'x' and 'y' values that is the top - * right of maxExtent in viewport pixel space. - * Used to verify in moveByPx that the new location we're moving to - * is valid. - */ - maxPx: null, - - /** - * Constructor: OpenLayers.Map - * Constructor for a new OpenLayers.Map instance. There are two possible - * ways to call the map constructor. See the examples below. - * - * Parameters: - * div - {DOMElement|String} The element or id of an element in your page - * that will contain the map. May be omitted if the
option is - * provided or if you intend to call the method later. - * options - {Object} Optional object with properties to tag onto the map. - * - * Valid options (in addition to the listed API properties): - * center - {|Array} The default initial center of the map. - * If provided as array, the first value is the x coordinate, - * and the 2nd value is the y coordinate. - * Only specify if is provided. - * Note that if an ArgParser/Permalink control is present, - * and the querystring contains coordinates, center will be set - * by that, and this option will be ignored. - * zoom - {Number} The initial zoom level for the map. Only specify if - * is provided. - * Note that if an ArgParser/Permalink control is present, - * and the querystring contains a zoom level, zoom will be set - * by that, and this option will be ignored. - * extent - {|Array} The initial extent of the map. - * If provided as an array, the array should consist of - * four values (left, bottom, right, top). - * Only specify if
and are not provided. - * - * Examples: - * (code) - * // create a map with default options in an element with the id "map1" - * var map = new OpenLayers.Map("map1"); - * - * // create a map with non-default options in an element with id "map2" - * var options = { - * projection: "EPSG:3857", - * maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000), - * center: new OpenLayers.LonLat(-12356463.476333, 5621521.4854095) - * }; - * var map = new OpenLayers.Map("map2", options); - * - * // map with non-default options - same as above but with a single argument, - * // a restricted extent, and using arrays for bounds and center - * var map = new OpenLayers.Map({ - * div: "map_id", - * projection: "EPSG:3857", - * maxExtent: [-18924313.432222, -15538711.094146, 18924313.432222, 15538711.094146], - * restrictedExtent: [-13358338.893333, -9608371.5085962, 13358338.893333, 9608371.5085962], - * center: [-12356463.476333, 5621521.4854095] - * }); - * - * // create a map without a reference to a container - call render later - * var map = new OpenLayers.Map({ - * projection: "EPSG:3857", - * maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000) - * }); - * (end) - */ - initialize: function (div, options) { - - // If only one argument is provided, check if it is an object. - if(arguments.length === 1 && typeof div === "object") { - options = div; - div = options && options.div; - } - - // Simple-type defaults are set in class definition. - // Now set complex-type defaults - this.tileSize = new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH, - OpenLayers.Map.TILE_HEIGHT); - - this.paddingForPopups = new OpenLayers.Bounds(15, 15, 15, 15); - - this.theme = OpenLayers._getScriptLocation() + - 'theme/default/style.css'; - - // backup original options - this.options = OpenLayers.Util.extend({}, options); - - // now override default options - OpenLayers.Util.extend(this, options); - - var projCode = this.projection instanceof OpenLayers.Projection ? - this.projection.projCode : this.projection; - OpenLayers.Util.applyDefaults(this, OpenLayers.Projection.defaults[projCode]); - - // allow extents and center to be arrays - if (this.maxExtent && !(this.maxExtent instanceof OpenLayers.Bounds)) { - this.maxExtent = new OpenLayers.Bounds(this.maxExtent); - } - if (this.minExtent && !(this.minExtent instanceof OpenLayers.Bounds)) { - this.minExtent = new OpenLayers.Bounds(this.minExtent); - } - if (this.restrictedExtent && !(this.restrictedExtent instanceof OpenLayers.Bounds)) { - this.restrictedExtent = new OpenLayers.Bounds(this.restrictedExtent); - } - if (this.center && !(this.center instanceof OpenLayers.LonLat)) { - this.center = new OpenLayers.LonLat(this.center); - } - - // initialize layers array - this.layers = []; - - this.id = OpenLayers.Util.createUniqueID("OpenLayers.Map_"); - - this.div = OpenLayers.Util.getElement(div); - if(!this.div) { - this.div = document.createElement("div"); - this.div.style.height = "1px"; - this.div.style.width = "1px"; - } - - OpenLayers.Element.addClass(this.div, 'olMap'); - - // the viewPortDiv is the outermost div we modify - var id = this.id + "_OpenLayers_ViewPort"; - this.viewPortDiv = OpenLayers.Util.createDiv(id, null, null, null, - "relative", null, - "hidden"); - this.viewPortDiv.style.width = "100%"; - this.viewPortDiv.style.height = "100%"; - this.viewPortDiv.className = "olMapViewport"; - this.div.appendChild(this.viewPortDiv); - - this.events = new OpenLayers.Events( - this, this.viewPortDiv, null, this.fallThrough, - {includeXY: true} - ); - - if (OpenLayers.TileManager && this.tileManager !== null) { - if (!(this.tileManager instanceof OpenLayers.TileManager)) { - this.tileManager = new OpenLayers.TileManager(this.tileManager); - } - this.tileManager.addMap(this); - } - - // the layerContainerDiv is the one that holds all the layers - id = this.id + "_OpenLayers_Container"; - this.layerContainerDiv = OpenLayers.Util.createDiv(id); - this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1; - this.layerContainerOriginPx = {x: 0, y: 0}; - this.applyTransform(); - - this.viewPortDiv.appendChild(this.layerContainerDiv); - - this.updateSize(); - if(this.eventListeners instanceof Object) { - this.events.on(this.eventListeners); - } - - if (this.autoUpdateSize === true) { - // updateSize on catching the window's resize - // Note that this is ok, as updateSize() does nothing if the - // map's size has not actually changed. - this.updateSizeDestroy = OpenLayers.Function.bind(this.updateSize, - this); - OpenLayers.Event.observe(window, 'resize', - this.updateSizeDestroy); - } - - // only append link stylesheet if the theme property is set - if(this.theme) { - // check existing links for equivalent url - var addNode = true; - var nodes = document.getElementsByTagName('link'); - for(var i=0, len=nodes.length; i=0; --i) { - this.controls[i].destroy(); - } - this.controls = null; - } - if (this.layers != null) { - for (var i = this.layers.length - 1; i>=0; --i) { - //pass 'false' to destroy so that map wont try to set a new - // baselayer after each baselayer is removed - this.layers[i].destroy(false); - } - this.layers = null; - } - if (this.viewPortDiv && this.viewPortDiv.parentNode) { - this.viewPortDiv.parentNode.removeChild(this.viewPortDiv); - } - this.viewPortDiv = null; - - if (this.tileManager) { - this.tileManager.removeMap(this); - this.tileManager = null; - } - - if(this.eventListeners) { - this.events.un(this.eventListeners); - this.eventListeners = null; - } - this.events.destroy(); - this.events = null; - - this.options = null; - }, - - /** - * APIMethod: setOptions - * Change the map options - * - * Parameters: - * options - {Object} Hashtable of options to tag to the map - */ - setOptions: function(options) { - var updatePxExtent = this.minPx && - options.restrictedExtent != this.restrictedExtent; - OpenLayers.Util.extend(this, options); - // force recalculation of minPx and maxPx - updatePxExtent && this.moveTo(this.getCachedCenter(), this.zoom, { - forceZoomChange: true - }); - }, - - /** - * APIMethod: getTileSize - * Get the tile size for the map - * - * Returns: - * {} - */ - getTileSize: function() { - return this.tileSize; - }, - - - /** - * APIMethod: getBy - * Get a list of objects given a property and a match item. - * - * Parameters: - * array - {String} A property on the map whose value is an array. - * property - {String} A property on each item of the given array. - * match - {String | Object} A string to match. Can also be a regular - * expression literal or object. In addition, it can be any object - * with a method named test. For reqular expressions or other, if - * match.test(map[array][i][property]) evaluates to true, the item will - * be included in the array returned. If no items are found, an empty - * array is returned. - * - * Returns: - * {Array} An array of items where the given property matches the given - * criteria. - */ - getBy: function(array, property, match) { - var test = (typeof match.test == "function"); - var found = OpenLayers.Array.filter(this[array], function(item) { - return item[property] == match || (test && match.test(item[property])); - }); - return found; - }, - - /** - * APIMethod: getLayersBy - * Get a list of layers with properties matching the given criteria. - * - * Parameters: - * property - {String} A layer property to be matched. - * match - {String | Object} A string to match. Can also be a regular - * expression literal or object. In addition, it can be any object - * with a method named test. For reqular expressions or other, if - * match.test(layer[property]) evaluates to true, the layer will be - * included in the array returned. If no layers are found, an empty - * array is returned. - * - * Returns: - * {Array()} A list of layers matching the given criteria. - * An empty array is returned if no matches are found. - */ - getLayersBy: function(property, match) { - return this.getBy("layers", property, match); - }, - - /** - * APIMethod: getLayersByName - * Get a list of layers with names matching the given name. - * - * Parameters: - * match - {String | Object} A layer name. The name can also be a regular - * expression literal or object. In addition, it can be any object - * with a method named test. For reqular expressions or other, if - * name.test(layer.name) evaluates to true, the layer will be included - * in the list of layers returned. If no layers are found, an empty - * array is returned. - * - * Returns: - * {Array()} A list of layers matching the given name. - * An empty array is returned if no matches are found. - */ - getLayersByName: function(match) { - return this.getLayersBy("name", match); - }, - - /** - * APIMethod: getLayersByClass - * Get a list of layers of a given class (CLASS_NAME). - * - * Parameters: - * match - {String | Object} A layer class name. The match can also be a - * regular expression literal or object. In addition, it can be any - * object with a method named test. For reqular expressions or other, - * if type.test(layer.CLASS_NAME) evaluates to true, the layer will - * be included in the list of layers returned. If no layers are - * found, an empty array is returned. - * - * Returns: - * {Array()} A list of layers matching the given class. - * An empty array is returned if no matches are found. - */ - getLayersByClass: function(match) { - return this.getLayersBy("CLASS_NAME", match); - }, - - /** - * APIMethod: getControlsBy - * Get a list of controls with properties matching the given criteria. - * - * Parameters: - * property - {String} A control property to be matched. - * match - {String | Object} A string to match. Can also be a regular - * expression literal or object. In addition, it can be any object - * with a method named test. For reqular expressions or other, if - * match.test(layer[property]) evaluates to true, the layer will be - * included in the array returned. If no layers are found, an empty - * array is returned. - * - * Returns: - * {Array()} A list of controls matching the given - * criteria. An empty array is returned if no matches are found. - */ - getControlsBy: function(property, match) { - return this.getBy("controls", property, match); - }, - - /** - * APIMethod: getControlsByClass - * Get a list of controls of a given class (CLASS_NAME). - * - * Parameters: - * match - {String | Object} A control class name. The match can also be a - * regular expression literal or object. In addition, it can be any - * object with a method named test. For reqular expressions or other, - * if type.test(control.CLASS_NAME) evaluates to true, the control will - * be included in the list of controls returned. If no controls are - * found, an empty array is returned. - * - * Returns: - * {Array()} A list of controls matching the given class. - * An empty array is returned if no matches are found. - */ - getControlsByClass: function(match) { - return this.getControlsBy("CLASS_NAME", match); - }, - - /********************************************************/ - /* */ - /* Layer Functions */ - /* */ - /* The following functions deal with adding and */ - /* removing Layers to and from the Map */ - /* */ - /********************************************************/ - - /** - * APIMethod: getLayer - * Get a layer based on its id - * - * Parameters: - * id - {String} A layer id - * - * Returns: - * {} The Layer with the corresponding id from the map's - * layer collection, or null if not found. - */ - getLayer: function(id) { - var foundLayer = null; - for (var i=0, len=this.layers.length; i} - * zIdx - {int} - */ - setLayerZIndex: function (layer, zIdx) { - layer.setZIndex( - this.Z_INDEX_BASE[layer.isBaseLayer ? 'BaseLayer' : 'Overlay'] - + zIdx * 5 ); - }, - - /** - * Method: resetLayersZIndex - * Reset each layer's z-index based on layer's array index - */ - resetLayersZIndex: function() { - for (var i=0, len=this.layers.length; i} - * - * Returns: - * {Boolean} True if the layer has been added to the map. - */ - addLayer: function (layer) { - for(var i = 0, len = this.layers.length; i < len; i++) { - if (this.layers[i] == layer) { - return false; - } - } - if (this.events.triggerEvent("preaddlayer", {layer: layer}) === false) { - return false; - } - if(this.allOverlays) { - layer.isBaseLayer = false; - } - - layer.div.className = "olLayerDiv"; - layer.div.style.overflow = ""; - this.setLayerZIndex(layer, this.layers.length); - - if (layer.isFixed) { - this.viewPortDiv.appendChild(layer.div); - } else { - this.layerContainerDiv.appendChild(layer.div); - } - this.layers.push(layer); - layer.setMap(this); - - if (layer.isBaseLayer || (this.allOverlays && !this.baseLayer)) { - if (this.baseLayer == null) { - // set the first baselaye we add as the baselayer - this.setBaseLayer(layer); - } else { - layer.setVisibility(false); - } - } else { - layer.redraw(); - } - - this.events.triggerEvent("addlayer", {layer: layer}); - layer.events.triggerEvent("added", {map: this, layer: layer}); - layer.afterAdd(); - - return true; - }, - - /** - * APIMethod: addLayers - * - * Parameters: - * layers - {Array()} - */ - addLayers: function (layers) { - for (var i=0, len=layers.length; i} - * setNewBaseLayer - {Boolean} Default is true - */ - removeLayer: function(layer, setNewBaseLayer) { - if (this.events.triggerEvent("preremovelayer", {layer: layer}) === false) { - return; - } - if (setNewBaseLayer == null) { - setNewBaseLayer = true; - } - - if (layer.isFixed) { - this.viewPortDiv.removeChild(layer.div); - } else { - this.layerContainerDiv.removeChild(layer.div); - } - OpenLayers.Util.removeItem(this.layers, layer); - layer.removeMap(this); - layer.map = null; - - // if we removed the base layer, need to set a new one - if(this.baseLayer == layer) { - this.baseLayer = null; - if(setNewBaseLayer) { - for(var i=0, len=this.layers.length; i} - * - * Returns: - * {Integer} The current (zero-based) index of the given layer in the map's - * layer stack. Returns -1 if the layer isn't on the map. - */ - getLayerIndex: function (layer) { - return OpenLayers.Util.indexOf(this.layers, layer); - }, - - /** - * APIMethod: setLayerIndex - * Move the given layer to the specified (zero-based) index in the layer - * list, changing its z-index in the map display. Use - * map.getLayerIndex() to find out the current index of a layer. Note - * that this cannot (or at least should not) be effectively used to - * raise base layers above overlays. - * - * Parameters: - * layer - {} - * idx - {int} - */ - setLayerIndex: function (layer, idx) { - var base = this.getLayerIndex(layer); - if (idx < 0) { - idx = 0; - } else if (idx > this.layers.length) { - idx = this.layers.length; - } - if (base != idx) { - this.layers.splice(base, 1); - this.layers.splice(idx, 0, layer); - for (var i=0, len=this.layers.length; i} - * delta - {int} - */ - raiseLayer: function (layer, delta) { - var idx = this.getLayerIndex(layer) + delta; - this.setLayerIndex(layer, idx); - }, - - /** - * APIMethod: setBaseLayer - * Allows user to specify one of the currently-loaded layers as the Map's - * new base layer. - * - * Parameters: - * newBaseLayer - {} - */ - setBaseLayer: function(newBaseLayer) { - - if (newBaseLayer != this.baseLayer) { - - // ensure newBaseLayer is already loaded - if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) { - - // preserve center and scale when changing base layers - var center = this.getCachedCenter(); - var newResolution = OpenLayers.Util.getResolutionFromScale( - this.getScale(), newBaseLayer.units - ); - - // make the old base layer invisible - if (this.baseLayer != null && !this.allOverlays) { - this.baseLayer.setVisibility(false); - } - - // set new baselayer - this.baseLayer = newBaseLayer; - - if(!this.allOverlays || this.baseLayer.visibility) { - this.baseLayer.setVisibility(true); - // Layer may previously have been visible but not in range. - // In this case we need to redraw it to make it visible. - if (this.baseLayer.inRange === false) { - this.baseLayer.redraw(); - } - } - - // recenter the map - if (center != null) { - // new zoom level derived from old scale - var newZoom = this.getZoomForResolution( - newResolution || this.resolution, true - ); - // zoom and force zoom change - this.setCenter(center, newZoom, false, true); - } - - this.events.triggerEvent("changebaselayer", { - layer: this.baseLayer - }); - } - } - }, - - - /********************************************************/ - /* */ - /* Control Functions */ - /* */ - /* The following functions deal with adding and */ - /* removing Controls to and from the Map */ - /* */ - /********************************************************/ - - /** - * APIMethod: addControl - * Add the passed over control to the map. Optionally - * position the control at the given pixel. - * - * Parameters: - * control - {} - * px - {} - */ - addControl: function (control, px) { - this.controls.push(control); - this.addControlToMap(control, px); - }, - - /** - * APIMethod: addControls - * Add all of the passed over controls to the map. - * You can pass over an optional second array - * with pixel-objects to position the controls. - * The indices of the two arrays should match and - * you can add null as pixel for those controls - * you want to be autopositioned. - * - * Parameters: - * controls - {Array()} - * pixels - {Array()} - */ - addControls: function (controls, pixels) { - var pxs = (arguments.length === 1) ? [] : pixels; - for (var i=0, len=controls.length; i} - * px - {} - */ - addControlToMap: function (control, px) { - // If a control doesn't have a div at this point, it belongs in the - // viewport. - control.outsideViewport = (control.div != null); - - // If the map has a displayProjection, and the control doesn't, set - // the display projection. - if (this.displayProjection && !control.displayProjection) { - control.displayProjection = this.displayProjection; - } - - control.setMap(this); - var div = control.draw(px); - if (div) { - if(!control.outsideViewport) { - div.style.zIndex = this.Z_INDEX_BASE['Control'] + - this.controls.length; - this.viewPortDiv.appendChild( div ); - } - } - if(control.autoActivate) { - control.activate(); - } - }, - - /** - * APIMethod: getControl - * - * Parameters: - * id - {String} ID of the control to return. - * - * Returns: - * {} The control from the map's list of controls - * which has a matching 'id'. If none found, - * returns null. - */ - getControl: function (id) { - var returnControl = null; - for(var i=0, len=this.controls.length; i} The control to remove. - */ - removeControl: function (control) { - //make sure control is non-null and actually part of our map - if ( (control) && (control == this.getControl(control.id)) ) { - if (control.div && (control.div.parentNode == this.viewPortDiv)) { - this.viewPortDiv.removeChild(control.div); - } - OpenLayers.Util.removeItem(this.controls, control); - } - }, - - /********************************************************/ - /* */ - /* Popup Functions */ - /* */ - /* The following functions deal with adding and */ - /* removing Popups to and from the Map */ - /* */ - /********************************************************/ - - /** - * APIMethod: addPopup - * - * Parameters: - * popup - {} - * exclusive - {Boolean} If true, closes all other popups first - */ - addPopup: function(popup, exclusive) { - - if (exclusive) { - //remove all other popups from screen - for (var i = this.popups.length - 1; i >= 0; --i) { - this.removePopup(this.popups[i]); - } - } - - popup.map = this; - this.popups.push(popup); - var popupDiv = popup.draw(); - if (popupDiv) { - popupDiv.style.zIndex = this.Z_INDEX_BASE['Popup'] + - this.popups.length; - this.layerContainerDiv.appendChild(popupDiv); - } - }, - - /** - * APIMethod: removePopup - * - * Parameters: - * popup - {} - */ - removePopup: function(popup) { - OpenLayers.Util.removeItem(this.popups, popup); - if (popup.div) { - try { this.layerContainerDiv.removeChild(popup.div); } - catch (e) { } // Popups sometimes apparently get disconnected - // from the layerContainerDiv, and cause complaints. - } - popup.map = null; - }, - - /********************************************************/ - /* */ - /* Container Div Functions */ - /* */ - /* The following functions deal with the access to */ - /* and maintenance of the size of the container div */ - /* */ - /********************************************************/ - - /** - * APIMethod: getSize - * - * Returns: - * {} An object that represents the - * size, in pixels, of the div into which OpenLayers - * has been loaded. - * Note - A clone() of this locally cached variable is - * returned, so as not to allow users to modify it. - */ - getSize: function () { - var size = null; - if (this.size != null) { - size = this.size.clone(); - } - return size; - }, - - /** - * APIMethod: updateSize - * This function should be called by any external code which dynamically - * changes the size of the map div (because mozilla wont let us catch - * the "onresize" for an element) - */ - updateSize: function() { - // the div might have moved on the page, also - var newSize = this.getCurrentSize(); - if (newSize && !isNaN(newSize.h) && !isNaN(newSize.w)) { - this.events.clearMouseCache(); - var oldSize = this.getSize(); - if (oldSize == null) { - this.size = oldSize = newSize; - } - if (!newSize.equals(oldSize)) { - - // store the new size - this.size = newSize; - - //notify layers of mapresize - for(var i=0, len=this.layers.length; i} A new object with the dimensions - * of the map div - */ - getCurrentSize: function() { - - var size = new OpenLayers.Size(this.div.clientWidth, - this.div.clientHeight); - - if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) { - size.w = this.div.offsetWidth; - size.h = this.div.offsetHeight; - } - if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) { - size.w = parseInt(this.div.style.width); - size.h = parseInt(this.div.style.height); - } - return size; - }, - - /** - * Method: calculateBounds - * - * Parameters: - * center - {} Default is this.getCenter() - * resolution - {float} Default is this.getResolution() - * - * Returns: - * {} A bounds based on resolution, center, and - * current mapsize. - */ - calculateBounds: function(center, resolution) { - - var extent = null; - - if (center == null) { - center = this.getCachedCenter(); - } - if (resolution == null) { - resolution = this.getResolution(); - } - - if ((center != null) && (resolution != null)) { - var halfWDeg = (this.size.w * resolution) / 2; - var halfHDeg = (this.size.h * resolution) / 2; - - extent = new OpenLayers.Bounds(center.lon - halfWDeg, - center.lat - halfHDeg, - center.lon + halfWDeg, - center.lat + halfHDeg); - } - - return extent; - }, - - - /********************************************************/ - /* */ - /* Zoom, Center, Pan Functions */ - /* */ - /* The following functions handle the validation, */ - /* getting and setting of the Zoom Level and Center */ - /* as well as the panning of the Map */ - /* */ - /********************************************************/ - /** - * APIMethod: getCenter - * - * Returns: - * {} - */ - getCenter: function () { - var center = null; - var cachedCenter = this.getCachedCenter(); - if (cachedCenter) { - center = cachedCenter.clone(); - } - return center; - }, - - /** - * Method: getCachedCenter - * - * Returns: - * {} - */ - getCachedCenter: function() { - if (!this.center && this.size) { - this.center = this.getLonLatFromViewPortPx({ - x: this.size.w / 2, - y: this.size.h / 2 - }); - } - return this.center; - }, - - /** - * APIMethod: getZoom - * - * Returns: - * {Integer} - */ - getZoom: function () { - return this.zoom; - }, - - /** - * APIMethod: pan - * Allows user to pan by a value of screen pixels - * - * Parameters: - * dx - {Integer} - * dy - {Integer} - * options - {Object} Options to configure panning: - * - *animate* {Boolean} Use panTo instead of setCenter. Default is true. - * - *dragging* {Boolean} Call setCenter with dragging true. Default is - * false. - */ - pan: function(dx, dy, options) { - options = OpenLayers.Util.applyDefaults(options, { - animate: true, - dragging: false - }); - if (options.dragging) { - if (dx != 0 || dy != 0) { - this.moveByPx(dx, dy); - } - } else { - // getCenter - var centerPx = this.getViewPortPxFromLonLat(this.getCachedCenter()); - - // adjust - var newCenterPx = centerPx.add(dx, dy); - - if (this.dragging || !newCenterPx.equals(centerPx)) { - var newCenterLonLat = this.getLonLatFromViewPortPx(newCenterPx); - if (options.animate) { - this.panTo(newCenterLonLat); - } else { - this.moveTo(newCenterLonLat); - if(this.dragging) { - this.dragging = false; - this.events.triggerEvent("moveend"); - } - } - } - } - - }, - - /** - * APIMethod: panTo - * Allows user to pan to a new lonlat - * If the new lonlat is in the current extent the map will slide smoothly - * - * Parameters: - * lonlat - {} - */ - panTo: function(lonlat) { - if (this.panTween && this.getExtent().scale(this.panRatio).containsLonLat(lonlat)) { - var center = this.getCachedCenter(); - - // center will not change, don't do nothing - if (lonlat.equals(center)) { - return; - } - - var from = this.getPixelFromLonLat(center); - var to = this.getPixelFromLonLat(lonlat); - var vector = { x: to.x - from.x, y: to.y - from.y }; - var last = { x: 0, y: 0 }; - - this.panTween.start( { x: 0, y: 0 }, vector, this.panDuration, { - callbacks: { - eachStep: OpenLayers.Function.bind(function(px) { - var x = px.x - last.x, - y = px.y - last.y; - this.moveByPx(x, y); - last.x = Math.round(px.x); - last.y = Math.round(px.y); - }, this), - done: OpenLayers.Function.bind(function(px) { - this.moveTo(lonlat); - this.dragging = false; - this.events.triggerEvent("moveend"); - }, this) - } - }); - } else { - this.setCenter(lonlat); - } - }, - - /** - * APIMethod: setCenter - * Set the map center (and optionally, the zoom level). - * - * Parameters: - * lonlat - {|Array} The new center location. - * If provided as array, the first value is the x coordinate, - * and the 2nd value is the y coordinate. - * zoom - {Integer} Optional zoom level. - * dragging - {Boolean} Specifies whether or not to trigger - * movestart/end events - * forceZoomChange - {Boolean} Specifies whether or not to trigger zoom - * change events (needed on baseLayer change) - * - * TBD: reconsider forceZoomChange in 3.0 - */ - setCenter: function(lonlat, zoom, dragging, forceZoomChange) { - if (this.panTween) { - this.panTween.stop(); - } - if (this.zoomTween) { - this.zoomTween.stop(); - } - this.moveTo(lonlat, zoom, { - 'dragging': dragging, - 'forceZoomChange': forceZoomChange - }); - }, - - /** - * Method: moveByPx - * Drag the map by pixels. - * - * Parameters: - * dx - {Number} - * dy - {Number} - */ - moveByPx: function(dx, dy) { - var hw = this.size.w / 2; - var hh = this.size.h / 2; - var x = hw + dx; - var y = hh + dy; - var wrapDateLine = this.baseLayer.wrapDateLine; - var xRestriction = 0; - var yRestriction = 0; - if (this.restrictedExtent) { - xRestriction = hw; - yRestriction = hh; - // wrapping the date line makes no sense for restricted extents - wrapDateLine = false; - } - dx = wrapDateLine || - x <= this.maxPx.x - xRestriction && - x >= this.minPx.x + xRestriction ? Math.round(dx) : 0; - dy = y <= this.maxPx.y - yRestriction && - y >= this.minPx.y + yRestriction ? Math.round(dy) : 0; - if (dx || dy) { - if (!this.dragging) { - this.dragging = true; - this.events.triggerEvent("movestart"); - } - this.center = null; - if (dx) { - this.layerContainerOriginPx.x -= dx; - this.minPx.x -= dx; - this.maxPx.x -= dx; - } - if (dy) { - this.layerContainerOriginPx.y -= dy; - this.minPx.y -= dy; - this.maxPx.y -= dy; - } - this.applyTransform(); - var layer, i, len; - for (i=0, len=this.layers.length; i's maxExtent. - */ - adjustZoom: function(zoom) { - if (this.baseLayer && this.baseLayer.wrapDateLine) { - var resolution, resolutions = this.baseLayer.resolutions, - maxResolution = this.getMaxExtent().getWidth() / this.size.w; - if (this.getResolutionForZoom(zoom) > maxResolution) { - if (this.fractionalZoom) { - zoom = this.getZoomForResolution(maxResolution); - } else { - for (var i=zoom|0, ii=resolutions.length; i set to true, this will be the - * first zoom level that shows no more than one world width in the current - * map viewport. Components that rely on this value (e.g. zoom sliders) - * should also listen to the map's "updatesize" event and call this method - * in the "updatesize" listener. - * - * Returns: - * {Number} Minimum zoom level that shows a map not wider than its - * 's maxExtent. This is an Integer value, unless the map is - * configured with set to true. - */ - getMinZoom: function() { - return this.adjustZoom(0); - }, - - /** - * Method: moveTo - * - * Parameters: - * lonlat - {} - * zoom - {Integer} - * options - {Object} - */ - moveTo: function(lonlat, zoom, options) { - if (lonlat != null && !(lonlat instanceof OpenLayers.LonLat)) { - lonlat = new OpenLayers.LonLat(lonlat); - } - if (!options) { - options = {}; - } - if (zoom != null) { - zoom = parseFloat(zoom); - if (!this.fractionalZoom) { - zoom = Math.round(zoom); - } - } - var requestedZoom = zoom; - zoom = this.adjustZoom(zoom); - if (zoom !== requestedZoom) { - // zoom was adjusted, so keep old lonlat to avoid panning - lonlat = this.getCenter(); - } - // dragging is false by default - var dragging = options.dragging || this.dragging; - // forceZoomChange is false by default - var forceZoomChange = options.forceZoomChange; - - if (!this.getCachedCenter() && !this.isValidLonLat(lonlat)) { - lonlat = this.maxExtent.getCenterLonLat(); - this.center = lonlat.clone(); - } - - if(this.restrictedExtent != null) { - // In 3.0, decide if we want to change interpretation of maxExtent. - if(lonlat == null) { - lonlat = this.center; - } - if(zoom == null) { - zoom = this.getZoom(); - } - var resolution = this.getResolutionForZoom(zoom); - var extent = this.calculateBounds(lonlat, resolution); - if(!this.restrictedExtent.containsBounds(extent)) { - var maxCenter = this.restrictedExtent.getCenterLonLat(); - if(extent.getWidth() > this.restrictedExtent.getWidth()) { - lonlat = new OpenLayers.LonLat(maxCenter.lon, lonlat.lat); - } else if(extent.left < this.restrictedExtent.left) { - lonlat = lonlat.add(this.restrictedExtent.left - - extent.left, 0); - } else if(extent.right > this.restrictedExtent.right) { - lonlat = lonlat.add(this.restrictedExtent.right - - extent.right, 0); - } - if(extent.getHeight() > this.restrictedExtent.getHeight()) { - lonlat = new OpenLayers.LonLat(lonlat.lon, maxCenter.lat); - } else if(extent.bottom < this.restrictedExtent.bottom) { - lonlat = lonlat.add(0, this.restrictedExtent.bottom - - extent.bottom); - } - else if(extent.top > this.restrictedExtent.top) { - lonlat = lonlat.add(0, this.restrictedExtent.top - - extent.top); - } - } - } - - var zoomChanged = forceZoomChange || ( - (this.isValidZoomLevel(zoom)) && - (zoom != this.getZoom()) ); - - var centerChanged = (this.isValidLonLat(lonlat)) && - (!lonlat.equals(this.center)); - - // if neither center nor zoom will change, no need to do anything - if (zoomChanged || centerChanged || dragging) { - dragging || this.events.triggerEvent("movestart", { - zoomChanged: zoomChanged - }); - - if (centerChanged) { - if (!zoomChanged && this.center) { - // if zoom hasnt changed, just slide layerContainer - // (must be done before setting this.center to new value) - this.centerLayerContainer(lonlat); - } - this.center = lonlat.clone(); - } - - var res = zoomChanged ? - this.getResolutionForZoom(zoom) : this.getResolution(); - // (re)set the layerContainerDiv's location - if (zoomChanged || this.layerContainerOrigin == null) { - this.layerContainerOrigin = this.getCachedCenter(); - this.layerContainerOriginPx.x = 0; - this.layerContainerOriginPx.y = 0; - this.applyTransform(); - var maxExtent = this.getMaxExtent({restricted: true}); - var maxExtentCenter = maxExtent.getCenterLonLat(); - var lonDelta = this.center.lon - maxExtentCenter.lon; - var latDelta = maxExtentCenter.lat - this.center.lat; - var extentWidth = Math.round(maxExtent.getWidth() / res); - var extentHeight = Math.round(maxExtent.getHeight() / res); - this.minPx = { - x: (this.size.w - extentWidth) / 2 - lonDelta / res, - y: (this.size.h - extentHeight) / 2 - latDelta / res - }; - this.maxPx = { - x: this.minPx.x + Math.round(maxExtent.getWidth() / res), - y: this.minPx.y + Math.round(maxExtent.getHeight() / res) - }; - } - - if (zoomChanged) { - this.zoom = zoom; - this.resolution = res; - } - - var bounds = this.getExtent(); - - //send the move call to the baselayer and all the overlays - - if(this.baseLayer.visibility) { - this.baseLayer.moveTo(bounds, zoomChanged, options.dragging); - options.dragging || this.baseLayer.events.triggerEvent( - "moveend", {zoomChanged: zoomChanged} - ); - } - - bounds = this.baseLayer.getExtent(); - - for (var i=this.layers.length-1; i>=0; --i) { - var layer = this.layers[i]; - if (layer !== this.baseLayer && !layer.isBaseLayer) { - var inRange = layer.calculateInRange(); - if (layer.inRange != inRange) { - // the inRange property has changed. If the layer is - // no longer in range, we turn it off right away. If - // the layer is no longer out of range, the moveTo - // call below will turn on the layer. - layer.inRange = inRange; - if (!inRange) { - layer.display(false); - } - this.events.triggerEvent("changelayer", { - layer: layer, property: "visibility" - }); - } - if (inRange && layer.visibility) { - layer.moveTo(bounds, zoomChanged, options.dragging); - options.dragging || layer.events.triggerEvent( - "moveend", {zoomChanged: zoomChanged} - ); - } - } - } - - this.events.triggerEvent("move"); - dragging || this.events.triggerEvent("moveend"); - - if (zoomChanged) { - //redraw popups - for (var i=0, len=this.popups.length; i} - */ - centerLayerContainer: function (lonlat) { - var originPx = this.getViewPortPxFromLonLat(this.layerContainerOrigin); - var newPx = this.getViewPortPxFromLonLat(lonlat); - - if ((originPx != null) && (newPx != null)) { - var oldLeft = this.layerContainerOriginPx.x; - var oldTop = this.layerContainerOriginPx.y; - var newLeft = Math.round(originPx.x - newPx.x); - var newTop = Math.round(originPx.y - newPx.y); - this.applyTransform( - (this.layerContainerOriginPx.x = newLeft), - (this.layerContainerOriginPx.y = newTop)); - var dx = oldLeft - newLeft; - var dy = oldTop - newTop; - this.minPx.x -= dx; - this.maxPx.x -= dx; - this.minPx.y -= dy; - this.maxPx.y -= dy; - } - }, - - /** - * Method: isValidZoomLevel - * - * Parameters: - * zoomLevel - {Integer} - * - * Returns: - * {Boolean} Whether or not the zoom level passed in is non-null and - * within the min/max range of zoom levels. - */ - isValidZoomLevel: function(zoomLevel) { - return ( (zoomLevel != null) && - (zoomLevel >= 0) && - (zoomLevel < this.getNumZoomLevels()) ); - }, - - /** - * Method: isValidLonLat - * - * Parameters: - * lonlat - {} - * - * Returns: - * {Boolean} Whether or not the lonlat passed in is non-null and within - * the maxExtent bounds - */ - isValidLonLat: function(lonlat) { - var valid = false; - if (lonlat != null) { - var maxExtent = this.getMaxExtent(); - var worldBounds = this.baseLayer.wrapDateLine && maxExtent; - valid = maxExtent.containsLonLat(lonlat, {worldBounds: worldBounds}); - } - return valid; - }, - - /********************************************************/ - /* */ - /* Layer Options */ - /* */ - /* Accessor functions to Layer Options parameters */ - /* */ - /********************************************************/ - - /** - * APIMethod: getProjection - * This method returns a string representing the projection. In - * the case of projection support, this will be the srsCode which - * is loaded -- otherwise it will simply be the string value that - * was passed to the projection at startup. - * - * FIXME: In 3.0, we will remove getProjectionObject, and instead - * return a Projection object from this function. - * - * Returns: - * {String} The Projection string from the base layer or null. - */ - getProjection: function() { - var projection = this.getProjectionObject(); - return projection ? projection.getCode() : null; - }, - - /** - * APIMethod: getProjectionObject - * Returns the projection obect from the baselayer. - * - * Returns: - * {} The Projection of the base layer. - */ - getProjectionObject: function() { - var projection = null; - if (this.baseLayer != null) { - projection = this.baseLayer.projection; - } - return projection; - }, - - /** - * APIMethod: getMaxResolution - * - * Returns: - * {String} The Map's Maximum Resolution - */ - getMaxResolution: function() { - var maxResolution = null; - if (this.baseLayer != null) { - maxResolution = this.baseLayer.maxResolution; - } - return maxResolution; - }, - - /** - * APIMethod: getMaxExtent - * - * Parameters: - * options - {Object} - * - * Allowed Options: - * restricted - {Boolean} If true, returns restricted extent (if it is - * available.) - * - * Returns: - * {} The maxExtent property as set on the current - * baselayer, unless the 'restricted' option is set, in which case - * the 'restrictedExtent' option from the map is returned (if it - * is set). - */ - getMaxExtent: function (options) { - var maxExtent = null; - if(options && options.restricted && this.restrictedExtent){ - maxExtent = this.restrictedExtent; - } else if (this.baseLayer != null) { - maxExtent = this.baseLayer.maxExtent; - } - return maxExtent; - }, - - /** - * APIMethod: getNumZoomLevels - * - * Returns: - * {Integer} The total number of zoom levels that can be displayed by the - * current baseLayer. - */ - getNumZoomLevels: function() { - var numZoomLevels = null; - if (this.baseLayer != null) { - numZoomLevels = this.baseLayer.numZoomLevels; - } - return numZoomLevels; - }, - - /********************************************************/ - /* */ - /* Baselayer Functions */ - /* */ - /* The following functions, all publicly exposed */ - /* in the API?, are all merely wrappers to the */ - /* the same calls on whatever layer is set as */ - /* the current base layer */ - /* */ - /********************************************************/ - - /** - * APIMethod: getExtent - * - * Returns: - * {} A Bounds object which represents the lon/lat - * bounds of the current viewPort. - * If no baselayer is set, returns null. - */ - getExtent: function () { - var extent = null; - if (this.baseLayer != null) { - extent = this.baseLayer.getExtent(); - } - return extent; - }, - - /** - * APIMethod: getResolution - * - * Returns: - * {Float} The current resolution of the map. - * If no baselayer is set, returns null. - */ - getResolution: function () { - var resolution = null; - if (this.baseLayer != null) { - resolution = this.baseLayer.getResolution(); - } else if(this.allOverlays === true && this.layers.length > 0) { - // while adding the 1st layer to the map in allOverlays mode, - // this.baseLayer is not set yet when we need the resolution - // for calculateInRange. - resolution = this.layers[0].getResolution(); - } - return resolution; - }, - - /** - * APIMethod: getUnits - * - * Returns: - * {Float} The current units of the map. - * If no baselayer is set, returns null. - */ - getUnits: function () { - var units = null; - if (this.baseLayer != null) { - units = this.baseLayer.units; - } - return units; - }, - - /** - * APIMethod: getScale - * - * Returns: - * {Float} The current scale denominator of the map. - * If no baselayer is set, returns null. - */ - getScale: function () { - var scale = null; - if (this.baseLayer != null) { - var res = this.getResolution(); - var units = this.baseLayer.units; - scale = OpenLayers.Util.getScaleFromResolution(res, units); - } - return scale; - }, - - - /** - * APIMethod: getZoomForExtent - * - * Parameters: - * bounds - {} - * closest - {Boolean} Find the zoom level that most closely fits the - * specified bounds. Note that this may result in a zoom that does - * not exactly contain the entire extent. - * Default is false. - * - * Returns: - * {Integer} A suitable zoom level for the specified bounds. - * If no baselayer is set, returns null. - */ - getZoomForExtent: function (bounds, closest) { - var zoom = null; - if (this.baseLayer != null) { - zoom = this.baseLayer.getZoomForExtent(bounds, closest); - } - return zoom; - }, - - /** - * APIMethod: getResolutionForZoom - * - * Parameters: - * zoom - {Float} - * - * Returns: - * {Float} A suitable resolution for the specified zoom. If no baselayer - * is set, returns null. - */ - getResolutionForZoom: function(zoom) { - var resolution = null; - if(this.baseLayer) { - resolution = this.baseLayer.getResolutionForZoom(zoom); - } - return resolution; - }, - - /** - * APIMethod: getZoomForResolution - * - * Parameters: - * resolution - {Float} - * closest - {Boolean} Find the zoom level that corresponds to the absolute - * closest resolution, which may result in a zoom whose corresponding - * resolution is actually smaller than we would have desired (if this - * is being called from a getZoomForExtent() call, then this means that - * the returned zoom index might not actually contain the entire - * extent specified... but it'll be close). - * Default is false. - * - * Returns: - * {Integer} A suitable zoom level for the specified resolution. - * If no baselayer is set, returns null. - */ - getZoomForResolution: function(resolution, closest) { - var zoom = null; - if (this.baseLayer != null) { - zoom = this.baseLayer.getZoomForResolution(resolution, closest); - } - return zoom; - }, - - /********************************************************/ - /* */ - /* Zooming Functions */ - /* */ - /* The following functions, all publicly exposed */ - /* in the API, are all merely wrappers to the */ - /* the setCenter() function */ - /* */ - /********************************************************/ - - /** - * APIMethod: zoomTo - * Zoom to a specific zoom level. Zooming will be animated unless the map - * is configured with {zoomMethod: null}. To zoom without animation, use - * without a lonlat argument. - * - * Parameters: - * zoom - {Integer} - */ - zoomTo: function(zoom, xy) { - // non-API arguments: - // xy - {} optional zoom origin - - var map = this; - if (map.isValidZoomLevel(zoom)) { - if (map.baseLayer.wrapDateLine) { - zoom = map.adjustZoom(zoom); - } - if (map.zoomTween) { - var currentRes = map.getResolution(), - targetRes = map.getResolutionForZoom(zoom), - start = {scale: 1}, - end = {scale: currentRes / targetRes}; - if (map.zoomTween.playing && map.zoomTween.duration < 3 * map.zoomDuration) { - // update the end scale, and reuse the running zoomTween - map.zoomTween.finish = { - scale: map.zoomTween.finish.scale * end.scale - }; - } else { - if (!xy) { - var size = map.getSize(); - xy = {x: size.w / 2, y: size.h / 2}; - } - map.zoomTween.start(start, end, map.zoomDuration, { - minFrameRate: 50, // don't spend much time zooming - callbacks: { - eachStep: function(data) { - var containerOrigin = map.layerContainerOriginPx, - scale = data.scale, - dx = ((scale - 1) * (containerOrigin.x - xy.x)) | 0, - dy = ((scale - 1) * (containerOrigin.y - xy.y)) | 0; - map.applyTransform(containerOrigin.x + dx, containerOrigin.y + dy, scale); - }, - done: function(data) { - map.applyTransform(); - var resolution = map.getResolution() / data.scale, - zoom = map.getZoomForResolution(resolution, true) - map.moveTo(map.getZoomTargetCenter(xy, resolution), zoom, true); - } - } - }); - } - } else { - var center = xy ? - map.getZoomTargetCenter(xy, map.getResolutionForZoom(zoom)) : - null; - map.setCenter(center, zoom); - } - } - }, - - /** - * APIMethod: zoomIn - * - */ - zoomIn: function() { - this.zoomTo(this.getZoom() + 1); - }, - - /** - * APIMethod: zoomOut - * - */ - zoomOut: function() { - this.zoomTo(this.getZoom() - 1); - }, - - /** - * APIMethod: zoomToExtent - * Zoom to the passed in bounds, recenter - * - * Parameters: - * bounds - {|Array} If provided as an array, the array - * should consist of four values (left, bottom, right, top). - * closest - {Boolean} Find the zoom level that most closely fits the - * specified bounds. Note that this may result in a zoom that does - * not exactly contain the entire extent. - * Default is false. - * - */ - zoomToExtent: function(bounds, closest) { - if (!(bounds instanceof OpenLayers.Bounds)) { - bounds = new OpenLayers.Bounds(bounds); - } - var center = bounds.getCenterLonLat(); - if (this.baseLayer.wrapDateLine) { - var maxExtent = this.getMaxExtent(); - - //fix straddling bounds (in the case of a bbox that straddles the - // dateline, it's left and right boundaries will appear backwards. - // we fix this by allowing a right value that is greater than the - // max value at the dateline -- this allows us to pass a valid - // bounds to calculate zoom) - // - bounds = bounds.clone(); - while (bounds.right < bounds.left) { - bounds.right += maxExtent.getWidth(); - } - //if the bounds was straddling (see above), then the center point - // we got from it was wrong. So we take our new bounds and ask it - // for the center. - // - center = bounds.getCenterLonLat().wrapDateLine(maxExtent); - } - this.setCenter(center, this.getZoomForExtent(bounds, closest)); - }, - - /** - * APIMethod: zoomToMaxExtent - * Zoom to the full extent and recenter. - * - * Parameters: - * options - {Object} - * - * Allowed Options: - * restricted - {Boolean} True to zoom to restricted extent if it is - * set. Defaults to true. - */ - zoomToMaxExtent: function(options) { - //restricted is true by default - var restricted = (options) ? options.restricted : true; - - var maxExtent = this.getMaxExtent({ - 'restricted': restricted - }); - this.zoomToExtent(maxExtent); - }, - - /** - * APIMethod: zoomToScale - * Zoom to a specified scale - * - * Parameters: - * scale - {float} - * closest - {Boolean} Find the zoom level that most closely fits the - * specified scale. Note that this may result in a zoom that does - * not exactly contain the entire extent. - * Default is false. - * - */ - zoomToScale: function(scale, closest) { - var res = OpenLayers.Util.getResolutionFromScale(scale, - this.baseLayer.units); - - var halfWDeg = (this.size.w * res) / 2; - var halfHDeg = (this.size.h * res) / 2; - var center = this.getCachedCenter(); - - var extent = new OpenLayers.Bounds(center.lon - halfWDeg, - center.lat - halfHDeg, - center.lon + halfWDeg, - center.lat + halfHDeg); - this.zoomToExtent(extent, closest); - }, - - /********************************************************/ - /* */ - /* Translation Functions */ - /* */ - /* The following functions translate between */ - /* LonLat, LayerPx, and ViewPortPx */ - /* */ - /********************************************************/ - - // - // TRANSLATION: LonLat <-> ViewPortPx - // - - /** - * Method: getLonLatFromViewPortPx - * - * Parameters: - * viewPortPx - {|Object} An OpenLayers.Pixel or - * an object with a 'x' - * and 'y' properties. - * - * Returns: - * {} An OpenLayers.LonLat which is the passed-in view - * port , translated into lon/lat - * by the current base layer. - */ - getLonLatFromViewPortPx: function (viewPortPx) { - var lonlat = null; - if (this.baseLayer != null) { - lonlat = this.baseLayer.getLonLatFromViewPortPx(viewPortPx); - } - return lonlat; - }, - - /** - * APIMethod: getViewPortPxFromLonLat - * - * Parameters: - * lonlat - {} - * - * Returns: - * {} An OpenLayers.Pixel which is the passed-in - * , translated into view port - * pixels by the current base layer. - */ - getViewPortPxFromLonLat: function (lonlat) { - var px = null; - if (this.baseLayer != null) { - px = this.baseLayer.getViewPortPxFromLonLat(lonlat); - } - return px; - }, - - /** - * Method: getZoomTargetCenter - * - * Parameters: - * xy - {} The zoom origin pixel location on the screen - * resolution - {Float} The resolution we want to get the center for - * - * Returns: - * {} The location of the map center after the - * transformation described by the origin xy and the target resolution. - */ - getZoomTargetCenter: function (xy, resolution) { - var lonlat = null, - size = this.getSize(), - deltaX = size.w/2 - xy.x, - deltaY = xy.y - size.h/2, - zoomPoint = this.getLonLatFromPixel(xy); - if (zoomPoint) { - lonlat = new OpenLayers.LonLat( - zoomPoint.lon + deltaX * resolution, - zoomPoint.lat + deltaY * resolution - ); - } - return lonlat; - }, - - // - // CONVENIENCE TRANSLATION FUNCTIONS FOR API - // - - /** - * APIMethod: getLonLatFromPixel - * - * Parameters: - * px - {|Object} An OpenLayers.Pixel or an object with - * a 'x' and 'y' properties. - * - * Returns: - * {} An OpenLayers.LonLat corresponding to the given - * OpenLayers.Pixel, translated into lon/lat by the - * current base layer - */ - getLonLatFromPixel: function (px) { - return this.getLonLatFromViewPortPx(px); - }, - - /** - * APIMethod: getPixelFromLonLat - * Returns a pixel location given a map location. The map location is - * translated to an integer pixel location (in viewport pixel - * coordinates) by the current base layer. - * - * Parameters: - * lonlat - {} A map location. - * - * Returns: - * {} An OpenLayers.Pixel corresponding to the - * translated into view port pixels by the current - * base layer. - */ - getPixelFromLonLat: function (lonlat) { - var px = this.getViewPortPxFromLonLat(lonlat); - px.x = Math.round(px.x); - px.y = Math.round(px.y); - return px; - }, - - /** - * Method: getGeodesicPixelSize - * - * Parameters: - * px - {} The pixel to get the geodesic length for. If - * not provided, the center pixel of the map viewport will be used. - * - * Returns: - * {} The geodesic size of the pixel in kilometers. - */ - getGeodesicPixelSize: function(px) { - var lonlat = px ? this.getLonLatFromPixel(px) : ( - this.getCachedCenter() || new OpenLayers.LonLat(0, 0)); - var res = this.getResolution(); - var left = lonlat.add(-res / 2, 0); - var right = lonlat.add(res / 2, 0); - var bottom = lonlat.add(0, -res / 2); - var top = lonlat.add(0, res / 2); - var dest = new OpenLayers.Projection("EPSG:4326"); - var source = this.getProjectionObject() || dest; - if(!source.equals(dest)) { - left.transform(source, dest); - right.transform(source, dest); - bottom.transform(source, dest); - top.transform(source, dest); - } - - return new OpenLayers.Size( - OpenLayers.Util.distVincenty(left, right), - OpenLayers.Util.distVincenty(bottom, top) - ); - }, - - - - // - // TRANSLATION: ViewPortPx <-> LayerPx - // - - /** - * APIMethod: getViewPortPxFromLayerPx - * - * Parameters: - * layerPx - {} - * - * Returns: - * {} Layer Pixel translated into ViewPort Pixel - * coordinates - */ - getViewPortPxFromLayerPx:function(layerPx) { - var viewPortPx = null; - if (layerPx != null) { - var dX = this.layerContainerOriginPx.x; - var dY = this.layerContainerOriginPx.y; - viewPortPx = layerPx.add(dX, dY); - } - return viewPortPx; - }, - - /** - * APIMethod: getLayerPxFromViewPortPx - * - * Parameters: - * viewPortPx - {} - * - * Returns: - * {} ViewPort Pixel translated into Layer Pixel - * coordinates - */ - getLayerPxFromViewPortPx:function(viewPortPx) { - var layerPx = null; - if (viewPortPx != null) { - var dX = -this.layerContainerOriginPx.x; - var dY = -this.layerContainerOriginPx.y; - layerPx = viewPortPx.add(dX, dY); - if (isNaN(layerPx.x) || isNaN(layerPx.y)) { - layerPx = null; - } - } - return layerPx; - }, - - // - // TRANSLATION: LonLat <-> LayerPx - // - - /** - * Method: getLonLatFromLayerPx - * - * Parameters: - * px - {} - * - * Returns: - * {} - */ - getLonLatFromLayerPx: function (px) { - //adjust for displacement of layerContainerDiv - px = this.getViewPortPxFromLayerPx(px); - return this.getLonLatFromViewPortPx(px); - }, - - /** - * APIMethod: getLayerPxFromLonLat - * - * Parameters: - * lonlat - {} lonlat - * - * Returns: - * {} An OpenLayers.Pixel which is the passed-in - * , translated into layer pixels - * by the current base layer - */ - getLayerPxFromLonLat: function (lonlat) { - //adjust for displacement of layerContainerDiv - var px = this.getPixelFromLonLat(lonlat); - return this.getLayerPxFromViewPortPx(px); - }, - - /** - * Method: applyTransform - * Applies the given transform to the . This method has - * a 2-stage fallback from translate3d/scale3d via translate/scale to plain - * style.left/style.top, in which case no scaling is supported. - * - * Parameters: - * x - {Number} x parameter for the translation. Defaults to the x value of - * the map's - * y - {Number} y parameter for the translation. Defaults to the y value of - * the map's - * scale - {Number} scale. Defaults to 1 if not provided. - */ - applyTransform: function(x, y, scale) { - scale = scale || 1; - var origin = this.layerContainerOriginPx, - needTransform = scale !== 1; - x = x || origin.x; - y = y || origin.y; - - var style = this.layerContainerDiv.style, - transform = this.applyTransform.transform, - template = this.applyTransform.template; - - if (transform === undefined) { - transform = OpenLayers.Util.vendorPrefix.style('transform'); - this.applyTransform.transform = transform; - if (transform) { - // Try translate3d, but only if the viewPortDiv has a transform - // defined in a stylesheet - var computedStyle = OpenLayers.Element.getStyle(this.viewPortDiv, - OpenLayers.Util.vendorPrefix.css('transform')); - if (!computedStyle || computedStyle !== 'none') { - template = ['translate3d(', ',0) ', 'scale3d(', ',1)']; - style[transform] = [template[0], '0,0', template[1]].join(''); - } - // If no transform is defined in the stylesheet or translate3d - // does not stick, use translate and scale - if (!template || !~style[transform].indexOf(template[0])) { - template = ['translate(', ') ', 'scale(', ')']; - } - this.applyTransform.template = template; - } - } - - // If we do 3d transforms, we always want to use them. If we do 2d - // transforms, we only use them when we need to. - if (transform !== null && (template[0] === 'translate3d(' || needTransform === true)) { - // Our 2d transforms are combined with style.left and style.top, so - // adjust x and y values and set the origin as left and top - if (needTransform === true && template[0] === 'translate(') { - x -= origin.x; - y -= origin.y; - style.left = origin.x + 'px'; - style.top = origin.y + 'px'; - } - style[transform] = [ - template[0], x, 'px,', y, 'px', template[1], - template[2], scale, ',', scale, template[3] - ].join(''); - } else { - style.left = x + 'px'; - style.top = y + 'px'; - // We previously might have had needTransform, so remove transform - if (transform !== null) { - style[transform] = ''; - } - } - }, - - CLASS_NAME: "OpenLayers.Map" -}); - -/** - * Constant: TILE_WIDTH - * {Integer} 256 Default tile width (unless otherwise specified) - */ -OpenLayers.Map.TILE_WIDTH = 256; -/** - * Constant: TILE_HEIGHT - * {Integer} 256 Default tile height (unless otherwise specified) - */ -OpenLayers.Map.TILE_HEIGHT = 256; -/* ====================================================================== - OpenLayers/Layer.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/Map.js - * @requires OpenLayers/Projection.js - */ - -/** - * Class: OpenLayers.Layer - */ -OpenLayers.Layer = OpenLayers.Class({ - - /** - * APIProperty: id - * {String} - */ - id: null, - - /** - * APIProperty: name - * {String} - */ - name: null, - - /** - * APIProperty: div - * {DOMElement} - */ - div: null, - - /** - * APIProperty: opacity - * {Float} The layer's opacity. Float number between 0.0 and 1.0. Default - * is 1. - */ - opacity: 1, - - /** - * APIProperty: alwaysInRange - * {Boolean} If a layer's display should not be scale-based, this should - * be set to true. This will cause the layer, as an overlay, to always - * be 'active', by always returning true from the calculateInRange() - * function. - * - * If not explicitly specified for a layer, its value will be - * determined on startup in initResolutions() based on whether or not - * any scale-specific properties have been set as options on the - * layer. If no scale-specific options have been set on the layer, we - * assume that it should always be in range. - * - * See #987 for more info. - */ - alwaysInRange: null, - - /** - * Constant: RESOLUTION_PROPERTIES - * {Array} The properties that are used for calculating resolutions - * information. - */ - RESOLUTION_PROPERTIES: [ - 'scales', 'resolutions', - 'maxScale', 'minScale', - 'maxResolution', 'minResolution', - 'numZoomLevels', 'maxZoomLevel' - ], - - /** - * APIProperty: events - * {} - * - * Register a listener for a particular event with the following syntax: - * (code) - * layer.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 layer.events.object. - * element - {DOMElement} A reference to layer.events.element. - * - * Supported map event types: - * loadstart - Triggered when layer loading starts. When using a Vector - * layer with a Fixed or BBOX strategy, the event object includes - * a *filter* property holding the OpenLayers.Filter used when - * calling read on the protocol. - * loadend - Triggered when layer loading ends. When using a Vector layer - * with a Fixed or BBOX strategy, the event object includes a - * *response* property holding an OpenLayers.Protocol.Response object. - * visibilitychanged - Triggered when the layer's visibility property is - * changed, e.g. by turning the layer on or off in the layer switcher. - * Note that the actual visibility of the layer can also change if it - * gets out of range (see ). If you also want to catch - * these cases, register for the map's 'changelayer' event instead. - * move - Triggered when layer moves (triggered with every mousemove - * during a drag). - * moveend - Triggered when layer is done moving, object passed as - * argument has a zoomChanged boolean property which tells that the - * zoom has changed. - * added - Triggered after the layer is added to a map. Listeners will - * receive an object with a *map* property referencing the map and a - * *layer* property referencing the layer. - * removed - Triggered after the layer is removed from the map. Listeners - * will receive an object with a *map* property referencing the map and - * a *layer* property referencing the layer. - */ - events: null, - - /** - * APIProperty: map - * {} This variable is set when the layer is added to - * the map, via the accessor function setMap(). - */ - map: null, - - /** - * APIProperty: isBaseLayer - * {Boolean} Whether or not the layer is a base layer. This should be set - * individually by all subclasses. Default is false - */ - isBaseLayer: false, - - /** - * Property: alpha - * {Boolean} The layer's images have an alpha channel. Default is false. - */ - alpha: false, - - /** - * APIProperty: displayInLayerSwitcher - * {Boolean} Display the layer's name in the layer switcher. Default is - * true. - */ - displayInLayerSwitcher: true, - - /** - * APIProperty: visibility - * {Boolean} The layer should be displayed in the map. Default is true. - */ - visibility: true, - - /** - * APIProperty: attribution - * {String} Attribution string, displayed when an - * has been added to the map. - */ - attribution: null, - - /** - * Property: inRange - * {Boolean} The current map resolution is within the layer's min/max - * range. This is set in whenever the zoom - * changes. - */ - inRange: false, - - /** - * Propery: imageSize - * {} For layers with a gutter, the image is larger than - * the tile by twice the gutter in each dimension. - */ - imageSize: null, - - // OPTIONS - - /** - * Property: options - * {Object} An optional object whose properties will be set on the layer. - * Any of the layer properties can be set as a property of the options - * object and sent to the constructor when the layer is created. - */ - options: 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: gutter - * {Integer} Determines the width (in pixels) of the gutter around image - * tiles to ignore. By setting this property to a non-zero value, - * images will be requested that are wider and taller than the tile - * size by a value of 2 x gutter. This allows artifacts of rendering - * at tile edges to be ignored. Set a gutter value that is equal to - * half the size of the widest symbol that needs to be displayed. - * Defaults to zero. Non-tiled layers always have zero gutter. - */ - gutter: 0, - - /** - * APIProperty: projection - * {} or {} Specifies the projection of the layer. - * Can be set in the layer options. If not specified in the layer options, - * it is set to the default projection specified in the map, - * when the layer is added to the map. - * Projection along with default maxExtent and resolutions - * are set automatically with commercial baselayers in EPSG:3857, - * such as Google, Bing and OpenStreetMap, and do not need to be specified. - * Otherwise, if specifying projection, also set maxExtent, - * maxResolution or resolutions as appropriate. - * When using vector layers with strategies, layer projection should be set - * to the projection of the source data if that is different from the map default. - * - * Can be either a string or an object; - * if a string is passed, will be converted to an object when - * the layer is added to the map. - * - */ - projection: null, - - /** - * APIProperty: units - * {String} The layer map units. Defaults to null. Possible values - * are 'degrees' (or 'dd'), 'm', 'ft', 'km', 'mi', 'inches'. - * Normally taken from the projection. - * Only required if both map and layers do not define a projection, - * or if they define a projection which does not define units. - */ - units: null, - - /** - * APIProperty: scales - * {Array} An array of map scales in descending order. The values in the - * array correspond to the map scale denominator. Note that these - * values only make sense if the display (monitor) resolution of the - * client is correctly guessed by whomever is configuring the - * application. In addition, the units property must also be set. - * Use instead wherever possible. - */ - scales: null, - - /** - * APIProperty: resolutions - * {Array} A list of map resolutions (map units per pixel) in descending - * order. If this is not set in the layer constructor, it will be set - * based on other resolution related properties (maxExtent, - * maxResolution, maxScale, etc.). - */ - resolutions: null, - - /** - * APIProperty: maxExtent - * {|Array} If provided as an array, the array - * should consist of four values (left, bottom, right, top). - * The maximum extent for the layer. Defaults to null. - * - * The center of these bounds will not stray outside - * of the viewport extent during panning. In addition, if - * is set to false, data will not be - * requested that falls completely outside of these bounds. - */ - maxExtent: null, - - /** - * APIProperty: minExtent - * {|Array} If provided as an array, the array - * should consist of four values (left, bottom, right, top). - * The minimum extent for the layer. Defaults to null. - */ - minExtent: null, - - /** - * APIProperty: maxResolution - * {Float} Default max is 360 deg / 256 px, which corresponds to - * zoom level 0 on gmaps. Specify a different value in the layer - * options if you are not using the default - * and displaying the whole world. - */ - maxResolution: null, - - /** - * APIProperty: minResolution - * {Float} - */ - minResolution: null, - - /** - * APIProperty: numZoomLevels - * {Integer} - */ - numZoomLevels: null, - - /** - * APIProperty: minScale - * {Float} - */ - minScale: null, - - /** - * APIProperty: maxScale - * {Float} - */ - maxScale: null, - - /** - * APIProperty: displayOutsideMaxExtent - * {Boolean} Request map tiles that are completely outside of the max - * extent for this layer. Defaults to false. - */ - displayOutsideMaxExtent: false, - - /** - * APIProperty: wrapDateLine - * {Boolean} Wraps the world at the international dateline, so the map can - * be panned infinitely in longitudinal direction. Only use this on the - * base layer, and only if the layer's maxExtent equals the world bounds. - * #487 for more info. - */ - wrapDateLine: false, - - /** - * Property: metadata - * {Object} This object can be used to store additional information on a - * layer object. - */ - metadata: null, - - /** - * Constructor: OpenLayers.Layer - * - * Parameters: - * name - {String} The layer name - * options - {Object} Hashtable of extra options to tag onto the layer - */ - initialize: function(name, options) { - - this.metadata = {}; - - options = OpenLayers.Util.extend({}, options); - // make sure we respect alwaysInRange if set on the prototype - if (this.alwaysInRange != null) { - options.alwaysInRange = this.alwaysInRange; - } - this.addOptions(options); - - this.name = name; - - if (this.id == null) { - - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); - - this.div = OpenLayers.Util.createDiv(this.id); - this.div.style.width = "100%"; - this.div.style.height = "100%"; - this.div.dir = "ltr"; - - this.events = new OpenLayers.Events(this, this.div); - if(this.eventListeners instanceof Object) { - this.events.on(this.eventListeners); - } - - } - }, - - /** - * Method: destroy - * Destroy is a destructor: this is to alleviate cyclic references which - * the Javascript garbage cleaner can not take care of on its own. - * - * Parameters: - * setNewBaseLayer - {Boolean} Set a new base layer when this layer has - * been destroyed. Default is true. - */ - destroy: function(setNewBaseLayer) { - if (setNewBaseLayer == null) { - setNewBaseLayer = true; - } - if (this.map != null) { - this.map.removeLayer(this, setNewBaseLayer); - } - this.projection = null; - this.map = null; - this.name = null; - this.div = null; - this.options = null; - - if (this.events) { - if(this.eventListeners) { - this.events.un(this.eventListeners); - } - this.events.destroy(); - } - this.eventListeners = null; - this.events = null; - }, - - /** - * Method: clone - * - * Parameters: - * obj - {} The layer to be cloned - * - * Returns: - * {} An exact clone of this - */ - clone: function (obj) { - - if (obj == null) { - obj = new OpenLayers.Layer(this.name, this.getOptions()); - } - - // catch any randomly tagged-on properties - OpenLayers.Util.applyDefaults(obj, this); - - // a cloned layer should never have its map property set - // because it has not been added to a map yet. - obj.map = null; - - return obj; - }, - - /** - * Method: getOptions - * Extracts an object from the layer with the properties that were set as - * options, but updates them with the values currently set on the - * instance. - * - * Returns: - * {Object} the of the layer, representing the current state. - */ - getOptions: function() { - var options = {}; - for(var o in this.options) { - options[o] = this[o]; - } - return options; - }, - - /** - * APIMethod: setName - * Sets the new layer name for this layer. Can trigger a changelayer event - * on the map. - * - * Parameters: - * newName - {String} The new name. - */ - setName: function(newName) { - if (newName != this.name) { - this.name = newName; - if (this.map != null) { - this.map.events.triggerEvent("changelayer", { - layer: this, - property: "name" - }); - } - } - }, - - /** - * APIMethod: addOptions - * - * Parameters: - * newOptions - {Object} - * reinitialize - {Boolean} If set to true, and if resolution options of the - * current baseLayer were changed, the map will be recentered to make - * sure that it is displayed with a valid resolution, and a - * changebaselayer event will be triggered. - */ - addOptions: function (newOptions, reinitialize) { - - if (this.options == null) { - this.options = {}; - } - - if (newOptions) { - // make sure this.projection references a projection object - if(typeof newOptions.projection == "string") { - newOptions.projection = new OpenLayers.Projection(newOptions.projection); - } - if (newOptions.projection) { - // get maxResolution, units and maxExtent from projection defaults if - // they are not defined already - OpenLayers.Util.applyDefaults(newOptions, - OpenLayers.Projection.defaults[newOptions.projection.getCode()]); - } - // allow array for extents - if (newOptions.maxExtent && !(newOptions.maxExtent instanceof OpenLayers.Bounds)) { - newOptions.maxExtent = new OpenLayers.Bounds(newOptions.maxExtent); - } - if (newOptions.minExtent && !(newOptions.minExtent instanceof OpenLayers.Bounds)) { - newOptions.minExtent = new OpenLayers.Bounds(newOptions.minExtent); - } - } - - // update our copy for clone - OpenLayers.Util.extend(this.options, newOptions); - - // add new options to this - OpenLayers.Util.extend(this, newOptions); - - // get the units from the projection, if we have a projection - // and it it has units - if(this.projection && this.projection.getUnits()) { - this.units = this.projection.getUnits(); - } - - // re-initialize resolutions if necessary, i.e. if any of the - // properties of the "properties" array defined below is set - // in the new options - if(this.map) { - // store current resolution so we can try to restore it later - var resolution = this.map.getResolution(); - var properties = this.RESOLUTION_PROPERTIES.concat( - ["projection", "units", "minExtent", "maxExtent"] - ); - for(var o in newOptions) { - if(newOptions.hasOwnProperty(o) && - OpenLayers.Util.indexOf(properties, o) >= 0) { - - this.initResolutions(); - if (reinitialize && this.map.baseLayer === this) { - // update map position, and restore previous resolution - this.map.setCenter(this.map.getCenter(), - this.map.getZoomForResolution(resolution), - false, true - ); - // trigger a changebaselayer event to make sure that - // all controls (especially - // OpenLayers.Control.PanZoomBar) get notified of the - // new options - this.map.events.triggerEvent("changebaselayer", { - layer: this - }); - } - break; - } - } - } - }, - - /** - * APIMethod: onMapResize - * This function can be implemented by subclasses - */ - onMapResize: function() { - //this function can be implemented by subclasses - }, - - /** - * APIMethod: redraw - * Redraws the layer. Returns true if the layer was redrawn, false if not. - * - * Returns: - * {Boolean} The layer was redrawn. - */ - redraw: function() { - var redrawn = false; - if (this.map) { - - // min/max Range may have changed - this.inRange = this.calculateInRange(); - - // map's center might not yet be set - var extent = this.getExtent(); - - if (extent && this.inRange && this.visibility) { - var zoomChanged = true; - this.moveTo(extent, zoomChanged, false); - this.events.triggerEvent("moveend", - {"zoomChanged": zoomChanged}); - redrawn = true; - } - } - return redrawn; - }, - - /** - * Method: moveTo - * - * Parameters: - * bounds - {} - * zoomChanged - {Boolean} Tells when zoom has changed, as layers have to - * do some init work in that case. - * dragging - {Boolean} - */ - moveTo:function(bounds, zoomChanged, dragging) { - var display = this.visibility; - if (!this.isBaseLayer) { - display = display && this.inRange; - } - this.display(display); - }, - - /** - * Method: moveByPx - * Move the layer based on pixel vector. To be implemented by subclasses. - * - * Parameters: - * dx - {Number} The x coord of the displacement vector. - * dy - {Number} The y coord of the displacement vector. - */ - moveByPx: function(dx, dy) { - }, - - /** - * Method: setMap - * Set the map property for the layer. This is done through an accessor - * so that subclasses can override this and take special action once - * they have their map variable set. - * - * Here we take care to bring over any of the necessary default - * properties from the map. - * - * Parameters: - * map - {} - */ - setMap: function(map) { - if (this.map == null) { - - this.map = map; - - // grab some essential layer data from the map if it hasn't already - // been set - this.maxExtent = this.maxExtent || this.map.maxExtent; - this.minExtent = this.minExtent || this.map.minExtent; - - this.projection = this.projection || this.map.projection; - if (typeof this.projection == "string") { - this.projection = new OpenLayers.Projection(this.projection); - } - - // Check the projection to see if we can get units -- if not, refer - // to properties. - this.units = this.projection.getUnits() || - this.units || this.map.units; - - this.initResolutions(); - - if (!this.isBaseLayer) { - this.inRange = this.calculateInRange(); - var show = ((this.visibility) && (this.inRange)); - this.div.style.display = show ? "" : "none"; - } - - // deal with gutters - this.setTileSize(); - } - }, - - /** - * Method: afterAdd - * Called at the end of the map.addLayer sequence. At this point, the map - * will have a base layer. To be overridden by subclasses. - */ - afterAdd: function() { - }, - - /** - * APIMethod: removeMap - * Just as setMap() allows each layer the possibility to take a - * personalized action on being added to the map, removeMap() allows - * each layer to take a personalized action on being removed from it. - * For now, this will be mostly unused, except for the EventPane layer, - * which needs this hook so that it can remove the special invisible - * pane. - * - * Parameters: - * map - {} - */ - removeMap: function(map) { - //to be overridden by subclasses - }, - - /** - * APIMethod: getImageSize - * - * Parameters: - * bounds - {} optional tile bounds, can be used - * by subclasses that have to deal with different tile sizes at the - * layer extent edges (e.g. Zoomify) - * - * Returns: - * {} The size that the image should be, taking into - * account gutters. - */ - getImageSize: function(bounds) { - return (this.imageSize || this.tileSize); - }, - - /** - * APIMethod: setTileSize - * Set the tile size based on the map size. This also sets layer.imageSize - * or use by Tile.Image. - * - * Parameters: - * size - {} - */ - setTileSize: function(size) { - var tileSize = (size) ? size : - ((this.tileSize) ? this.tileSize : - this.map.getTileSize()); - this.tileSize = tileSize; - if(this.gutter) { - // layers with gutters need non-null tile sizes - //if(tileSize == null) { - // OpenLayers.console.error("Error in layer.setMap() for " + - // this.name + ": layers with " + - // "gutters need non-null tile sizes"); - //} - this.imageSize = new OpenLayers.Size(tileSize.w + (2*this.gutter), - tileSize.h + (2*this.gutter)); - } - }, - - /** - * APIMethod: getVisibility - * - * Returns: - * {Boolean} The layer should be displayed (if in range). - */ - getVisibility: function() { - return this.visibility; - }, - - /** - * APIMethod: setVisibility - * Set the visibility flag for the layer and hide/show & redraw - * accordingly. Fire event unless otherwise specified - * - * Note that visibility is no longer simply whether or not the layer's - * style.display is set to "block". Now we store a 'visibility' state - * property on the layer class, this allows us to remember whether or - * not we *desire* for a layer to be visible. In the case where the - * map's resolution is out of the layer's range, this desire may be - * subverted. - * - * Parameters: - * visibility - {Boolean} Whether or not to display the layer (if in range) - */ - setVisibility: function(visibility) { - if (visibility != this.visibility) { - this.visibility = visibility; - this.display(visibility); - this.redraw(); - if (this.map != null) { - this.map.events.triggerEvent("changelayer", { - layer: this, - property: "visibility" - }); - } - this.events.triggerEvent("visibilitychanged"); - } - }, - - /** - * APIMethod: display - * Hide or show the Layer. This is designed to be used internally, and - * is not generally the way to enable or disable the layer. For that, - * use the setVisibility function instead.. - * - * Parameters: - * display - {Boolean} - */ - display: function(display) { - if (display != (this.div.style.display != "none")) { - this.div.style.display = (display && this.calculateInRange()) ? "block" : "none"; - } - }, - - /** - * APIMethod: calculateInRange - * - * Returns: - * {Boolean} The layer is displayable at the current map's current - * resolution. Note that if 'alwaysInRange' is true for the layer, - * this function will always return true. - */ - calculateInRange: function() { - var inRange = false; - - if (this.alwaysInRange) { - inRange = true; - } else { - if (this.map) { - var resolution = this.map.getResolution(); - inRange = ( (resolution >= this.minResolution) && - (resolution <= this.maxResolution) ); - } - } - return inRange; - }, - - /** - * APIMethod: setIsBaseLayer - * - * Parameters: - * isBaseLayer - {Boolean} - */ - setIsBaseLayer: function(isBaseLayer) { - if (isBaseLayer != this.isBaseLayer) { - this.isBaseLayer = isBaseLayer; - if (this.map != null) { - this.map.events.triggerEvent("changebaselayer", { - layer: this - }); - } - } - }, - - /********************************************************/ - /* */ - /* Baselayer Functions */ - /* */ - /********************************************************/ - - /** - * Method: initResolutions - * This method's responsibility is to set up the 'resolutions' array - * for the layer -- this array is what the layer will use to interface - * between the zoom levels of the map and the resolution display - * of the layer. - * - * The user has several options that determine how the array is set up. - * - * For a detailed explanation, see the following wiki from the - * openlayers.org homepage: - * http://trac.openlayers.org/wiki/SettingZoomLevels - */ - initResolutions: function() { - - // ok we want resolutions, here's our strategy: - // - // 1. if resolutions are defined in the layer config, use them - // 2. else, if scales are defined in the layer config then derive - // resolutions from these scales - // 3. else, attempt to calculate resolutions from maxResolution, - // minResolution, numZoomLevels, maxZoomLevel set in the - // layer config - // 4. if we still don't have resolutions, and if resolutions - // are defined in the same, use them - // 5. else, if scales are defined in the map then derive - // resolutions from these scales - // 6. else, attempt to calculate resolutions from maxResolution, - // minResolution, numZoomLevels, maxZoomLevel set in the - // map - // 7. hope for the best! - - var i, len, p; - var props = {}, alwaysInRange = true; - - // get resolution data from layer config - // (we also set alwaysInRange in the layer as appropriate) - for(i=0, len=this.RESOLUTION_PROPERTIES.length; i} A Bounds object which represents the lon/lat - * bounds of the current viewPort. - */ - getExtent: function() { - // just use stock map calculateBounds function -- passing no arguments - // means it will user map's current center & resolution - // - return this.map.calculateBounds(); - }, - - /** - * APIMethod: getZoomForExtent - * - * Parameters: - * extent - {} - * closest - {Boolean} Find the zoom level that most closely fits the - * specified bounds. Note that this may result in a zoom that does - * not exactly contain the entire extent. - * Default is false. - * - * Returns: - * {Integer} The index of the zoomLevel (entry in the resolutions array) - * for the passed-in extent. We do this by calculating the ideal - * resolution for the given extent (based on the map size) and then - * calling getZoomForResolution(), passing along the 'closest' - * parameter. - */ - getZoomForExtent: function(extent, closest) { - var viewSize = this.map.getSize(); - var idealResolution = Math.max( extent.getWidth() / viewSize.w, - extent.getHeight() / viewSize.h ); - - return this.getZoomForResolution(idealResolution, closest); - }, - - /** - * Method: getDataExtent - * Calculates the max extent which includes all of the data for the layer. - * This function is to be implemented by subclasses. - * - * Returns: - * {} - */ - getDataExtent: function () { - //to be implemented by subclasses - }, - - /** - * APIMethod: getResolutionForZoom - * - * Parameters: - * zoom - {Float} - * - * Returns: - * {Float} A suitable resolution for the specified zoom. - */ - getResolutionForZoom: function(zoom) { - zoom = Math.max(0, Math.min(zoom, this.resolutions.length - 1)); - var resolution; - if(this.map.fractionalZoom) { - var low = Math.floor(zoom); - var high = Math.ceil(zoom); - resolution = this.resolutions[low] - - ((zoom-low) * (this.resolutions[low]-this.resolutions[high])); - } else { - resolution = this.resolutions[Math.round(zoom)]; - } - return resolution; - }, - - /** - * APIMethod: getZoomForResolution - * - * Parameters: - * resolution - {Float} - * closest - {Boolean} Find the zoom level that corresponds to the absolute - * closest resolution, which may result in a zoom whose corresponding - * resolution is actually smaller than we would have desired (if this - * is being called from a getZoomForExtent() call, then this means that - * the returned zoom index might not actually contain the entire - * extent specified... but it'll be close). - * Default is false. - * - * Returns: - * {Integer} The index of the zoomLevel (entry in the resolutions array) - * that corresponds to the best fit resolution given the passed in - * value and the 'closest' specification. - */ - getZoomForResolution: function(resolution, closest) { - var zoom, i, len; - if(this.map.fractionalZoom) { - var lowZoom = 0; - var highZoom = this.resolutions.length - 1; - var highRes = this.resolutions[lowZoom]; - var lowRes = this.resolutions[highZoom]; - var res; - for(i=0, len=this.resolutions.length; i= resolution) { - highRes = res; - lowZoom = i; - } - if(res <= resolution) { - lowRes = res; - highZoom = i; - break; - } - } - var dRes = highRes - lowRes; - if(dRes > 0) { - zoom = lowZoom + ((highRes - resolution) / dRes); - } else { - zoom = lowZoom; - } - } else { - var diff; - var minDiff = Number.POSITIVE_INFINITY; - for(i=0, len=this.resolutions.length; i minDiff) { - break; - } - minDiff = diff; - } else { - if (this.resolutions[i] < resolution) { - break; - } - } - } - zoom = Math.max(0, i-1); - } - return zoom; - }, - - /** - * APIMethod: getLonLatFromViewPortPx - * - * Parameters: - * viewPortPx - {|Object} An OpenLayers.Pixel or - * an object with a 'x' - * and 'y' properties. - * - * Returns: - * {} An OpenLayers.LonLat which is the passed-in - * view port , translated into lon/lat by the layer. - */ - getLonLatFromViewPortPx: function (viewPortPx) { - var lonlat = null; - var map = this.map; - if (viewPortPx != null && map.minPx) { - var res = map.getResolution(); - var maxExtent = map.getMaxExtent({restricted: true}); - var lon = (viewPortPx.x - map.minPx.x) * res + maxExtent.left; - var lat = (map.minPx.y - viewPortPx.y) * res + maxExtent.top; - lonlat = new OpenLayers.LonLat(lon, lat); - - if (this.wrapDateLine) { - lonlat = lonlat.wrapDateLine(this.maxExtent); - } - } - return lonlat; - }, - - /** - * APIMethod: getViewPortPxFromLonLat - * Returns a pixel location given a map location. This method will return - * fractional pixel values. - * - * Parameters: - * lonlat - {|Object} An OpenLayers.LonLat or - * an object with a 'lon' - * and 'lat' properties. - * - * Returns: - * {} An which is the passed-in - * lonlat translated into view port pixels. - */ - getViewPortPxFromLonLat: function (lonlat, resolution) { - var px = null; - if (lonlat != null) { - resolution = resolution || this.map.getResolution(); - var extent = this.map.calculateBounds(null, resolution); - px = new OpenLayers.Pixel( - (1/resolution * (lonlat.lon - extent.left)), - (1/resolution * (extent.top - lonlat.lat)) - ); - } - return px; - }, - - /** - * APIMethod: setOpacity - * Sets the opacity for the entire layer (all images) - * - * Parameters: - * opacity - {Float} - */ - setOpacity: function(opacity) { - if (opacity != this.opacity) { - this.opacity = opacity; - var childNodes = this.div.childNodes; - for(var i = 0, len = childNodes.length; i < len; ++i) { - var element = childNodes[i].firstChild || childNodes[i]; - var lastChild = childNodes[i].lastChild; - //TODO de-uglify this - if (lastChild && lastChild.nodeName.toLowerCase() === "iframe") { - element = lastChild.parentNode; - } - OpenLayers.Util.modifyDOMElement(element, null, null, null, - null, null, null, opacity); - } - if (this.map != null) { - this.map.events.triggerEvent("changelayer", { - layer: this, - property: "opacity" - }); - } - } - }, - - /** - * Method: getZIndex - * - * Returns: - * {Integer} the z-index of this layer - */ - getZIndex: function () { - return this.div.style.zIndex; - }, - - /** - * Method: setZIndex - * - * Parameters: - * zIndex - {Integer} - */ - setZIndex: function (zIndex) { - this.div.style.zIndex = zIndex; - }, - - /** - * Method: adjustBounds - * This function will take a bounds, and if wrapDateLine option is set - * on the layer, it will return a bounds which is wrapped around the - * world. We do not wrap for bounds which *cross* the - * maxExtent.left/right, only bounds which are entirely to the left - * or entirely to the right. - * - * Parameters: - * bounds - {} - */ - adjustBounds: function (bounds) { - - if (this.gutter) { - // Adjust the extent of a bounds in map units by the - // layer's gutter in pixels. - var mapGutter = this.gutter * this.map.getResolution(); - bounds = new OpenLayers.Bounds(bounds.left - mapGutter, - bounds.bottom - mapGutter, - bounds.right + mapGutter, - bounds.top + mapGutter); - } - - if (this.wrapDateLine) { - // wrap around the date line, within the limits of rounding error - var wrappingOptions = { - 'rightTolerance':this.getResolution(), - 'leftTolerance':this.getResolution() - }; - bounds = bounds.wrapDateLine(this.maxExtent, wrappingOptions); - - } - return bounds; - }, - - CLASS_NAME: "OpenLayers.Layer" -}); -/* ====================================================================== - 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. - * See license.txt in the OpenLayers distribution or repository for the - * full text of the license. */ - - -/** - * @requires OpenLayers/Layer.js - */ - -/** - * Class: OpenLayers.Layer.HTTPRequest - * - * Inherits from: - * - - */ -OpenLayers.Layer.HTTPRequest = OpenLayers.Class(OpenLayers.Layer, { - - /** - * Constant: URL_HASH_FACTOR - * {Float} Used to hash URL param strings for multi-WMS server selection. - * Set to the Golden Ratio per Knuth's recommendation. - */ - URL_HASH_FACTOR: (Math.sqrt(5) - 1) / 2, - - /** - * Property: url - * {Array(String) or String} This is either an array of url strings or - * a single url string. - */ - url: null, - - /** - * Property: params - * {Object} Hashtable of key/value parameters - */ - params: null, - - /** - * APIProperty: reproject - * *Deprecated*. See http://docs.openlayers.org/library/spherical_mercator.html - * for information on the replacement for this functionality. - * {Boolean} Whether layer should reproject itself based on base layer - * locations. This allows reprojection onto commercial layers. - * Default is false: Most layers can't reproject, but layers - * which can create non-square geographic pixels can, like WMS. - * - */ - reproject: false, - - /** - * Constructor: OpenLayers.Layer.HTTPRequest - * - * Parameters: - * name - {String} - * url - {Array(String) or String} - * params - {Object} - * options - {Object} Hashtable of extra options to tag onto the layer - */ - initialize: function(name, url, params, options) { - OpenLayers.Layer.prototype.initialize.apply(this, [name, options]); - this.url = url; - if (!this.params) { - this.params = OpenLayers.Util.extend({}, params); - } - }, - - /** - * APIMethod: destroy - */ - destroy: function() { - this.url = null; - this.params = null; - OpenLayers.Layer.prototype.destroy.apply(this, arguments); - }, - - /** - * APIMethod: clone - * - * Parameters: - * obj - {Object} - * - * Returns: - * {} An exact clone of this - * - */ - clone: function (obj) { - - if (obj == null) { - obj = new OpenLayers.Layer.HTTPRequest(this.name, - this.url, - this.params, - this.getOptions()); - } - - //get all additions from superclasses - obj = OpenLayers.Layer.prototype.clone.apply(this, [obj]); - - // copy/set any non-init, non-simple values here - - return obj; - }, - - /** - * APIMethod: setUrl - * - * Parameters: - * newUrl - {String} - */ - setUrl: function(newUrl) { - this.url = newUrl; - }, - - /** - * APIMethod: mergeNewParams - * - * Parameters: - * newParams - {Object} - * - * Returns: - * redrawn: {Boolean} whether the layer was actually redrawn. - */ - mergeNewParams:function(newParams) { - this.params = OpenLayers.Util.extend(this.params, newParams); - var ret = this.redraw(); - if(this.map != null) { - this.map.events.triggerEvent("changelayer", { - layer: this, - property: "params" - }); - } - return ret; - }, - - /** - * APIMethod: redraw - * Redraws the layer. Returns true if the layer was redrawn, false if not. - * - * Parameters: - * force - {Boolean} Force redraw by adding random parameter. - * - * Returns: - * {Boolean} The layer was redrawn. - */ - redraw: function(force) { - if (force) { - return this.mergeNewParams({"_olSalt": Math.random()}); - } else { - return OpenLayers.Layer.prototype.redraw.apply(this, []); - } - }, - - /** - * Method: selectUrl - * selectUrl() implements the standard floating-point multiplicative - * hash function described by Knuth, and hashes the contents of the - * given param string into a float between 0 and 1. This float is then - * scaled to the size of the provided urls array, and used to select - * a URL. - * - * Parameters: - * paramString - {String} - * urls - {Array(String)} - * - * Returns: - * {String} An entry from the urls array, deterministically selected based - * on the paramString. - */ - selectUrl: function(paramString, urls) { - var product = 1; - for (var i=0, len=paramString.length; i 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. */ - - -/** - * @requires OpenLayers/Tile.js - * @requires OpenLayers/Animation.js - * @requires OpenLayers/Util.js - */ - -/** - * Class: OpenLayers.Tile.Image - * Instances of OpenLayers.Tile.Image are used to manage the image tiles - * used by various layers. Create a new image tile with the - * constructor. - * - * Inherits from: - * - - */ -OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { - - /** - * 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 (in addition to the events): - * beforeload - Triggered before an image is prepared for loading, when the - * url for the image is known already. Listeners may call on - * the tile instance. If they do so, that image will be used and no new - * one will be created. - */ - - /** - * APIProperty: url - * {String} The URL of the image being requested. No default. Filled in by - * layer.getURL() function. May be modified by loadstart listeners. - */ - url: null, - - /** - * Property: imgDiv - * {HTMLImageElement} The image for this tile. - */ - imgDiv: null, - - /** - * Property: frame - * {DOMElement} The image element is appended to the frame. Any gutter on - * the image will be hidden behind the frame. If no gutter is set, - * this will be null. - */ - frame: null, - - /** - * Property: imageReloadAttempts - * {Integer} Attempts to load the image. - */ - imageReloadAttempts: null, - - /** - * Property: layerAlphaHack - * {Boolean} True if the png alpha hack needs to be applied on the layer's div. - */ - layerAlphaHack: null, - - /** - * Property: asyncRequestId - * {Integer} ID of an request to see if request is still valid. This is a - * number which increments by 1 for each asynchronous request. - */ - asyncRequestId: null, - - /** - * APIProperty: maxGetUrlLength - * {Number} If set, requests that would result in GET urls with more - * characters than the number provided will be made using form-encoded - * HTTP POST. It is good practice to avoid urls that are longer than 2048 - * characters. - * - * Caution: - * Older versions of Gecko based browsers (e.g. Firefox < 3.5) and most - * Opera versions do not fully support this option. On all browsers, - * transition effects are not supported if POST requests are used. - */ - maxGetUrlLength: null, - - /** - * Property: canvasContext - * {CanvasRenderingContext2D} A canvas context associated with - * the tile image. - */ - canvasContext: null, - - /** - * APIProperty: crossOriginKeyword - * The value of the crossorigin keyword to use when loading images. This is - * only relevant when using for tiles from remote - * origins and should be set to either 'anonymous' or 'use-credentials' - * for servers that send Access-Control-Allow-Origin headers with their - * tiles. - */ - crossOriginKeyword: null, - - /** TBD 3.0 - reorder the parameters to the init function to remove - * URL. the getUrl() function on the layer gets called on - * each draw(), so no need to specify it here. - */ - - /** - * Constructor: OpenLayers.Tile.Image - * Constructor for a new instance. - * - * Parameters: - * layer - {} layer that the tile will go in. - * position - {} - * bounds - {} - * url - {} Deprecated. Remove me in 3.0. - * size - {} - * options - {Object} - */ - initialize: function(layer, position, bounds, url, size, options) { - OpenLayers.Tile.prototype.initialize.apply(this, arguments); - - this.url = url; //deprecated remove me - - this.layerAlphaHack = this.layer.alpha && OpenLayers.Util.alphaHack(); - - if (this.maxGetUrlLength != null || this.layer.gutter || this.layerAlphaHack) { - // only create frame if it's needed - this.frame = document.createElement("div"); - this.frame.style.position = "absolute"; - this.frame.style.overflow = "hidden"; - } - if (this.maxGetUrlLength != null) { - OpenLayers.Util.extend(this, OpenLayers.Tile.Image.IFrame); - } - }, - - /** - * APIMethod: destroy - * nullify references to prevent circular references and memory leaks - */ - destroy: function() { - if (this.imgDiv) { - this.clear(); - this.imgDiv = null; - this.frame = null; - } - // don't handle async requests any more - this.asyncRequestId = null; - OpenLayers.Tile.prototype.destroy.apply(this, arguments); - }, - - /** - * Method: draw - * Check that a tile should be drawn, and draw it. - * - * Returns: - * {Boolean} Was a tile drawn? Or null if a beforedraw listener returned - * false. - */ - draw: function() { - var shouldDraw = OpenLayers.Tile.prototype.draw.apply(this, arguments); - if (shouldDraw) { - // The layer's reproject option is deprecated. - if (this.layer != this.layer.map.baseLayer && this.layer.reproject) { - // getBoundsFromBaseLayer is defined in deprecated.js. - this.bounds = this.getBoundsFromBaseLayer(this.position); - } - if (this.isLoading) { - //if we're already loading, send 'reload' instead of 'loadstart'. - this._loadEvent = "reload"; - } else { - this.isLoading = true; - this._loadEvent = "loadstart"; - } - this.renderTile(); - this.positionTile(); - } else if (shouldDraw === false) { - this.unload(); - } - return shouldDraw; - }, - - /** - * Method: renderTile - * Internal function to actually initialize the image tile, - * position it correctly, and set its url. - */ - renderTile: function() { - if (this.layer.async) { - // Asynchronous image requests call the asynchronous getURL method - // on the layer to fetch an image that covers 'this.bounds'. - var id = this.asyncRequestId = (this.asyncRequestId || 0) + 1; - this.layer.getURLasync(this.bounds, function(url) { - if (id == this.asyncRequestId) { - this.url = url; - this.initImage(); - } - }, this); - } else { - // synchronous image requests get the url immediately. - this.url = this.layer.getURL(this.bounds); - this.initImage(); - } - }, - - /** - * Method: positionTile - * Using the properties currenty set on the layer, position the tile correctly. - * This method is used both by the async and non-async versions of the Tile.Image - * code. - */ - positionTile: function() { - var style = this.getTile().style, - size = this.frame ? this.size : - this.layer.getImageSize(this.bounds), - ratio = 1; - if (this.layer instanceof OpenLayers.Layer.Grid) { - ratio = this.layer.getServerResolution() / this.layer.map.getResolution(); - } - style.left = this.position.x + "px"; - style.top = this.position.y + "px"; - style.width = Math.round(ratio * size.w) + "px"; - style.height = Math.round(ratio * size.h) + "px"; - }, - - /** - * Method: clear - * Remove the tile from the DOM, clear it of any image related data so that - * it can be reused in a new location. - */ - clear: function() { - OpenLayers.Tile.prototype.clear.apply(this, arguments); - var img = this.imgDiv; - if (img) { - var tile = this.getTile(); - if (tile.parentNode === this.layer.div) { - this.layer.div.removeChild(tile); - } - this.setImgSrc(); - if (this.layerAlphaHack === true) { - img.style.filter = ""; - } - OpenLayers.Element.removeClass(img, "olImageLoadError"); - } - this.canvasContext = null; - }, - - /** - * Method: getImage - * Returns or creates and returns the tile image. - */ - getImage: function() { - if (!this.imgDiv) { - this.imgDiv = OpenLayers.Tile.Image.IMAGE.cloneNode(false); - - var style = this.imgDiv.style; - if (this.frame) { - var left = 0, top = 0; - if (this.layer.gutter) { - left = this.layer.gutter / this.layer.tileSize.w * 100; - top = this.layer.gutter / this.layer.tileSize.h * 100; - } - style.left = -left + "%"; - style.top = -top + "%"; - style.width = (2 * left + 100) + "%"; - style.height = (2 * top + 100) + "%"; - } - style.visibility = "hidden"; - style.opacity = 0; - if (this.layer.opacity < 1) { - style.filter = 'alpha(opacity=' + - (this.layer.opacity * 100) + - ')'; - } - style.position = "absolute"; - if (this.layerAlphaHack) { - // move the image out of sight - style.paddingTop = style.height; - style.height = "0"; - style.width = "100%"; - } - if (this.frame) { - this.frame.appendChild(this.imgDiv); - } - } - - return this.imgDiv; - }, - - /** - * APIMethod: setImage - * Sets the image element for this tile. This method should only be called - * from beforeload listeners. - * - * Parameters - * img - {HTMLImageElement} The image to use for this tile. - */ - setImage: function(img) { - this.imgDiv = img; - }, - - /** - * Method: initImage - * Creates the content for the frame on the tile. - */ - initImage: function() { - if (!this.url && !this.imgDiv) { - // fast path out - if there is no tile url and no previous image - this.isLoading = false; - return; - } - this.events.triggerEvent('beforeload'); - this.layer.div.appendChild(this.getTile()); - this.events.triggerEvent(this._loadEvent); - var img = this.getImage(); - var src = img.getAttribute('src') || ''; - if (this.url && OpenLayers.Util.isEquivalentUrl(src, this.url)) { - this._loadTimeout = window.setTimeout( - OpenLayers.Function.bind(this.onImageLoad, this), 0 - ); - } else { - this.stopLoading(); - if (this.crossOriginKeyword) { - img.removeAttribute("crossorigin"); - } - OpenLayers.Event.observe(img, "load", - OpenLayers.Function.bind(this.onImageLoad, this) - ); - OpenLayers.Event.observe(img, "error", - OpenLayers.Function.bind(this.onImageError, this) - ); - this.imageReloadAttempts = 0; - this.setImgSrc(this.url); - } - }, - - /** - * Method: setImgSrc - * Sets the source for the tile image - * - * Parameters: - * url - {String} or undefined to hide the image - */ - setImgSrc: function(url) { - var img = this.imgDiv; - if (url) { - img.style.visibility = 'hidden'; - img.style.opacity = 0; - // don't set crossOrigin if the url is a data URL - if (this.crossOriginKeyword) { - if (url.substr(0, 5) !== 'data:') { - img.setAttribute("crossorigin", this.crossOriginKeyword); - } else { - img.removeAttribute("crossorigin"); - } - } - img.src = url; - } else { - // Remove reference to the image, and leave it to the browser's - // caching and garbage collection. - this.stopLoading(); - this.imgDiv = null; - if (img.parentNode) { - img.parentNode.removeChild(img); - } - } - }, - - /** - * Method: getTile - * Get the tile's markup. - * - * Returns: - * {DOMElement} The tile's markup - */ - getTile: function() { - return this.frame ? this.frame : this.getImage(); - }, - - /** - * Method: createBackBuffer - * Create a backbuffer for this tile. A backbuffer isn't exactly a clone - * of the tile's markup, because we want to avoid the reloading of the - * image. So we clone the frame, and steal the image from the tile. - * - * Returns: - * {DOMElement} The markup, or undefined if the tile has no image - * or if it's currently loading. - */ - createBackBuffer: function() { - if (!this.imgDiv || this.isLoading) { - return; - } - var backBuffer; - if (this.frame) { - backBuffer = this.frame.cloneNode(false); - backBuffer.appendChild(this.imgDiv); - } else { - backBuffer = this.imgDiv; - } - this.imgDiv = null; - return backBuffer; - }, - - /** - * Method: onImageLoad - * Handler for the image onload event - */ - onImageLoad: function() { - var img = this.imgDiv; - this.stopLoading(); - img.style.visibility = 'inherit'; - img.style.opacity = this.layer.opacity; - this.isLoading = false; - this.canvasContext = null; - this.events.triggerEvent("loadend"); - - if (this.layerAlphaHack === true) { - img.style.filter = - "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + - img.src + "', sizingMethod='scale')"; - } - }, - - /** - * Method: onImageError - * Handler for the image onerror event - */ - onImageError: function() { - var img = this.imgDiv; - if (img.src != null) { - this.imageReloadAttempts++; - if (this.imageReloadAttempts <= OpenLayers.IMAGE_RELOAD_ATTEMPTS) { - this.setImgSrc(this.layer.getURL(this.bounds)); - } else { - OpenLayers.Element.addClass(img, "olImageLoadError"); - this.events.triggerEvent("loaderror"); - this.onImageLoad(); - } - } - }, - - /** - * Method: stopLoading - * Stops a loading sequence so won't be executed. - */ - stopLoading: function() { - OpenLayers.Event.stopObservingElement(this.imgDiv); - window.clearTimeout(this._loadTimeout); - delete this._loadTimeout; - }, - - /** - * APIMethod: getCanvasContext - * Returns a canvas context associated with the tile image (with - * the image drawn on it). - * Returns undefined if the browser does not support canvas, if - * the tile has no image or if it's currently loading. - * - * The function returns a canvas context instance but the - * underlying canvas is still available in the 'canvas' property: - * (code) - * var context = tile.getCanvasContext(); - * if (context) { - * var data = context.canvas.toDataURL('image/jpeg'); - * } - * (end) - * - * Returns: - * {Boolean} - */ - getCanvasContext: function() { - if (OpenLayers.CANVAS_SUPPORTED && this.imgDiv && !this.isLoading) { - if (!this.canvasContext) { - var canvas = document.createElement("canvas"); - canvas.width = this.size.w; - canvas.height = this.size.h; - this.canvasContext = canvas.getContext("2d"); - this.canvasContext.drawImage(this.imgDiv, 0, 0); - } - return this.canvasContext; - } - }, - - CLASS_NAME: "OpenLayers.Tile.Image" - -}); - -/** - * Constant: OpenLayers.Tile.Image.IMAGE - * {HTMLImageElement} The image for a tile. - */ -OpenLayers.Tile.Image.IMAGE = (function() { - var img = new Image(); - img.className = "olTileImage"; - // avoid image gallery menu in IE6 - img.galleryImg = "no"; - return img; -}()); - -/* ====================================================================== - OpenLayers/Layer/Grid.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/Layer/HTTPRequest.js - * @requires OpenLayers/Tile/Image.js - */ - -/** - * Class: OpenLayers.Layer.Grid - * Base class for layers that use a lattice of tiles. Create a new grid - * layer with the constructor. - * - * Inherits from: - * - - */ -OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { - - /** - * APIProperty: tileSize - * {} - */ - tileSize: null, - - /** - * Property: tileOriginCorner - * {String} If the property is not provided, the tile origin - * will be derived from the layer's . The corner of the - * used is determined by this property. Acceptable values - * are "tl" (top left), "tr" (top right), "bl" (bottom left), and "br" - * (bottom right). Default is "bl". - */ - tileOriginCorner: "bl", - - /** - * APIProperty: tileOrigin - * {} Optional origin for aligning the grid of tiles. - * If provided, requests for tiles at all resolutions will be aligned - * with this location (no tiles shall overlap this location). If - * not provided, the grid of tiles will be aligned with the layer's - * . Default is ``null``. - */ - tileOrigin: null, - - /** APIProperty: tileOptions - * {Object} optional configuration options for instances - * created by this Layer, if supported by the tile class. - */ - tileOptions: null, - - /** - * APIProperty: tileClass - * {} The tile class to use for this layer. - * Defaults is OpenLayers.Tile.Image. - */ - tileClass: OpenLayers.Tile.Image, - - /** - * Property: grid - * {Array(Array())} This is an array of rows, each row is - * an array of tiles. - */ - grid: null, - - /** - * APIProperty: singleTile - * {Boolean} Moves the layer into single-tile mode, meaning that one tile - * will be loaded. The tile's size will be determined by the 'ratio' - * property. When the tile is dragged such that it does not cover the - * entire viewport, it is reloaded. - */ - singleTile: false, - - /** APIProperty: ratio - * {Float} Used only when in single-tile mode, this specifies the - * ratio of the size of the single tile to the size of the map. - * Default value is 1.5. - */ - ratio: 1.5, - - /** - * APIProperty: buffer - * {Integer} Used only when in gridded mode, this specifies the number of - * extra rows and colums of tiles on each side which will - * surround the minimum grid tiles to cover the map. - * For very slow loading layers, a larger value may increase - * performance somewhat when dragging, but will increase bandwidth - * use significantly. - */ - buffer: 0, - - /** - * APIProperty: transitionEffect - * {String} The transition effect to use when the map is zoomed. - * Two posible values: - * - * "resize" - Existing tiles are resized on zoom to provide a visual - * effect of the zoom having taken place immediately. As the - * new tiles become available, they are drawn on top of the - * resized tiles (this is the default setting). - * "map-resize" - Existing tiles are resized on zoom and placed below the - * base layer. New tiles for the base layer will cover existing tiles. - * This setting is recommended when having an overlay duplicated during - * the transition is undesirable (e.g. street labels or big transparent - * fills). - * null - No transition effect. - * - * Using "resize" on non-opaque layers can cause undesired visual - * effects. Set transitionEffect to null in this case. - */ - transitionEffect: "resize", - - /** - * APIProperty: numLoadingTiles - * {Integer} How many tiles are still loading? - */ - numLoadingTiles: 0, - - /** - * Property: serverResolutions - * {Array(Number}} This property is documented in subclasses as - * an API property. - */ - serverResolutions: null, - - /** - * Property: loading - * {Boolean} Indicates if tiles are being loaded. - */ - loading: false, - - /** - * Property: backBuffer - * {DOMElement} The back buffer. - */ - backBuffer: null, - - /** - * Property: gridResolution - * {Number} The resolution of the current grid. Used for backbuffer and - * client zoom. This property is updated every time the grid is - * initialized. - */ - gridResolution: null, - - /** - * Property: backBufferResolution - * {Number} The resolution of the current back buffer. This property is - * updated each time a back buffer is created. - */ - backBufferResolution: null, - - /** - * Property: backBufferLonLat - * {Object} The top-left corner of the current back buffer. Includes lon - * and lat properties. This object is updated each time a back buffer - * is created. - */ - backBufferLonLat: null, - - /** - * Property: backBufferTimerId - * {Number} The id of the back buffer timer. This timer is used to - * delay the removal of the back buffer, thereby preventing - * flash effects caused by tile animation. - */ - backBufferTimerId: null, - - /** - * APIProperty: removeBackBufferDelay - * {Number} Delay for removing the backbuffer when all tiles have finished - * loading. Can be set to 0 when no css opacity transitions for the - * olTileImage class are used. Default is 0 for layers, - * 2500 for tiled layers. See for more information on - * tile animation. - */ - removeBackBufferDelay: null, - - /** - * APIProperty: className - * {String} Name of the class added to the layer div. If not set in the - * options passed to the constructor then className defaults to - * "olLayerGridSingleTile" for single tile layers (see ), - * and "olLayerGrid" for non single tile layers. - * - * Note: - * - * The displaying of tiles is not animated by default for single tile - * layers - OpenLayers' default theme (style.css) includes this: - * (code) - * .olLayerGrid .olTileImage { - * -webkit-transition: opacity 0.2s linear; - * -moz-transition: opacity 0.2s linear; - * -o-transition: opacity 0.2s linear; - * transition: opacity 0.2s linear; - * } - * (end) - * To animate tile displaying for any grid layer the following - * CSS rule can be used: - * (code) - * .olTileImage { - * -webkit-transition: opacity 0.2s linear; - * -moz-transition: opacity 0.2s linear; - * -o-transition: opacity 0.2s linear; - * transition: opacity 0.2s linear; - * } - * (end) - * In that case, to avoid flash effects, - * should not be zero. - */ - className: null, - - /** - * Register a listener for a particular event with the following syntax: - * (code) - * layer.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 layer.events.object. - * element - {DOMElement} A reference to layer.events.element. - * - * Supported event types: - * addtile - Triggered when a tile is added to this layer. Listeners receive - * an object as first argument, which has a tile property that - * references the tile that has been added. - * tileloadstart - Triggered when a tile starts loading. Listeners receive - * an object as first argument, which has a tile property that - * references the tile that starts loading. - * tileloaded - Triggered when each new tile is - * loaded, as a means of progress update to listeners. - * listeners can access 'numLoadingTiles' if they wish to keep - * track of the loading progress. Listeners are called with an object - * with a 'tile' property as first argument, making the loaded tile - * available to the listener, and an 'aborted' property, which will be - * true when loading was aborted and no tile data is available. - * tileerror - Triggered before the tileloaded event (i.e. when the tile is - * still hidden) if a tile failed to load. Listeners receive an object - * as first argument, which has a tile property that references the - * tile that could not be loaded. - * retile - Triggered when the layer recreates its tile grid. - */ - - /** - * Property: gridLayout - * {Object} Object containing properties tilelon, tilelat, startcol, - * startrow - */ - gridLayout: null, - - /** - * Property: rowSign - * {Number} 1 for grids starting at the top, -1 for grids starting at the - * bottom. This is used for several grid index and offset calculations. - */ - rowSign: null, - - /** - * Property: transitionendEvents - * {Array} Event names for transitionend - */ - transitionendEvents: [ - 'transitionend', 'webkitTransitionEnd', 'otransitionend', - 'oTransitionEnd' - ], - - /** - * Constructor: OpenLayers.Layer.Grid - * Create a new grid layer - * - * Parameters: - * name - {String} - * url - {String} - * params - {Object} - * options - {Object} Hashtable of extra options to tag onto the layer - */ - initialize: function(name, url, params, options) { - OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this, - arguments); - this.grid = []; - this._removeBackBuffer = OpenLayers.Function.bind(this.removeBackBuffer, this); - - this.initProperties(); - - this.rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1; - }, - - /** - * Method: initProperties - * Set any properties that depend on the value of singleTile. - * Currently sets removeBackBufferDelay and className - */ - initProperties: function() { - if (this.options.removeBackBufferDelay === undefined) { - this.removeBackBufferDelay = this.singleTile ? 0 : 2500; - } - - if (this.options.className === undefined) { - this.className = this.singleTile ? 'olLayerGridSingleTile' : - 'olLayerGrid'; - } - }, - - /** - * Method: setMap - * - * Parameters: - * map - {} The map. - */ - setMap: function(map) { - OpenLayers.Layer.HTTPRequest.prototype.setMap.call(this, map); - OpenLayers.Element.addClass(this.div, this.className); - }, - - /** - * Method: removeMap - * Called when the layer is removed from the map. - * - * Parameters: - * map - {} The map. - */ - removeMap: function(map) { - this.removeBackBuffer(); - }, - - /** - * APIMethod: destroy - * Deconstruct the layer and clear the grid. - */ - destroy: function() { - this.removeBackBuffer(); - this.clearGrid(); - - this.grid = null; - this.tileSize = null; - OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this, arguments); - }, - - /** - * APIMethod: mergeNewParams - * Refetches tiles with new params merged, keeping a backbuffer. Each - * loading new tile will have a css class of '.olTileReplacing'. If a - * stylesheet applies a 'display: none' style to that class, any fade-in - * transition will not apply, and backbuffers for each tile will be removed - * as soon as the tile is loaded. - * - * Parameters: - * newParams - {Object} - * - * Returns: - * redrawn: {Boolean} whether the layer was actually redrawn. - */ - - /** - * Method: clearGrid - * Go through and remove all tiles from the grid, calling - * destroy() on each of them to kill circular references - */ - clearGrid:function() { - if (this.grid) { - for(var iRow=0, len=this.grid.length; iRow} An exact clone of this OpenLayers.Layer.Grid - */ - clone: function (obj) { - - if (obj == null) { - obj = new OpenLayers.Layer.Grid(this.name, - this.url, - this.params, - this.getOptions()); - } - - //get all additions from superclasses - obj = OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this, [obj]); - - // copy/set any non-init, non-simple values here - if (this.tileSize != null) { - obj.tileSize = this.tileSize.clone(); - } - - // we do not want to copy reference to grid, so we make a new array - obj.grid = []; - obj.gridResolution = null; - // same for backbuffer - obj.backBuffer = null; - obj.backBufferTimerId = null; - obj.loading = false; - obj.numLoadingTiles = 0; - - return obj; - }, - - /** - * Method: moveTo - * This function is called whenever the map is moved. All the moving - * of actual 'tiles' is done by the map, but moveTo's role is to accept - * a bounds and make sure the data that that bounds requires is pre-loaded. - * - * Parameters: - * bounds - {} - * zoomChanged - {Boolean} - * dragging - {Boolean} - */ - moveTo:function(bounds, zoomChanged, dragging) { - - OpenLayers.Layer.HTTPRequest.prototype.moveTo.apply(this, arguments); - - bounds = bounds || this.map.getExtent(); - - if (bounds != null) { - - // if grid is empty or zoom has changed, we *must* re-tile - var forceReTile = !this.grid.length || zoomChanged; - - // total bounds of the tiles - var tilesBounds = this.getTilesBounds(); - - // the new map resolution - var resolution = this.map.getResolution(); - - // the server-supported resolution for the new map resolution - var serverResolution = this.getServerResolution(resolution); - - if (this.singleTile) { - - // We want to redraw whenever even the slightest part of the - // current bounds is not contained by our tile. - // (thus, we do not specify partial -- its default is false) - - if ( forceReTile || - (!dragging && !tilesBounds.containsBounds(bounds))) { - - // In single tile mode with no transition effect, we insert - // a non-scaled backbuffer when the layer is moved. But if - // a zoom occurs right after a move, i.e. before the new - // image is received, we need to remove the backbuffer, or - // an ill-positioned image will be visible during the zoom - // transition. - - if(zoomChanged && this.transitionEffect !== 'resize') { - this.removeBackBuffer(); - } - - if(!zoomChanged || this.transitionEffect === 'resize') { - this.applyBackBuffer(resolution); - } - - this.initSingleTile(bounds); - } - } else { - - // if the bounds have changed such that they are not even - // *partially* contained by our tiles (e.g. when user has - // programmatically panned to the other side of the earth on - // zoom level 18), then moveGriddedTiles could potentially have - // to run through thousands of cycles, so we want to reTile - // instead (thus, partial true). - forceReTile = forceReTile || - !tilesBounds.intersectsBounds(bounds, { - worldBounds: this.map.baseLayer.wrapDateLine && - this.map.getMaxExtent() - }); - - if(forceReTile) { - if(zoomChanged && (this.transitionEffect === 'resize' || - this.gridResolution === resolution)) { - this.applyBackBuffer(resolution); - } - this.initGriddedTiles(bounds); - } else { - this.moveGriddedTiles(); - } - } - } - }, - - /** - * Method: getTileData - * Given a map location, retrieve a tile and the pixel offset within that - * tile corresponding to the location. If there is not an existing - * tile in the grid that covers the given location, null will be - * returned. - * - * Parameters: - * loc - {} map location - * - * Returns: - * {Object} Object with the following properties: tile ({}), - * i ({Number} x-pixel offset from top left), and j ({Integer} y-pixel - * offset from top left). - */ - getTileData: function(loc) { - var data = null, - x = loc.lon, - y = loc.lat, - numRows = this.grid.length; - - if (this.map && numRows) { - var res = this.map.getResolution(), - tileWidth = this.tileSize.w, - tileHeight = this.tileSize.h, - bounds = this.grid[0][0].bounds, - left = bounds.left, - top = bounds.top; - - if (x < left) { - // deal with multiple worlds - if (this.map.baseLayer.wrapDateLine) { - var worldWidth = this.map.getMaxExtent().getWidth(); - var worldsAway = Math.ceil((left - x) / worldWidth); - x += worldWidth * worldsAway; - } - } - // tile distance to location (fractional number of tiles); - var dtx = (x - left) / (res * tileWidth); - var dty = (top - y) / (res * tileHeight); - // index of tile in grid - var col = Math.floor(dtx); - var row = Math.floor(dty); - if (row >= 0 && row < numRows) { - var tile = this.grid[row][col]; - if (tile) { - data = { - tile: tile, - // pixel index within tile - i: Math.floor((dtx - col) * tileWidth), - j: Math.floor((dty - row) * tileHeight) - }; - } - } - } - return data; - }, - - /** - * Method: destroyTile - * - * Parameters: - * tile - {} - */ - destroyTile: function(tile) { - this.removeTileMonitoringHooks(tile); - tile.destroy(); - }, - - /** - * Method: getServerResolution - * Return the closest server-supported resolution. - * - * Parameters: - * resolution - {Number} The base resolution. If undefined the - * map resolution is used. - * - * Returns: - * {Number} The closest server resolution value. - */ - getServerResolution: function(resolution) { - var distance = Number.POSITIVE_INFINITY; - resolution = resolution || this.map.getResolution(); - if(this.serverResolutions && - OpenLayers.Util.indexOf(this.serverResolutions, resolution) === -1) { - var i, newDistance, newResolution, serverResolution; - for(i=this.serverResolutions.length-1; i>= 0; i--) { - newResolution = this.serverResolutions[i]; - newDistance = Math.abs(newResolution - resolution); - if (newDistance > distance) { - break; - } - distance = newDistance; - serverResolution = newResolution; - } - resolution = serverResolution; - } - return resolution; - }, - - /** - * Method: getServerZoom - * Return the zoom value corresponding to the best matching server - * resolution, taking into account and . - * - * Returns: - * {Number} The closest server supported zoom. This is not the map zoom - * level, but an index of the server's resolutions array. - */ - getServerZoom: function() { - var resolution = this.getServerResolution(); - return this.serverResolutions ? - OpenLayers.Util.indexOf(this.serverResolutions, resolution) : - this.map.getZoomForResolution(resolution) + (this.zoomOffset || 0); - }, - - /** - * Method: applyBackBuffer - * Create, insert, scale and position a back buffer for the layer. - * - * Parameters: - * resolution - {Number} The resolution to transition to. - */ - applyBackBuffer: function(resolution) { - if(this.backBufferTimerId !== null) { - this.removeBackBuffer(); - } - var backBuffer = this.backBuffer; - if(!backBuffer) { - backBuffer = this.createBackBuffer(); - if(!backBuffer) { - return; - } - if (resolution === this.gridResolution) { - this.div.insertBefore(backBuffer, this.div.firstChild); - } else { - this.map.baseLayer.div.parentNode.insertBefore(backBuffer, this.map.baseLayer.div); - } - this.backBuffer = backBuffer; - - // set some information in the instance for subsequent - // calls to applyBackBuffer where the same back buffer - // is reused - var topLeftTileBounds = this.grid[0][0].bounds; - this.backBufferLonLat = { - lon: topLeftTileBounds.left, - lat: topLeftTileBounds.top - }; - this.backBufferResolution = this.gridResolution; - } - - var ratio = this.backBufferResolution / resolution; - - // scale the tiles inside the back buffer - var tiles = backBuffer.childNodes, tile; - for (var i=tiles.length-1; i>=0; --i) { - tile = tiles[i]; - tile.style.top = ((ratio * tile._i * tile._h) | 0) + 'px'; - tile.style.left = ((ratio * tile._j * tile._w) | 0) + 'px'; - tile.style.width = Math.round(ratio * tile._w) + 'px'; - tile.style.height = Math.round(ratio * tile._h) + 'px'; - } - - // and position it (based on the grid's top-left corner) - var position = this.getViewPortPxFromLonLat( - this.backBufferLonLat, resolution); - var leftOffset = this.map.layerContainerOriginPx.x; - var topOffset = this.map.layerContainerOriginPx.y; - backBuffer.style.left = Math.round(position.x - leftOffset) + 'px'; - backBuffer.style.top = Math.round(position.y - topOffset) + 'px'; - }, - - /** - * Method: createBackBuffer - * Create a back buffer. - * - * Returns: - * {DOMElement} The DOM element for the back buffer, undefined if the - * grid isn't initialized yet. - */ - createBackBuffer: function() { - var backBuffer; - if(this.grid.length > 0) { - backBuffer = document.createElement('div'); - backBuffer.id = this.div.id + '_bb'; - backBuffer.className = 'olBackBuffer'; - backBuffer.style.position = 'absolute'; - var map = this.map; - backBuffer.style.zIndex = this.transitionEffect === 'resize' ? - this.getZIndex() - 1 : - // 'map-resize': - map.Z_INDEX_BASE.BaseLayer - - (map.getNumLayers() - map.getLayerIndex(this)); - for(var i=0, lenI=this.grid.length; i=0; --i) { - OpenLayers.Event.stopObserving(this._transitionElement, - this.transitionendEvents[i], this._removeBackBuffer); - } - delete this._transitionElement; - } - if(this.backBuffer) { - if (this.backBuffer.parentNode) { - this.backBuffer.parentNode.removeChild(this.backBuffer); - } - this.backBuffer = null; - this.backBufferResolution = null; - if(this.backBufferTimerId !== null) { - window.clearTimeout(this.backBufferTimerId); - this.backBufferTimerId = null; - } - } - }, - - /** - * Method: moveByPx - * Move the layer based on pixel vector. - * - * Parameters: - * dx - {Number} - * dy - {Number} - */ - moveByPx: function(dx, dy) { - if (!this.singleTile) { - this.moveGriddedTiles(); - } - }, - - /** - * APIMethod: setTileSize - * Check if we are in singleTile mode and if so, set the size as a ratio - * of the map size (as specified by the layer's 'ratio' property). - * - * Parameters: - * size - {} - */ - setTileSize: function(size) { - if (this.singleTile) { - size = this.map.getSize(); - size.h = parseInt(size.h * this.ratio, 10); - size.w = parseInt(size.w * this.ratio, 10); - } - OpenLayers.Layer.HTTPRequest.prototype.setTileSize.apply(this, [size]); - }, - - /** - * APIMethod: getTilesBounds - * Return the bounds of the tile grid. - * - * Returns: - * {} A Bounds object representing the bounds of all the - * currently loaded tiles (including those partially or not at all seen - * onscreen). - */ - getTilesBounds: function() { - var bounds = null; - - var length = this.grid.length; - if (length) { - var bottomLeftTileBounds = this.grid[length - 1][0].bounds, - width = this.grid[0].length * bottomLeftTileBounds.getWidth(), - height = this.grid.length * bottomLeftTileBounds.getHeight(); - - bounds = new OpenLayers.Bounds(bottomLeftTileBounds.left, - bottomLeftTileBounds.bottom, - bottomLeftTileBounds.left + width, - bottomLeftTileBounds.bottom + height); - } - return bounds; - }, - - /** - * Method: initSingleTile - * - * Parameters: - * bounds - {} - */ - initSingleTile: function(bounds) { - this.events.triggerEvent("retile"); - - //determine new tile bounds - var center = bounds.getCenterLonLat(); - var tileWidth = bounds.getWidth() * this.ratio; - var tileHeight = bounds.getHeight() * this.ratio; - - var tileBounds = - new OpenLayers.Bounds(center.lon - (tileWidth/2), - center.lat - (tileHeight/2), - center.lon + (tileWidth/2), - center.lat + (tileHeight/2)); - - var px = this.map.getLayerPxFromLonLat({ - lon: tileBounds.left, - lat: tileBounds.top - }); - - if (!this.grid.length) { - this.grid[0] = []; - } - - var tile = this.grid[0][0]; - if (!tile) { - tile = this.addTile(tileBounds, px); - - this.addTileMonitoringHooks(tile); - tile.draw(); - this.grid[0][0] = tile; - } else { - tile.moveTo(tileBounds, px); - } - - //remove all but our single tile - this.removeExcessTiles(1,1); - - // store the resolution of the grid - this.gridResolution = this.getServerResolution(); - }, - - /** - * Method: calculateGridLayout - * Generate parameters for the grid layout. - * - * Parameters: - * bounds - {|Object} OpenLayers.Bounds or an - * object with a 'left' and 'top' properties. - * origin - {|Object} OpenLayers.LonLat or an - * object with a 'lon' and 'lat' properties. - * resolution - {Number} - * - * Returns: - * {Object} Object containing properties tilelon, tilelat, startcol, - * startrow - */ - calculateGridLayout: function(bounds, origin, resolution) { - var tilelon = resolution * this.tileSize.w; - var tilelat = resolution * this.tileSize.h; - - var offsetlon = bounds.left - origin.lon; - var tilecol = Math.floor(offsetlon/tilelon) - this.buffer; - - var rowSign = this.rowSign; - - var offsetlat = rowSign * (origin.lat - bounds.top + tilelat); - var tilerow = Math[~rowSign ? 'floor' : 'ceil'](offsetlat/tilelat) - this.buffer * rowSign; - - return { - tilelon: tilelon, tilelat: tilelat, - startcol: tilecol, startrow: tilerow - }; - - }, - - /** - * Method: getTileOrigin - * Determine the origin for aligning the grid of tiles. If a - * property is supplied, that will be returned. Otherwise, the origin - * will be derived from the layer's property. In this case, - * the tile origin will be the corner of the given by the - * property. - * - * Returns: - * {} The tile origin. - */ - getTileOrigin: function() { - var origin = this.tileOrigin; - if (!origin) { - var extent = this.getMaxExtent(); - var edges = ({ - "tl": ["left", "top"], - "tr": ["right", "top"], - "bl": ["left", "bottom"], - "br": ["right", "bottom"] - })[this.tileOriginCorner]; - origin = new OpenLayers.LonLat(extent[edges[0]], extent[edges[1]]); - } - return origin; - }, - - /** - * Method: getTileBoundsForGridIndex - * - * Parameters: - * row - {Number} The row of the grid - * col - {Number} The column of the grid - * - * Returns: - * {} The bounds for the tile at (row, col) - */ - getTileBoundsForGridIndex: function(row, col) { - var origin = this.getTileOrigin(); - var tileLayout = this.gridLayout; - var tilelon = tileLayout.tilelon; - var tilelat = tileLayout.tilelat; - var startcol = tileLayout.startcol; - var startrow = tileLayout.startrow; - var rowSign = this.rowSign; - return new OpenLayers.Bounds( - origin.lon + (startcol + col) * tilelon, - origin.lat - (startrow + row * rowSign) * tilelat * rowSign, - origin.lon + (startcol + col + 1) * tilelon, - origin.lat - (startrow + (row - 1) * rowSign) * tilelat * rowSign - ); - }, - - /** - * Method: initGriddedTiles - * - * Parameters: - * bounds - {} - */ - initGriddedTiles:function(bounds) { - this.events.triggerEvent("retile"); - - // work out mininum number of rows and columns; this is the number of - // tiles required to cover the viewport plus at least one for panning - - var viewSize = this.map.getSize(); - - var origin = this.getTileOrigin(); - var resolution = this.map.getResolution(), - serverResolution = this.getServerResolution(), - ratio = resolution / serverResolution, - tileSize = { - w: this.tileSize.w / ratio, - h: this.tileSize.h / ratio - }; - - var minRows = Math.ceil(viewSize.h/tileSize.h) + - 2 * this.buffer + 1; - var minCols = Math.ceil(viewSize.w/tileSize.w) + - 2 * this.buffer + 1; - - var tileLayout = this.calculateGridLayout(bounds, origin, serverResolution); - this.gridLayout = tileLayout; - - var tilelon = tileLayout.tilelon; - var tilelat = tileLayout.tilelat; - - var layerContainerDivLeft = this.map.layerContainerOriginPx.x; - var layerContainerDivTop = this.map.layerContainerOriginPx.y; - - var tileBounds = this.getTileBoundsForGridIndex(0, 0); - var startPx = this.map.getViewPortPxFromLonLat( - new OpenLayers.LonLat(tileBounds.left, tileBounds.top) - ); - startPx.x = Math.round(startPx.x) - layerContainerDivLeft; - startPx.y = Math.round(startPx.y) - layerContainerDivTop; - - var tileData = [], center = this.map.getCenter(); - - var rowidx = 0; - do { - var row = this.grid[rowidx]; - if (!row) { - row = []; - this.grid.push(row); - } - - var colidx = 0; - do { - tileBounds = this.getTileBoundsForGridIndex(rowidx, colidx); - var px = startPx.clone(); - px.x = px.x + colidx * Math.round(tileSize.w); - px.y = px.y + rowidx * Math.round(tileSize.h); - var tile = row[colidx]; - if (!tile) { - tile = this.addTile(tileBounds, px); - this.addTileMonitoringHooks(tile); - row.push(tile); - } else { - tile.moveTo(tileBounds, px, false); - } - var tileCenter = tileBounds.getCenterLonLat(); - tileData.push({ - tile: tile, - distance: Math.pow(tileCenter.lon - center.lon, 2) + - Math.pow(tileCenter.lat - center.lat, 2) - }); - - colidx += 1; - } while ((tileBounds.right <= bounds.right + tilelon * this.buffer) - || colidx < minCols); - - rowidx += 1; - } while((tileBounds.bottom >= bounds.bottom - tilelat * this.buffer) - || rowidx < minRows); - - //shave off exceess rows and colums - this.removeExcessTiles(rowidx, colidx); - - var resolution = this.getServerResolution(); - // store the resolution of the grid - this.gridResolution = resolution; - - //now actually draw the tiles - tileData.sort(function(a, b) { - return a.distance - b.distance; - }); - for (var i=0, ii=tileData.length; i} - */ - getMaxExtent: function() { - return this.maxExtent; - }, - - /** - * APIMethod: addTile - * Create a tile, initialize it, and add it to the layer div. - * - * Parameters - * bounds - {} - * position - {} - * - * Returns: - * {} The added OpenLayers.Tile - */ - addTile: function(bounds, position) { - var tile = new this.tileClass( - this, position, bounds, null, this.tileSize, this.tileOptions - ); - this.events.triggerEvent("addtile", {tile: tile}); - return tile; - }, - - /** - * Method: addTileMonitoringHooks - * This function takes a tile as input and adds the appropriate hooks to - * the tile so that the layer can keep track of the loading tiles. - * - * Parameters: - * tile - {} - */ - addTileMonitoringHooks: function(tile) { - - var replacingCls = 'olTileReplacing'; - - tile.onLoadStart = function() { - //if that was first tile then trigger a 'loadstart' on the layer - if (this.loading === false) { - this.loading = true; - this.events.triggerEvent("loadstart"); - } - this.events.triggerEvent("tileloadstart", {tile: tile}); - this.numLoadingTiles++; - if (!this.singleTile && this.backBuffer && this.gridResolution === this.backBufferResolution) { - OpenLayers.Element.addClass(tile.getTile(), replacingCls); - } - }; - - tile.onLoadEnd = function(evt) { - this.numLoadingTiles--; - var aborted = evt.type === 'unload'; - this.events.triggerEvent("tileloaded", { - tile: tile, - aborted: aborted - }); - if (!this.singleTile && !aborted && this.backBuffer && this.gridResolution === this.backBufferResolution) { - var tileDiv = tile.getTile(); - if (OpenLayers.Element.getStyle(tileDiv, 'display') === 'none') { - var bufferTile = document.getElementById(tile.id + '_bb'); - if (bufferTile) { - bufferTile.parentNode.removeChild(bufferTile); - } - } - OpenLayers.Element.removeClass(tileDiv, replacingCls); - } - //if that was the last tile, then trigger a 'loadend' on the layer - if (this.numLoadingTiles === 0) { - if (this.backBuffer) { - if (this.backBuffer.childNodes.length === 0) { - // no tiles transitioning, remove immediately - this.removeBackBuffer(); - } else { - // wait until transition has ended or delay has passed - this._transitionElement = aborted ? - this.div.lastChild : tile.imgDiv; - var transitionendEvents = this.transitionendEvents; - for (var i=transitionendEvents.length-1; i>=0; --i) { - OpenLayers.Event.observe(this._transitionElement, - transitionendEvents[i], - this._removeBackBuffer); - } - // the removal of the back buffer is delayed to prevent - // flash effects due to the animation of tile displaying - this.backBufferTimerId = window.setTimeout( - this._removeBackBuffer, this.removeBackBufferDelay - ); - } - } - this.loading = false; - this.events.triggerEvent("loadend"); - } - }; - - tile.onLoadError = function() { - this.events.triggerEvent("tileerror", {tile: tile}); - }; - - tile.events.on({ - "loadstart": tile.onLoadStart, - "loadend": tile.onLoadEnd, - "unload": tile.onLoadEnd, - "loaderror": tile.onLoadError, - scope: this - }); - }, - - /** - * Method: removeTileMonitoringHooks - * This function takes a tile as input and removes the tile hooks - * that were added in addTileMonitoringHooks() - * - * Parameters: - * tile - {} - */ - removeTileMonitoringHooks: function(tile) { - tile.unload(); - tile.events.un({ - "loadstart": tile.onLoadStart, - "loadend": tile.onLoadEnd, - "unload": tile.onLoadEnd, - "loaderror": tile.onLoadError, - scope: this - }); - }, - - /** - * Method: moveGriddedTiles - */ - moveGriddedTiles: function() { - var buffer = this.buffer + 1; - while(true) { - var tlTile = this.grid[0][0]; - var tlViewPort = { - x: tlTile.position.x + - this.map.layerContainerOriginPx.x, - y: tlTile.position.y + - this.map.layerContainerOriginPx.y - }; - var ratio = this.getServerResolution() / this.map.getResolution(); - var tileSize = { - w: Math.round(this.tileSize.w * ratio), - h: Math.round(this.tileSize.h * ratio) - }; - if (tlViewPort.x > -tileSize.w * (buffer - 1)) { - this.shiftColumn(true, tileSize); - } else if (tlViewPort.x < -tileSize.w * buffer) { - this.shiftColumn(false, tileSize); - } else if (tlViewPort.y > -tileSize.h * (buffer - 1)) { - this.shiftRow(true, tileSize); - } else if (tlViewPort.y < -tileSize.h * buffer) { - this.shiftRow(false, tileSize); - } else { - break; - } - } - }, - - /** - * Method: shiftRow - * Shifty grid work - * - * Parameters: - * prepend - {Boolean} if true, prepend to beginning. - * if false, then append to end - * tileSize - {Object} rendered tile size; object with w and h properties - */ - shiftRow: function(prepend, tileSize) { - var grid = this.grid; - var rowIndex = prepend ? 0 : (grid.length - 1); - var sign = prepend ? -1 : 1; - var rowSign = this.rowSign; - var tileLayout = this.gridLayout; - tileLayout.startrow += sign * rowSign; - - var modelRow = grid[rowIndex]; - var row = grid[prepend ? 'pop' : 'shift'](); - for (var i=0, len=row.length; i rows) { - var row = this.grid.pop(); - for (i=0, l=row.length; i 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/Layer/XYZ.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/Layer/Grid.js - */ - -/** - * Class: OpenLayers.Layer.XYZ - * The XYZ class is designed to make it easier for people who have tiles - * arranged by a standard XYZ grid. - * - * Inherits from: - * - - */ -OpenLayers.Layer.XYZ = OpenLayers.Class(OpenLayers.Layer.Grid, { - - /** - * APIProperty: isBaseLayer - * Default is true, as this is designed to be a base tile source. - */ - isBaseLayer: true, - - /** - * APIProperty: sphericalMercator - * Whether the tile extents should be set to the defaults for - * spherical mercator. Useful for things like OpenStreetMap. - * Default is false, except for the OSM subclass. - */ - sphericalMercator: false, - - /** - * APIProperty: zoomOffset - * {Number} If your cache has more zoom levels than you want to provide - * access to with this layer, supply a zoomOffset. This zoom offset - * is added to the current map zoom level to determine the level - * for a requested tile. For example, if you supply a zoomOffset - * of 3, when the map is at the zoom 0, tiles will be requested from - * level 3 of your cache. Default is 0 (assumes cache level and map - * zoom are equivalent). Using is an alternative to - * setting if you only want to expose a subset - * of the server resolutions. - */ - zoomOffset: 0, - - /** - * APIProperty: serverResolutions - * {Array} A list of all resolutions available on the server. Only set this - * property if the map resolutions differ from the server. This - * property serves two purposes. (a) can include - * resolutions that the server supports and that you don't want to - * provide with this layer; you can also look at , which is - * an alternative to for that specific purpose. - * (b) The map can work with resolutions that aren't supported by - * the server, i.e. that aren't in . When the - * map is displayed in such a resolution data for the closest - * server-supported resolution is loaded and the layer div is - * stretched as necessary. - */ - serverResolutions: null, - - /** - * Constructor: OpenLayers.Layer.XYZ - * - * Parameters: - * name - {String} - * url - {String} - * options - {Object} Hashtable of extra options to tag onto the layer - */ - initialize: function(name, url, options) { - if (options && options.sphericalMercator || this.sphericalMercator) { - options = OpenLayers.Util.extend({ - projection: "EPSG:900913", - numZoomLevels: 19 - }, options); - } - OpenLayers.Layer.Grid.prototype.initialize.apply(this, [ - name || this.name, url || this.url, {}, options - ]); - }, - - /** - * APIMethod: clone - * Create a clone of this layer - * - * Parameters: - * obj - {Object} Is this ever used? - * - * Returns: - * {} An exact clone of this OpenLayers.Layer.XYZ - */ - clone: function (obj) { - - if (obj == null) { - obj = new OpenLayers.Layer.XYZ(this.name, - this.url, - this.getOptions()); - } - - //get all additions from superclasses - obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]); - - return obj; - }, - - /** - * Method: getURL - * - * Parameters: - * bounds - {} - * - * Returns: - * {String} A string with the layer's url and parameters and also the - * passed-in bounds and appropriate tile size specified as - * parameters - */ - getURL: function (bounds) { - var xyz = this.getXYZ(bounds); - var url = this.url; - if (OpenLayers.Util.isArray(url)) { - var s = '' + xyz.x + xyz.y + xyz.z; - url = this.selectUrl(s, url); - } - - return OpenLayers.String.format(url, xyz); - }, - - /** - * Method: getXYZ - * Calculates x, y and z for the given bounds. - * - * Parameters: - * bounds - {} - * - * Returns: - * {Object} - an object with x, y and z properties. - */ - getXYZ: function(bounds) { - var res = this.getServerResolution(); - var x = Math.round((bounds.left - this.maxExtent.left) / - (res * this.tileSize.w)); - var y = Math.round((this.maxExtent.top - bounds.top) / - (res * this.tileSize.h)); - var z = this.getServerZoom(); - - if (this.wrapDateLine) { - var limit = Math.pow(2, z); - x = ((x % limit) + limit) % limit; - } - - return {'x': x, 'y': y, 'z': z}; - }, - - /* APIMethod: setMap - * When the layer is added to a map, then we can fetch our origin - * (if we don't have one.) - * - * Parameters: - * map - {} - */ - setMap: function(map) { - OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments); - if (!this.tileOrigin) { - this.tileOrigin = new OpenLayers.LonLat(this.maxExtent.left, - this.maxExtent.bottom); - } - }, - - CLASS_NAME: "OpenLayers.Layer.XYZ" -}); -/* ====================================================================== - OpenLayers/Layer/OSM.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/Layer/XYZ.js - */ - -/** - * Class: OpenLayers.Layer.OSM - * This layer allows accessing OpenStreetMap tiles. By default the OpenStreetMap - * hosted tile.openstreetmap.org Mapnik tileset is used. If you wish to use - * a different layer instead, you need to provide a different - * URL to the constructor. Here's an example for using OpenCycleMap: - * - * (code) - * new OpenLayers.Layer.OSM("OpenCycleMap", - * ["http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", - * "http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", - * "http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png"]); - * (end) - * - * Inherits from: - * - - */ -OpenLayers.Layer.OSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { - - /** - * APIProperty: name - * {String} The layer name. Defaults to "OpenStreetMap" if the first - * argument to the constructor is null or undefined. - */ - name: "OpenStreetMap", - - /** - * APIProperty: url - * {String} The tileset URL scheme. Defaults to - * : http://[a|b|c].tile.openstreetmap.org/${z}/${x}/${y}.png - * (the official OSM tileset) if the second argument to the constructor - * is null or undefined. To use another tileset you can have something - * like this: - * (code) - * new OpenLayers.Layer.OSM("OpenCycleMap", - * ["http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", - * "http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", - * "http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png"]); - * (end) - */ - url: [ - 'http://a.tile.openstreetmap.org/${z}/${x}/${y}.png', - 'http://b.tile.openstreetmap.org/${z}/${x}/${y}.png', - 'http://c.tile.openstreetmap.org/${z}/${x}/${y}.png' - ], - - /** - * Property: attribution - * {String} The layer attribution. - */ - attribution: "© OpenStreetMap contributors", - - /** - * Property: sphericalMercator - * {Boolean} - */ - sphericalMercator: true, - - /** - * Property: wrapDateLine - * {Boolean} - */ - wrapDateLine: true, - - /** APIProperty: tileOptions - * {Object} optional configuration options for instances - * created by this Layer. Default is - * - * (code) - * {crossOriginKeyword: 'anonymous'} - * (end) - * - * When using OSM tilesets other than the default ones, it may be - * necessary to set this to - * - * (code) - * {crossOriginKeyword: null} - * (end) - * - * if the server does not send Access-Control-Allow-Origin headers. - */ - tileOptions: null, - - /** - * Constructor: OpenLayers.Layer.OSM - * - * Parameters: - * name - {String} The layer name. - * url - {String} The tileset URL scheme. - * options - {Object} Configuration options for the layer. Any inherited - * layer option can be set in this object (e.g. - * ). - */ - initialize: function(name, url, options) { - OpenLayers.Layer.XYZ.prototype.initialize.apply(this, arguments); - this.tileOptions = OpenLayers.Util.extend({ - crossOriginKeyword: 'anonymous' - }, this.options && this.options.tileOptions); - }, - - /** - * Method: clone - */ - clone: function(obj) { - if (obj == null) { - obj = new OpenLayers.Layer.OSM( - this.name, this.url, this.getOptions()); - } - obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]); - return obj; - }, - - CLASS_NAME: "OpenLayers.Layer.OSM" -}); -/* ====================================================================== - 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; - } - }, - - /** - * 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} - * 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 - * - * Parameters: - * symbolizer - {Object} - * - * Returns: - * {Object} - */ - 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.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/Renderer/Canvas.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/Renderer.js - */ - -/** - * Class: OpenLayers.Renderer.Canvas - * A renderer based on the 2D 'canvas' drawing element. - * - * Inherits: - * - - */ -OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, { - - /** - * APIProperty: hitDetection - * {Boolean} Allow for hit detection of features. Default is true. - */ - hitDetection: true, - - /** - * Property: hitOverflow - * {Number} The method for converting feature identifiers to color values - * supports 16777215 sequential values. Two features cannot be - * predictably detected if their identifiers differ by more than this - * value. The hitOverflow allows for bigger numbers (but the - * difference in values is still limited). - */ - hitOverflow: 0, - - /** - * Property: canvas - * {Canvas} The canvas context object. - */ - canvas: null, - - /** - * Property: features - * {Object} Internal object of feature/style pairs for use in redrawing the layer. - */ - features: null, - - /** - * Property: pendingRedraw - * {Boolean} The renderer needs a redraw call to render features added while - * the renderer was locked. - */ - pendingRedraw: false, - - /** - * Property: cachedSymbolBounds - * {Object} Internal cache of calculated symbol extents. - */ - cachedSymbolBounds: {}, - - /** - * Constructor: OpenLayers.Renderer.Canvas - * - * Parameters: - * containerID - {} - * options - {Object} Optional properties to be set on the renderer. - */ - initialize: function(containerID, options) { - OpenLayers.Renderer.prototype.initialize.apply(this, arguments); - this.root = document.createElement("canvas"); - this.container.appendChild(this.root); - this.canvas = this.root.getContext("2d"); - this.features = {}; - if (this.hitDetection) { - this.hitCanvas = document.createElement("canvas"); - this.hitContext = this.hitCanvas.getContext("2d"); - } - }, - - /** - * Method: setExtent - * Set the visible part of the layer. - * - * 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() { - OpenLayers.Renderer.prototype.setExtent.apply(this, arguments); - // always redraw features - return false; - }, - - /** - * Method: eraseGeometry - * Erase a geometry from the renderer. Because the Canvas renderer has - * 'memory' of the features that it has drawn, we have to remove the - * feature so it doesn't redraw. - * - * Parameters: - * geometry - {} - * featureId - {String} - */ - eraseGeometry: function(geometry, featureId) { - this.eraseFeatures(this.features[featureId][0]); - }, - - /** - * APIMethod: supported - * - * Returns: - * {Boolean} Whether or not the browser supports the renderer class - */ - supported: function() { - return OpenLayers.CANVAS_SUPPORTED; - }, - - /** - * Method: setSize - * Sets the size of the drawing surface. - * - * Once the size is updated, redraw the canvas. - * - * Parameters: - * size - {} - */ - setSize: function(size) { - this.size = size.clone(); - var root = this.root; - root.style.width = size.w + "px"; - root.style.height = size.h + "px"; - root.width = size.w; - root.height = size.h; - this.resolution = null; - if (this.hitDetection) { - var hitCanvas = this.hitCanvas; - hitCanvas.style.width = size.w + "px"; - hitCanvas.style.height = size.h + "px"; - hitCanvas.width = size.w; - hitCanvas.height = size.h; - } - }, - - /** - * Method: drawFeature - * Draw the feature. Stores the feature in the features list, - * then redraws the layer. - * - * Parameters: - * feature - {} - * style - {} - * - * Returns: - * {Boolean} The feature has been drawn completely. If the feature has no - * geometry, undefined will be returned. If the feature is not rendered - * for other reasons, false will be returned. - */ - drawFeature: function(feature, style) { - var rendered; - if (feature.geometry) { - style = this.applyDefaultSymbolizer(style || feature.style); - // don't render if display none or feature outside extent - var bounds = feature.geometry.getBounds(); - - var worldBounds; - if (this.map.baseLayer && this.map.baseLayer.wrapDateLine) { - worldBounds = this.map.getMaxExtent(); - } - - var intersects = bounds && bounds.intersectsBounds(this.extent, {worldBounds: worldBounds}); - - rendered = (style.display !== "none") && !!bounds && intersects; - if (rendered) { - // keep track of what we have rendered for redraw - this.features[feature.id] = [feature, style]; - } - else { - // remove from features tracked for redraw - delete(this.features[feature.id]); - } - this.pendingRedraw = true; - } - if (this.pendingRedraw && !this.locked) { - this.redraw(); - this.pendingRedraw = false; - } - return rendered; - }, - - /** - * Method: drawGeometry - * Used when looping (in redraw) over the features; draws - * the canvas. - * - * Parameters: - * geometry - {} - * style - {Object} - */ - drawGeometry: function(geometry, style, featureId) { - var className = geometry.CLASS_NAME; - if ((className == "OpenLayers.Geometry.Collection") || - (className == "OpenLayers.Geometry.MultiPoint") || - (className == "OpenLayers.Geometry.MultiLineString") || - (className == "OpenLayers.Geometry.MultiPolygon")) { - for (var i = 0; i < geometry.components.length; i++) { - this.drawGeometry(geometry.components[i], style, featureId); - } - return; - } - switch (geometry.CLASS_NAME) { - case "OpenLayers.Geometry.Point": - this.drawPoint(geometry, style, featureId); - break; - case "OpenLayers.Geometry.LineString": - this.drawLineString(geometry, style, featureId); - break; - case "OpenLayers.Geometry.LinearRing": - this.drawLinearRing(geometry, style, featureId); - break; - case "OpenLayers.Geometry.Polygon": - this.drawPolygon(geometry, style, featureId); - break; - default: - break; - } - }, - - /** - * Method: drawExternalGraphic - * Called to draw External graphics. - * - * Parameters: - * geometry - {} - * style - {Object} - * featureId - {String} - */ - drawExternalGraphic: function(geometry, style, featureId) { - var img = new Image(); - - var title = style.title || style.graphicTitle; - if (title) { - img.title = title; - } - - var width = style.graphicWidth || style.graphicHeight; - var height = style.graphicHeight || style.graphicWidth; - width = width ? width : style.pointRadius * 2; - height = height ? height : style.pointRadius * 2; - var xOffset = (style.graphicXOffset != undefined) ? - style.graphicXOffset : -(0.5 * width); - var yOffset = (style.graphicYOffset != undefined) ? - style.graphicYOffset : -(0.5 * height); - - var opacity = style.graphicOpacity || style.fillOpacity; - - var onLoad = function() { - if(!this.features[featureId]) { - return; - } - var pt = this.getLocalXY(geometry); - var p0 = pt[0]; - var p1 = pt[1]; - if(!isNaN(p0) && !isNaN(p1)) { - var x = (p0 + xOffset) | 0; - var y = (p1 + yOffset) | 0; - var canvas = this.canvas; - canvas.globalAlpha = opacity; - var factor = OpenLayers.Renderer.Canvas.drawImageScaleFactor || - (OpenLayers.Renderer.Canvas.drawImageScaleFactor = - /android 2.1/.test(navigator.userAgent.toLowerCase()) ? - // 320 is the screen width of the G1 phone, for - // which drawImage works out of the box. - 320 / window.screen.width : 1 - ); - canvas.drawImage( - img, x*factor, y*factor, width*factor, height*factor - ); - if (this.hitDetection) { - this.setHitContextStyle("fill", featureId); - this.hitContext.fillRect(x, y, width, height); - } - } - }; - - img.onload = OpenLayers.Function.bind(onLoad, this); - img.src = style.externalGraphic; - }, - - /** - * Method: drawNamedSymbol - * Called to draw Well Known Graphic Symbol Name. - * This method is only called by the renderer itself. - * - * Parameters: - * geometry - {} - * style - {Object} - * featureId - {String} - */ - drawNamedSymbol: function(geometry, style, featureId) { - var x, y, cx, cy, i, symbolBounds, scaling, angle; - var unscaledStrokeWidth; - var deg2rad = Math.PI / 180.0; - - var symbol = OpenLayers.Renderer.symbol[style.graphicName]; - - if (!symbol) { - throw new Error(style.graphicName + ' is not a valid symbol name'); - } - - if (!symbol.length || symbol.length < 2) return; - - var pt = this.getLocalXY(geometry); - var p0 = pt[0]; - var p1 = pt[1]; - - if (isNaN(p0) || isNaN(p1)) return; - - // Use rounded line caps - this.canvas.lineCap = "round"; - this.canvas.lineJoin = "round"; - - if (this.hitDetection) { - this.hitContext.lineCap = "round"; - this.hitContext.lineJoin = "round"; - } - - // Scale and rotate symbols, using precalculated bounds whenever possible. - if (style.graphicName in this.cachedSymbolBounds) { - symbolBounds = this.cachedSymbolBounds[style.graphicName]; - } else { - symbolBounds = new OpenLayers.Bounds(); - for(i = 0; i < symbol.length; i+=2) { - symbolBounds.extend(new OpenLayers.LonLat(symbol[i], symbol[i+1])); - } - this.cachedSymbolBounds[style.graphicName] = symbolBounds; - } - - // Push symbol scaling, translation and rotation onto the transformation stack in reverse order. - // Don't forget to apply all canvas transformations to the hitContext canvas as well(!) - this.canvas.save(); - if (this.hitDetection) { this.hitContext.save(); } - - // Step 3: place symbol at the desired location - this.canvas.translate(p0,p1); - if (this.hitDetection) { this.hitContext.translate(p0,p1); } - - // Step 2a. rotate the symbol if necessary - angle = deg2rad * style.rotation; // will be NaN when style.rotation is undefined. - if (!isNaN(angle)) { - this.canvas.rotate(angle); - if (this.hitDetection) { this.hitContext.rotate(angle); } - } - - // // Step 2: scale symbol such that pointRadius equals half the maximum symbol dimension. - scaling = 2.0 * style.pointRadius / Math.max(symbolBounds.getWidth(), symbolBounds.getHeight()); - this.canvas.scale(scaling,scaling); - if (this.hitDetection) { this.hitContext.scale(scaling,scaling); } - - // Step 1: center the symbol at the origin - cx = symbolBounds.getCenterLonLat().lon; - cy = symbolBounds.getCenterLonLat().lat; - this.canvas.translate(-cx,-cy); - if (this.hitDetection) { this.hitContext.translate(-cx,-cy); } - - // Don't forget to scale stroke widths, because they are affected by canvas scale transformations as well(!) - // Alternative: scale symbol coordinates manually, so stroke width scaling is not needed anymore. - unscaledStrokeWidth = style.strokeWidth; - style.strokeWidth = unscaledStrokeWidth / scaling; - - if (style.fill !== false) { - this.setCanvasStyle("fill", style); - this.canvas.beginPath(); - for (i=0; i= 16777216) { - this.hitOverflow = id - 16777215; - id = id % 16777216 + 1; - } - var hex = "000000" + id.toString(16); - var len = hex.length; - hex = "#" + hex.substring(len-6, len); - return hex; - }, - - /** - * Method: setHitContextStyle - * Prepare the hit canvas for drawing by setting various global settings. - * - * Parameters: - * type - {String} one of 'stroke', 'fill', or 'reset' - * featureId - {String} The feature id. - * symbolizer - {} The symbolizer. - */ - setHitContextStyle: function(type, featureId, symbolizer, strokeScaling) { - var hex = this.featureIdToHex(featureId); - if (type == "fill") { - this.hitContext.globalAlpha = 1.0; - this.hitContext.fillStyle = hex; - } else if (type == "stroke") { - this.hitContext.globalAlpha = 1.0; - this.hitContext.strokeStyle = hex; - // bump up stroke width to deal with antialiasing. If strokeScaling is defined, we're rendering a symbol - // on a transformed canvas, so the antialias width bump has to scale as well. - if (typeof strokeScaling === "undefined") { - this.hitContext.lineWidth = symbolizer.strokeWidth + 2; - } else { - if (!isNaN(strokeScaling)) { this.hitContext.lineWidth = symbolizer.strokeWidth + 2.0 / strokeScaling; } - } - } else { - this.hitContext.globalAlpha = 0; - this.hitContext.lineWidth = 1; - } - }, - - /** - * Method: drawPoint - * This method is only called by the renderer itself. - * - * Parameters: - * geometry - {} - * style - {Object} - * featureId - {String} - */ - drawPoint: function(geometry, style, featureId) { - if(style.graphic !== false) { - if(style.externalGraphic) { - this.drawExternalGraphic(geometry, style, featureId); - } else if (style.graphicName && (style.graphicName != "circle")) { - this.drawNamedSymbol(geometry, style, featureId); - } else { - var pt = this.getLocalXY(geometry); - var p0 = pt[0]; - var p1 = pt[1]; - if(!isNaN(p0) && !isNaN(p1)) { - var twoPi = Math.PI*2; - var radius = style.pointRadius; - if(style.fill !== false) { - this.setCanvasStyle("fill", style); - this.canvas.beginPath(); - this.canvas.arc(p0, p1, radius, 0, twoPi, true); - this.canvas.fill(); - if (this.hitDetection) { - this.setHitContextStyle("fill", featureId, style); - this.hitContext.beginPath(); - this.hitContext.arc(p0, p1, radius, 0, twoPi, true); - this.hitContext.fill(); - } - } - - if(style.stroke !== false) { - this.setCanvasStyle("stroke", style); - this.canvas.beginPath(); - this.canvas.arc(p0, p1, radius, 0, twoPi, true); - this.canvas.stroke(); - if (this.hitDetection) { - this.setHitContextStyle("stroke", featureId, style); - this.hitContext.beginPath(); - this.hitContext.arc(p0, p1, radius, 0, twoPi, true); - this.hitContext.stroke(); - } - this.setCanvasStyle("reset"); - } - } - } - } - }, - - /** - * Method: drawLineString - * This method is only called by the renderer itself. - * - * Parameters: - * geometry - {} - * style - {Object} - * featureId - {String} - */ - drawLineString: function(geometry, style, featureId) { - style = OpenLayers.Util.applyDefaults({fill: false}, style); - this.drawLinearRing(geometry, style, featureId); - }, - - /** - * Method: drawLinearRing - * This method is only called by the renderer itself. - * - * Parameters: - * geometry - {} - * style - {Object} - * featureId - {String} - */ - drawLinearRing: function(geometry, style, featureId) { - if (style.fill !== false) { - this.setCanvasStyle("fill", style); - this.renderPath(this.canvas, geometry, style, featureId, "fill"); - if (this.hitDetection) { - this.setHitContextStyle("fill", featureId, style); - this.renderPath(this.hitContext, geometry, style, featureId, "fill"); - } - } - if (style.stroke !== false) { - this.setCanvasStyle("stroke", style); - this.renderPath(this.canvas, geometry, style, featureId, "stroke"); - if (this.hitDetection) { - this.setHitContextStyle("stroke", featureId, style); - this.renderPath(this.hitContext, geometry, style, featureId, "stroke"); - } - } - this.setCanvasStyle("reset"); - }, - - /** - * Method: renderPath - * Render a path with stroke and optional fill. - */ - renderPath: function(context, geometry, style, featureId, type) { - var components = geometry.components; - var len = components.length; - context.beginPath(); - var start = this.getLocalXY(components[0]); - var x = start[0]; - var y = start[1]; - if (!isNaN(x) && !isNaN(y)) { - context.moveTo(start[0], start[1]); - for (var i=1; i} - * style - {Object} - * featureId - {String} - */ - drawPolygon: function(geometry, style, featureId) { - var components = geometry.components; - var len = components.length; - this.drawLinearRing(components[0], style, featureId); - // erase inner rings - for (var i=1; i} - * style - {Object} - */ - drawText: function(location, style) { - var pt = this.getLocalXY(location); - - this.setCanvasStyle("reset"); - this.canvas.fillStyle = style.fontColor; - this.canvas.globalAlpha = style.fontOpacity || 1.0; - var fontStyle = [style.fontStyle ? style.fontStyle : "normal", - "normal", // "font-variant" not supported - style.fontWeight ? style.fontWeight : "normal", - style.fontSize ? style.fontSize : "1em", - style.fontFamily ? style.fontFamily : "sans-serif"].join(" "); - var labelRows = style.label.split('\n'); - var numRows = labelRows.length; - if (this.canvas.fillText) { - // HTML5 - this.canvas.font = fontStyle; - this.canvas.textAlign = - OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[0]] || - "center"; - this.canvas.textBaseline = - OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[1]] || - "middle"; - var vfactor = - OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]]; - if (vfactor == null) { - vfactor = -.5; - } - var lineHeight = - this.canvas.measureText('Mg').height || - this.canvas.measureText('xx').width; - pt[1] += lineHeight*vfactor*(numRows-1); - for (var i = 0; i < numRows; i++) { - if (style.labelOutlineWidth) { - this.canvas.save(); - this.canvas.globalAlpha = style.labelOutlineOpacity || style.fontOpacity || 1.0; - this.canvas.strokeStyle = style.labelOutlineColor; - this.canvas.lineWidth = style.labelOutlineWidth; - this.canvas.strokeText(labelRows[i], pt[0], pt[1] + (lineHeight*i) + 1); - this.canvas.restore(); - } - this.canvas.fillText(labelRows[i], pt[0], pt[1] + (lineHeight*i)); - } - } else if (this.canvas.mozDrawText) { - // Mozilla pre-Gecko1.9.1 (} - */ - getLocalXY: function(point) { - var resolution = this.getResolution(); - var extent = this.extent; - var x = ((point.x - this.featureDx) / resolution + (-extent.left / resolution)); - var y = ((extent.top / resolution) - point.y / resolution); - return [x, y]; - }, - - /** - * Method: clear - * Clear all vectors from the renderer. - */ - clear: function() { - var height = this.root.height; - var width = this.root.width; - this.canvas.clearRect(0, 0, width, height); - this.features = {}; - if (this.hitDetection) { - this.hitContext.clearRect(0, 0, width, height); - } - }, - - /** - * Method: getFeatureIdFromEvent - * Returns a feature id from an event on the renderer. - * - * Parameters: - * evt - {} - * - * Returns: - * {)} - */ - eraseFeatures: function(features) { - if(!(OpenLayers.Util.isArray(features))) { - features = [features]; - } - for(var i=0; i}. 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 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, 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/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/Handler.js - */ - -/** - * 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.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, - - /** - * Property: stopDown - * {Boolean} Stop propagation of mousedown events from getting to listeners - * on the same element. Default is true. - */ - 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, - - /** - * Property: lastMoveEvt - * {Object} The last mousemove event that occurred. Used to - * position the map correctly when our "delay drag" - * timeout expired. - */ - lastMoveEvt: null, - - /** - * Property: oldOnselectstart - * {Function} - */ - oldOnselectstart: null, - - /** - * 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. - */ - interval: 0, - - /** - * 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: - * 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}}); - }; - } - }, - - - /** - * Method: dragstart - * This private method is factorized from mousedown and touchstart methods - * - * Parameters: - * evt - {Event} The event - * - * Returns: - * {Boolean} Let the event propagate. - */ - 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 { - this.started = false; - this.start = null; - this.last = null; - } - return propagate; - }, - - /** - * Method: dragmove - * This private method is factorized from mousemove and touchmove methods - * - * Parameters: - * evt - {Event} The event - * - * Returns: - * {Boolean} Let the event propagate. - */ - 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 true; - }, - - /** - * Method: dragend - * This private method is factorized from mouseup and touchend methods - * - * Parameters: - * evt - {Event} The event - * - * Returns: - * {Boolean} Let the event propagate. - */ - 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; - }, - - /** - * The four methods below (down, move, up, and out) are used by subclasses - * to do their own processing related to these mouse events. - */ - - /** - * 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 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; - }, - - /** - * 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 deactivated; - }, - - /** - * 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: - * evt - {Object} - */ - adjustXY: function(evt) { - var pos = OpenLayers.Util.pagePosition(this.map.viewPortDiv); - evt.xy.x -= pos[0]; - evt.xy.y -= pos[1]; - }, - - /** - * 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/Keyboard.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/Events.js - */ - -/** - * Class: OpenLayers.handler.Keyboard - * A handler for keyboard events. Create a new instance with the - * constructor. - * - * Inherits from: - * - - */ -OpenLayers.Handler.Keyboard = OpenLayers.Class(OpenLayers.Handler, { - - /* http://www.quirksmode.org/js/keys.html explains key x-browser - key handling quirks in pretty nice detail */ - - /** - * Constant: KEY_EVENTS - * keydown, keypress, keyup - */ - KEY_EVENTS: ["keydown", "keyup"], - - /** - * Property: eventListener - * {Function} - */ - eventListener: null, - - /** - * Property: observeElement - * {DOMElement|String} The DOM element on which we listen for - * key events. Default to the document. - */ - observeElement: null, - - /** - * Constructor: OpenLayers.Handler.Keyboard - * Returns a new keyboard handler. - * - * Parameters: - * 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 'keydown', 'keypress', and 'keyup' are supported. - * options - {Object} Optional object whose properties will be set on the - * handler. - */ - initialize: function(control, callbacks, options) { - OpenLayers.Handler.prototype.initialize.apply(this, arguments); - // cache the bound event listener method so it can be unobserved later - this.eventListener = OpenLayers.Function.bindAsEventListener( - this.handleKeyEvent, this - ); - }, - - /** - * Method: destroy - */ - destroy: function() { - this.deactivate(); - this.eventListener = null; - OpenLayers.Handler.prototype.destroy.apply(this, arguments); - }, - - /** - * Method: activate - */ - activate: function() { - if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) { - this.observeElement = this.observeElement || document; - for (var i=0, len=this.KEY_EVENTS.length; i constructor. - * - * Inherits From: - * - - */ -OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, { - - /** - * APIProperty: documentDrag - * {Boolean} If set to true, dragging vertices will continue even if the - * mouse cursor leaves the map viewport. Default is false. - */ - documentDrag: false, - - /** - * APIProperty: geometryTypes - * {Array(String)} To restrict modification to a limited set of geometry - * types, send a list of strings corresponding to the geometry class - * names. - */ - geometryTypes: null, - - /** - * APIProperty: clickout - * {Boolean} Unselect features when clicking outside any feature. - * Default is true. - */ - clickout: true, - - /** - * APIProperty: toggle - * {Boolean} Unselect a selected feature on click. - * Default is true. - */ - toggle: true, - - /** - * APIProperty: standalone - * {Boolean} Set to true to create a control without SelectFeature - * capabilities. Default is false. If standalone is true, to modify - * a feature, call the method with the target feature. - * Note that you must call the method to finish - * feature modification in standalone mode (before starting to modify - * another feature). - */ - standalone: false, - - /** - * Property: layer - * {} - */ - layer: null, - - /** - * Property: feature - * {} Feature currently available for modification. - */ - feature: null, - - /** - * Property: vertex - * {} Vertex currently being modified. - */ - vertex: null, - - /** - * Property: vertices - * {Array()} Verticies currently available - * for dragging. - */ - vertices: null, - - /** - * Property: virtualVertices - * {Array()} Virtual vertices in the middle - * of each edge. - */ - virtualVertices: null, - - /** - * Property: handlers - * {Object} - */ - handlers: null, - - /** - * APIProperty: deleteCodes - * {Array(Integer)} Keycodes for deleting verticies. Set to null to disable - * vertex deltion by keypress. If non-null, keypresses with codes - * in this array will delete vertices under the mouse. Default - * is 46 and 68, the 'delete' and lowercase 'd' keys. - */ - deleteCodes: null, - - /** - * APIProperty: virtualStyle - * {Object} A symbolizer to be used for virtual vertices. - */ - virtualStyle: null, - - /** - * APIProperty: vertexRenderIntent - * {String} The renderIntent to use for vertices. If no is - * provided, this renderIntent will also be used for virtual vertices, with - * a fillOpacity and strokeOpacity of 0.3. Default is null, which means - * that the layer's default style will be used for vertices. - */ - vertexRenderIntent: null, - - /** - * APIProperty: mode - * {Integer} Bitfields specifying the modification mode. Defaults to - * OpenLayers.Control.ModifyFeature.RESHAPE. To set the mode to a - * combination of options, use the | operator. For example, to allow - * the control to both resize and rotate features, use the following - * syntax - * (code) - * control.mode = OpenLayers.Control.ModifyFeature.RESIZE | - * OpenLayers.Control.ModifyFeature.ROTATE; - * (end) - */ - mode: null, - - /** - * APIProperty: createVertices - * {Boolean} Create new vertices by dragging the virtual vertices - * in the middle of each edge. Default is true. - */ - createVertices: true, - - /** - * Property: modified - * {Boolean} The currently selected feature has been modified. - */ - modified: false, - - /** - * Property: radiusHandle - * {} A handle for rotating/resizing a feature. - */ - radiusHandle: null, - - /** - * Property: dragHandle - * {} A handle for dragging a feature. - */ - dragHandle: null, - - /** - * APIProperty: onModificationStart - * {Function} *Deprecated*. Register for "beforefeaturemodified" instead. - * The "beforefeaturemodified" event is triggered on the layer before - * any modification begins. - * - * Optional function to be called when a feature is selected - * to be modified. The function should expect to be called with a - * feature. This could be used for example to allow to lock the - * feature on server-side. - */ - onModificationStart: function() {}, - - /** - * APIProperty: onModification - * {Function} *Deprecated*. Register for "featuremodified" instead. - * The "featuremodified" event is triggered on the layer with each - * feature modification. - * - * Optional function to be called when a feature has been - * modified. The function should expect to be called with a feature. - */ - onModification: function() {}, - - /** - * APIProperty: onModificationEnd - * {Function} *Deprecated*. Register for "afterfeaturemodified" instead. - * The "afterfeaturemodified" event is triggered on the layer after - * a feature has been modified. - * - * Optional function to be called when a feature is finished - * being modified. The function should expect to be called with a - * feature. - */ - onModificationEnd: function() {}, - - /** - * Constructor: OpenLayers.Control.ModifyFeature - * Create a new modify feature control. - * - * Parameters: - * layer - {} Layer that contains features that - * will be modified. - * options - {Object} Optional object whose properties will be set on the - * control. - */ - initialize: function(layer, options) { - options = options || {}; - this.layer = layer; - this.vertices = []; - this.virtualVertices = []; - this.virtualStyle = OpenLayers.Util.extend({}, - this.layer.style || - this.layer.styleMap.createSymbolizer(null, options.vertexRenderIntent) - ); - this.virtualStyle.fillOpacity = 0.3; - this.virtualStyle.strokeOpacity = 0.3; - this.deleteCodes = [46, 68]; - this.mode = OpenLayers.Control.ModifyFeature.RESHAPE; - OpenLayers.Control.prototype.initialize.apply(this, [options]); - if(!(OpenLayers.Util.isArray(this.deleteCodes))) { - this.deleteCodes = [this.deleteCodes]; - } - - // configure the drag handler - var dragCallbacks = { - down: function(pixel) { - this.vertex = null; - var feature = this.layer.getFeatureFromEvent( - this.handlers.drag.evt); - if (feature) { - this.dragStart(feature); - } else if (this.clickout) { - this._unselect = this.feature; - } - }, - move: function(pixel) { - delete this._unselect; - if (this.vertex) { - this.dragVertex(this.vertex, pixel); - } - }, - up: function() { - this.handlers.drag.stopDown = false; - if (this._unselect) { - this.unselectFeature(this._unselect); - delete this._unselect; - } - }, - done: function(pixel) { - if (this.vertex) { - this.dragComplete(this.vertex); - } - } - }; - var dragOptions = { - documentDrag: this.documentDrag, - stopDown: false - }; - - // configure the keyboard handler - var keyboardOptions = { - keydown: this.handleKeypress - }; - this.handlers = { - keyboard: new OpenLayers.Handler.Keyboard(this, keyboardOptions), - drag: new OpenLayers.Handler.Drag(this, dragCallbacks, dragOptions) - }; - }, - - /** - * APIMethod: destroy - * Take care of things that are not handled in superclass. - */ - destroy: function() { - if (this.map) { - this.map.events.un({ - "removelayer": this.handleMapEvents, - "changelayer": this.handleMapEvents, - scope: this - }); - } - this.layer = null; - OpenLayers.Control.prototype.destroy.apply(this, []); - }, - - /** - * APIMethod: activate - * Activate the control. - * - * Returns: - * {Boolean} Successfully activated the control. - */ - activate: function() { - this.moveLayerToTop(); - this.map.events.on({ - "removelayer": this.handleMapEvents, - "changelayer": this.handleMapEvents, - scope: this - }); - return (this.handlers.keyboard.activate() && - this.handlers.drag.activate() && - OpenLayers.Control.prototype.activate.apply(this, arguments)); - }, - - /** - * APIMethod: deactivate - * Deactivate the control. - * - * Returns: - * {Boolean} Successfully deactivated the control. - */ - deactivate: function() { - var deactivated = false; - // the return from the controls is unimportant in this case - if(OpenLayers.Control.prototype.deactivate.apply(this, arguments)) { - this.moveLayerBack(); - this.map.events.un({ - "removelayer": this.handleMapEvents, - "changelayer": this.handleMapEvents, - scope: this - }); - this.layer.removeFeatures(this.vertices, {silent: true}); - this.layer.removeFeatures(this.virtualVertices, {silent: true}); - this.vertices = []; - this.handlers.drag.deactivate(); - this.handlers.keyboard.deactivate(); - var feature = this.feature; - if (feature && feature.geometry && feature.layer) { - this.unselectFeature(feature); - } - deactivated = true; - } - return deactivated; - }, - - /** - * Method: beforeSelectFeature - * Called before a feature is selected. - * - * Parameters: - * feature - {} The feature about to be selected. - */ - beforeSelectFeature: function(feature) { - return this.layer.events.triggerEvent( - "beforefeaturemodified", {feature: feature} - ); - }, - - /** - * APIMethod: selectFeature - * Select a feature for modification in standalone mode. In non-standalone - * mode, this method is called when a feature is selected by clicking. - * Register a listener to the beforefeaturemodified event and return false - * to prevent feature modification. - * - * Parameters: - * feature - {} the selected feature. - */ - selectFeature: function(feature) { - if (this.feature === feature || - (this.geometryTypes && OpenLayers.Util.indexOf(this.geometryTypes, - feature.geometry.CLASS_NAME) == -1)) { - return; - } - if (this.beforeSelectFeature(feature) !== false) { - if (this.feature) { - this.unselectFeature(this.feature); - } - this.feature = feature; - this.layer.selectedFeatures.push(feature); - this.layer.drawFeature(feature, 'select'); - this.modified = false; - this.resetVertices(); - this.onModificationStart(this.feature); - } - // keep track of geometry modifications - var modified = feature.modified; - if (feature.geometry && !(modified && modified.geometry)) { - this._originalGeometry = feature.geometry.clone(); - } - }, - - /** - * APIMethod: unselectFeature - * Called when the select feature control unselects a feature. - * - * Parameters: - * feature - {} The unselected feature. - */ - unselectFeature: function(feature) { - this.layer.removeFeatures(this.vertices, {silent: true}); - this.vertices = []; - this.layer.destroyFeatures(this.virtualVertices, {silent: true}); - this.virtualVertices = []; - if(this.dragHandle) { - this.layer.destroyFeatures([this.dragHandle], {silent: true}); - delete this.dragHandle; - } - if(this.radiusHandle) { - this.layer.destroyFeatures([this.radiusHandle], {silent: true}); - delete this.radiusHandle; - } - this.layer.drawFeature(this.feature, 'default'); - this.feature = null; - OpenLayers.Util.removeItem(this.layer.selectedFeatures, feature); - this.onModificationEnd(feature); - this.layer.events.triggerEvent("afterfeaturemodified", { - feature: feature, - modified: this.modified - }); - this.modified = false; - }, - - - /** - * Method: dragStart - * Called by the drag handler before a feature is dragged. This method is - * used to differentiate between points and vertices - * of higher order geometries. - * - * Parameters: - * feature - {} The point or vertex about to be - * dragged. - */ - dragStart: function(feature) { - var isPoint = feature.geometry.CLASS_NAME == - 'OpenLayers.Geometry.Point'; - if (!this.standalone && - ((!feature._sketch && isPoint) || !feature._sketch)) { - if (this.toggle && this.feature === feature) { - // mark feature for unselection - this._unselect = feature; - } - this.selectFeature(feature); - } - if (feature._sketch || isPoint) { - // feature is a drag or virtual handle or point - this.vertex = feature; - this.handlers.drag.stopDown = true; - } - }, - - /** - * Method: dragVertex - * Called by the drag handler with each drag move of a vertex. - * - * Parameters: - * vertex - {} The vertex being dragged. - * pixel - {} Pixel location of the mouse event. - */ - dragVertex: function(vertex, pixel) { - var pos = this.map.getLonLatFromViewPortPx(pixel); - var geom = vertex.geometry; - geom.move(pos.lon - geom.x, pos.lat - geom.y); - this.modified = true; - /** - * Five cases: - * 1) dragging a simple point - * 2) dragging a virtual vertex - * 3) dragging a drag handle - * 4) dragging a real vertex - * 5) dragging a radius handle - */ - if(this.feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { - // dragging a simple point - this.layer.events.triggerEvent("vertexmodified", { - vertex: vertex.geometry, - feature: this.feature, - pixel: pixel - }); - } else { - if(vertex._index) { - // dragging a virtual vertex - vertex.geometry.parent.addComponent(vertex.geometry, - vertex._index); - // move from virtual to real vertex - delete vertex._index; - OpenLayers.Util.removeItem(this.virtualVertices, vertex); - this.vertices.push(vertex); - } else if(vertex == this.dragHandle) { - // dragging a drag handle - this.layer.removeFeatures(this.vertices, {silent: true}); - this.vertices = []; - if(this.radiusHandle) { - this.layer.destroyFeatures([this.radiusHandle], {silent: true}); - this.radiusHandle = null; - } - } else if(vertex !== this.radiusHandle) { - // dragging a real vertex - this.layer.events.triggerEvent("vertexmodified", { - vertex: vertex.geometry, - feature: this.feature, - pixel: pixel - }); - } - // dragging a radius handle - no special treatment - if(this.virtualVertices.length > 0) { - this.layer.destroyFeatures(this.virtualVertices, {silent: true}); - this.virtualVertices = []; - } - this.layer.drawFeature(this.feature, this.standalone ? undefined : - 'select'); - } - // keep the vertex on top so it gets the mouseout after dragging - // this should be removed in favor of an option to draw under or - // maintain node z-index - this.layer.drawFeature(vertex); - }, - - /** - * Method: dragComplete - * Called by the drag handler when the feature dragging is complete. - * - * Parameters: - * vertex - {} The vertex being dragged. - */ - dragComplete: function(vertex) { - this.resetVertices(); - this.setFeatureState(); - this.onModification(this.feature); - this.layer.events.triggerEvent("featuremodified", - {feature: this.feature}); - }, - - /** - * Method: setFeatureState - * Called when the feature is modified. If the current state is not - * INSERT or DELETE, the state is set to UPDATE. - */ - setFeatureState: function() { - if(this.feature.state != OpenLayers.State.INSERT && - this.feature.state != OpenLayers.State.DELETE) { - this.feature.state = OpenLayers.State.UPDATE; - if (this.modified && this._originalGeometry) { - var feature = this.feature; - feature.modified = OpenLayers.Util.extend(feature.modified, { - geometry: this._originalGeometry - }); - delete this._originalGeometry; - } - } - }, - - /** - * Method: resetVertices - */ - resetVertices: function() { - if(this.vertices.length > 0) { - this.layer.removeFeatures(this.vertices, {silent: true}); - this.vertices = []; - } - if(this.virtualVertices.length > 0) { - this.layer.removeFeatures(this.virtualVertices, {silent: true}); - this.virtualVertices = []; - } - if(this.dragHandle) { - this.layer.destroyFeatures([this.dragHandle], {silent: true}); - this.dragHandle = null; - } - if(this.radiusHandle) { - this.layer.destroyFeatures([this.radiusHandle], {silent: true}); - this.radiusHandle = null; - } - if(this.feature && - this.feature.geometry.CLASS_NAME != "OpenLayers.Geometry.Point") { - if((this.mode & OpenLayers.Control.ModifyFeature.DRAG)) { - this.collectDragHandle(); - } - if((this.mode & (OpenLayers.Control.ModifyFeature.ROTATE | - OpenLayers.Control.ModifyFeature.RESIZE))) { - this.collectRadiusHandle(); - } - if(this.mode & OpenLayers.Control.ModifyFeature.RESHAPE){ - // Don't collect vertices when we're resizing - if (!(this.mode & OpenLayers.Control.ModifyFeature.RESIZE)){ - this.collectVertices(); - } - } - } - }, - - /** - * Method: handleKeypress - * Called by the feature handler on keypress. This is used to delete - * vertices. If the property is set, vertices will - * be deleted when a feature is selected for modification and - * the mouse is over a vertex. - * - * Parameters: - * evt - {Event} Keypress event. - */ - handleKeypress: function(evt) { - var code = evt.keyCode; - - // check for delete key - if(this.feature && - OpenLayers.Util.indexOf(this.deleteCodes, code) != -1) { - var vertex = this.layer.getFeatureFromEvent(this.handlers.drag.evt); - if (vertex && - OpenLayers.Util.indexOf(this.vertices, vertex) != -1 && - !this.handlers.drag.dragging && vertex.geometry.parent) { - // remove the vertex - vertex.geometry.parent.removeComponent(vertex.geometry); - this.layer.events.triggerEvent("vertexremoved", { - vertex: vertex.geometry, - feature: this.feature, - pixel: evt.xy - }); - this.layer.drawFeature(this.feature, this.standalone ? - undefined : 'select'); - this.modified = true; - this.resetVertices(); - this.setFeatureState(); - this.onModification(this.feature); - this.layer.events.triggerEvent("featuremodified", - {feature: this.feature}); - } - } - }, - - /** - * Method: collectVertices - * Collect the vertices from the modifiable feature's geometry and push - * them on to the control's vertices array. - */ - collectVertices: function() { - this.vertices = []; - this.virtualVertices = []; - var control = this; - function collectComponentVertices(geometry) { - var i, vertex, component, len; - if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { - vertex = new OpenLayers.Feature.Vector(geometry); - vertex._sketch = true; - vertex.renderIntent = control.vertexRenderIntent; - control.vertices.push(vertex); - } else { - var numVert = geometry.components.length; - if(geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") { - numVert -= 1; - } - for(i=0; i} The control's map. - */ - setMap: function(map) { - this.handlers.drag.setMap(map); - OpenLayers.Control.prototype.setMap.apply(this, arguments); - }, - - /** - * Method: handleMapEvents - * - * Parameters: - * evt - {Object} - */ - handleMapEvents: function(evt) { - if (evt.type == "removelayer" || evt.property == "order") { - this.moveLayerToTop(); - } - }, - - /** - * Method: moveLayerToTop - * Moves the layer for this handler to the top, so mouse events can reach - * it. - */ - moveLayerToTop: function() { - var index = Math.max(this.map.Z_INDEX_BASE['Feature'] - 1, - this.layer.getZIndex()) + 1; - this.layer.setZIndex(index); - - }, - - /** - * Method: moveLayerBack - * Moves the layer back to the position determined by the map's layers - * array. - */ - moveLayerBack: function() { - var index = this.layer.getZIndex() - 1; - if (index >= this.map.Z_INDEX_BASE['Feature']) { - this.layer.setZIndex(index); - } else { - this.map.setLayerZIndex(this.layer, - this.map.getLayerIndex(this.layer)); - } - }, - - CLASS_NAME: "OpenLayers.Control.ModifyFeature" -}); - -/** - * Constant: RESHAPE - * {Integer} Constant used to make the control work in reshape mode - */ -OpenLayers.Control.ModifyFeature.RESHAPE = 1; -/** - * Constant: RESIZE - * {Integer} Constant used to make the control work in resize mode - */ -OpenLayers.Control.ModifyFeature.RESIZE = 2; -/** - * Constant: ROTATE - * {Integer} Constant used to make the control work in rotate mode - */ -OpenLayers.Control.ModifyFeature.ROTATE = 4; -/** - * Constant: DRAG - * {Integer} Constant used to make the control work in drag mode - */ -OpenLayers.Control.ModifyFeature.DRAG = 8; -/* ====================================================================== - OpenLayers/Layer/Bing.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/Layer/XYZ.js - */ - -/** - * Class: OpenLayers.Layer.Bing - * Bing layer using direct tile access as provided by Bing Maps REST Services. - * See http://msdn.microsoft.com/en-us/library/ff701713.aspx for more - * information. Note: Terms of Service compliant use requires the map to be - * configured with an control and the - * attribution placed on or near the map. - * - * Inherits from: - * - - */ -OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, { - - /** - * Property: key - * {String} API key for Bing maps, get your own key - * at http://bingmapsportal.com/ . - */ - key: null, - - /** - * Property: serverResolutions - * {Array} the resolutions provided by the Bing servers. - */ - serverResolutions: [ - 156543.03390625, 78271.516953125, 39135.7584765625, - 19567.87923828125, 9783.939619140625, 4891.9698095703125, - 2445.9849047851562, 1222.9924523925781, 611.4962261962891, - 305.74811309814453, 152.87405654907226, 76.43702827453613, - 38.218514137268066, 19.109257068634033, 9.554628534317017, - 4.777314267158508, 2.388657133579254, 1.194328566789627, - 0.5971642833948135, 0.29858214169740677, 0.14929107084870338, - 0.07464553542435169 - ], - - /** - * Property: attributionTemplate - * {String} - */ - attributionTemplate: '' + - '${copyrights}' + - '' + - 'Terms of Use', - - /** - * Property: metadata - * {Object} Metadata for this layer, as returned by the callback script - */ - metadata: null, - - /** - * Property: protocolRegex - * {RegExp} Regular expression to match and replace http: in bing urls - */ - protocolRegex: /^http:/i, - - /** - * APIProperty: type - * {String} The layer identifier. Any non-birdseye imageryType - * from http://msdn.microsoft.com/en-us/library/ff701716.aspx can be - * used. Default is "Road". - */ - type: "Road", - - /** - * APIProperty: culture - * {String} The culture identifier. See http://msdn.microsoft.com/en-us/library/ff701709.aspx - * for the definition and the possible values. Default is "en-US". - */ - culture: "en-US", - - /** - * APIProperty: metadataParams - * {Object} Optional url parameters for the Get Imagery Metadata request - * as described here: http://msdn.microsoft.com/en-us/library/ff701716.aspx - */ - metadataParams: null, - - /** APIProperty: tileOptions - * {Object} optional configuration options for instances - * created by this Layer. Default is - * - * (code) - * {crossOriginKeyword: 'anonymous'} - * (end) - */ - tileOptions: null, - - /** APIProperty: protocol - * {String} Protocol to use to fetch Imagery Metadata, tiles and bing logo - * Can be 'http:' 'https:' or '' - * - * Warning: tiles may not be available under both HTTP and HTTPS protocols. - * Microsoft approved use of both HTTP and HTTPS urls for tiles. However - * this is undocumented and the Imagery Metadata API always returns HTTP - * urls. - * - * Default is '', unless when executed from a file:/// uri, in which case - * it is 'http:'. - */ - protocol: ~window.location.href.indexOf('http') ? '' : 'http:', - - /** - * Constructor: OpenLayers.Layer.Bing - * Create a new Bing layer. - * - * Example: - * (code) - * var road = new OpenLayers.Layer.Bing({ - * name: "My Bing Aerial Layer", - * type: "Aerial", - * key: "my-api-key-here", - * }); - * (end) - * - * Parameters: - * options - {Object} Configuration properties for the layer. - * - * Required configuration properties: - * key - {String} Bing Maps API key for your application. Get one at - * http://bingmapsportal.com/. - * type - {String} The layer identifier. Any non-birdseye imageryType - * from http://msdn.microsoft.com/en-us/library/ff701716.aspx can be - * used. - * - * Any other documented layer properties can be provided in the config object. - */ - initialize: function(options) { - options = OpenLayers.Util.applyDefaults({ - sphericalMercator: true - }, options); - var name = options.name || "Bing " + (options.type || this.type); - - var newArgs = [name, null, options]; - OpenLayers.Layer.XYZ.prototype.initialize.apply(this, newArgs); - this.tileOptions = OpenLayers.Util.extend({ - crossOriginKeyword: 'anonymous' - }, this.options.tileOptions); - this.loadMetadata(); - }, - - /** - * Method: loadMetadata - */ - loadMetadata: function() { - this._callbackId = "_callback_" + this.id.replace(/\./g, "_"); - // link the processMetadata method to the global scope and bind it - // to this instance - window[this._callbackId] = OpenLayers.Function.bind( - OpenLayers.Layer.Bing.processMetadata, this - ); - var params = OpenLayers.Util.applyDefaults({ - key: this.key, - jsonp: this._callbackId, - include: "ImageryProviders" - }, this.metadataParams); - var url = this.protocol + "//dev.virtualearth.net/REST/v1/Imagery/Metadata/" + - this.type + "?" + OpenLayers.Util.getParameterString(params); - var script = document.createElement("script"); - script.type = "text/javascript"; - script.src = url; - script.id = this._callbackId; - document.getElementsByTagName("head")[0].appendChild(script); - }, - - /** - * Method: initLayer - * - * Sets layer properties according to the metadata provided by the API - */ - initLayer: function() { - var res = this.metadata.resourceSets[0].resources[0]; - var url = res.imageUrl.replace("{quadkey}", "${quadkey}"); - url = url.replace("{culture}", this.culture); - url = url.replace(this.protocolRegex, this.protocol); - this.url = []; - for (var i=0; i} - */ - getURL: function(bounds) { - if (!this.url) { - return; - } - var xyz = this.getXYZ(bounds), x = xyz.x, y = xyz.y, z = xyz.z; - var quadDigits = []; - for (var i = z; i > 0; --i) { - var digit = '0'; - var mask = 1 << (i - 1); - if ((x & mask) != 0) { - digit++; - } - if ((y & mask) != 0) { - digit++; - digit++; - } - quadDigits.push(digit); - } - var quadKey = quadDigits.join(""); - var url = this.selectUrl('' + x + y + z, this.url); - - return OpenLayers.String.format(url, {'quadkey': quadKey}); - }, - - /** - * Method: updateAttribution - * Updates the attribution according to the requirements outlined in - * http://gis.638310.n2.nabble.com/Bing-imagery-td5789168.html - */ - updateAttribution: function() { - var metadata = this.metadata; - if (!metadata.resourceSets || !this.map || !this.map.center) { - return; - } - var res = metadata.resourceSets[0].resources[0]; - var extent = this.map.getExtent().transform( - this.map.getProjectionObject(), - new OpenLayers.Projection("EPSG:4326") - ); - var providers = res.imageryProviders || [], - zoom = OpenLayers.Util.indexOf(this.serverResolutions, - this.getServerResolution()), - copyrights = "", provider, i, ii, j, jj, bbox, coverage; - for (i=0,ii=providers.length; i= coverage.zoomMin) { - copyrights += provider.attribution + " "; - } - } - } - var logo = metadata.brandLogoUri.replace(this.protocolRegex, this.protocol); - this.attribution = OpenLayers.String.format(this.attributionTemplate, { - type: this.type.toLowerCase(), - logo: logo, - copyrights: copyrights - }); - this.map && this.map.events.triggerEvent("changelayer", { - layer: this, - property: "attribution" - }); - }, - - /** - * Method: setMap - */ - setMap: function() { - OpenLayers.Layer.XYZ.prototype.setMap.apply(this, arguments); - this.map.events.register("moveend", this, this.updateAttribution); - }, - - /** - * APIMethod: clone - * - * Parameters: - * obj - {Object} - * - * Returns: - * {} An exact clone of this - */ - clone: function(obj) { - if (obj == null) { - obj = new OpenLayers.Layer.Bing(this.options); - } - //get all additions from superclasses - obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]); - // copy/set any non-init, non-simple values here - return obj; - }, - - /** - * Method: destroy - */ - destroy: function() { - this.map && - this.map.events.unregister("moveend", this, this.updateAttribution); - OpenLayers.Layer.XYZ.prototype.destroy.apply(this, arguments); - }, - - CLASS_NAME: "OpenLayers.Layer.Bing" -}); - -/** - * Function: OpenLayers.Layer.Bing.processMetadata - * This function will be bound to an instance, linked to the global scope with - * an id, and called by the JSONP script returned by the API. - * - * Parameters: - * metadata - {Object} metadata as returned by the API - */ -OpenLayers.Layer.Bing.processMetadata = function(metadata) { - this.metadata = metadata; - this.initLayer(); - var script = document.getElementById(this._callbackId); - script.parentNode.removeChild(script); - window[this._callbackId] = undefined; // cannot delete from window in IE - delete this._callbackId; -}; -/* ====================================================================== - OpenLayers/Geometry/MultiLineString.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/LineString.js - */ - -/** - * Class: OpenLayers.Geometry.MultiLineString - * A MultiLineString is a geometry with multiple - * components. - * - * Inherits from: - * - - * - - */ -OpenLayers.Geometry.MultiLineString = 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.LineString"], - - /** - * Constructor: OpenLayers.Geometry.MultiLineString - * Constructor for a MultiLineString Geometry. - * - * Parameters: - * components - {Array()} - * - */ - - /** - * Method: split - * Use this geometry (the source) to attempt to split a target geometry. - * - * Parameters: - * geometry - {} The target geometry. - * options - {Object} Properties of this object will be used to determine - * how the split is conducted. - * - * Valid options: - * mutual - {Boolean} Split the source geometry in addition to the target - * geometry. Default is false. - * edge - {Boolean} Allow splitting when only edges intersect. Default is - * true. If false, a vertex on the source 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 an existing vertex on the source - * will be assumed to occur at the vertex. - * - * Returns: - * {Array} A list of geometries (of this same type as the target) that - * result from splitting the target with the source geometry. The - * source and target geometry will remain unmodified. If no split - * results, null will be returned. If mutual is true and a split - * results, return will be an array of two arrays - the first will be - * all geometries that result from splitting the source geometry and - * the second will be all geometries that result from splitting the - * target geometry. - */ - split: function(geometry, options) { - var results = null; - var mutual = options && options.mutual; - var splits, sourceLine, sourceLines, sourceSplit, targetSplit; - var sourceParts = []; - var targetParts = [geometry]; - for(var i=0, len=this.components.length; i 1) { - sourceSplit = true; - } else { - sourceParts = []; - } - if(targetParts && targetParts.length > 1) { - targetSplit = true; - } else { - targetParts = []; - } - if(sourceSplit || targetSplit) { - if(mutual) { - results = [sourceParts, targetParts]; - } else { - results = targetParts; - } - } - return results; - }, - - /** - * Method: splitWith - * Split this geometry (the target) with the given geometry (the source). - * - * Parameters: - * geometry - {} A geometry used to split this - * geometry (the source). - * options - {Object} Properties of this object will be used to determine - * how the split is conducted. - * - * Valid options: - * mutual - {Boolean} Split the source geometry in addition to the target - * geometry. Default is false. - * edge - {Boolean} Allow splitting when only edges intersect. Default is - * true. If false, a vertex on the source 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 an existing vertex on the source - * will be assumed to occur at the vertex. - * - * Returns: - * {Array} A list of geometries (of this same type as the target) that - * result from splitting the target with the source geometry. The - * source and target geometry will remain unmodified. If no split - * results, null will be returned. If mutual is true and a split - * results, return will be an array of two arrays - the first will be - * all geometries that result from splitting the source geometry and - * the second will be all geometries that result from splitting the - * target geometry. - */ - splitWith: function(geometry, options) { - var results = null; - var mutual = options && options.mutual; - var splits, targetLine, sourceLines, sourceSplit, targetSplit, sourceParts, targetParts; - if(geometry instanceof OpenLayers.Geometry.LineString) { - targetParts = []; - sourceParts = [geometry]; - for(var i=0, len=this.components.length; i 1) { - sourceSplit = true; - } else { - sourceParts = []; - } - if(targetParts && targetParts.length > 1) { - targetSplit = true; - } else { - targetParts = []; - } - if(sourceSplit || targetSplit) { - if(mutual) { - results = [sourceParts, targetParts]; - } else { - results = targetParts; - } - } - return results; - }, - - CLASS_NAME: "OpenLayers.Geometry.MultiLineString" -}); -/* ====================================================================== - 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/Format/XML.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.js - */ - -/** - * Class: OpenLayers.Format.XML - * Read and write XML. For cross-browser XML generation, use methods on an - * instance of the XML format class instead of on document. - * The DOM creation and traversing methods exposed here all mimic the - * W3C XML DOM methods. Create a new parser with the - * constructor. - * - * Inherits from: - * - - */ -OpenLayers.Format.XML = OpenLayers.Class(OpenLayers.Format, { - - /** - * Property: namespaces - * {Object} Mapping of namespace aliases to namespace URIs. Properties - * of this object should not be set individually. Read-only. All - * XML subclasses should have their own namespaces object. Use - * to add or set a namespace alias after construction. - */ - namespaces: null, - - /** - * Property: namespaceAlias - * {Object} Mapping of namespace URI to namespace alias. This object - * is read-only. Use to add or set a namespace alias. - */ - namespaceAlias: null, - - /** - * Property: defaultPrefix - * {String} The default namespace alias for creating element nodes. - */ - defaultPrefix: null, - - /** - * 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: {}, - - /** - * Property: writers - * As a compliment to the property, this structure contains public - * writing functions grouped by namespace alias and named like the - * node names they produce. - */ - writers: {}, - - /** - * Property: xmldom - * {XMLDom} If this browser uses ActiveX, this will be set to a XMLDOM - * object. It is not intended to be a browser sniffing property. - * Instead, the xmldom property is used instead of document - * where namespaced node creation methods are not supported. In all - * other browsers, this remains null. - */ - xmldom: null, - - /** - * Constructor: OpenLayers.Format.XML - * Construct an XML parser. The parser is used to read and write XML. - * Reading XML from a string returns a DOM element. Writing XML from - * a DOM element returns a string. - * - * Parameters: - * options - {Object} Optional object whose properties will be set on - * the object. - */ - initialize: function(options) { - if(window.ActiveXObject) { - this.xmldom = new ActiveXObject("Microsoft.XMLDOM"); - } - OpenLayers.Format.prototype.initialize.apply(this, [options]); - // clone the namespace object and set all namespace aliases - this.namespaces = OpenLayers.Util.extend({}, this.namespaces); - this.namespaceAlias = {}; - for(var alias in this.namespaces) { - this.namespaceAlias[this.namespaces[alias]] = alias; - } - }, - - /** - * APIMethod: destroy - * Clean up. - */ - destroy: function() { - this.xmldom = null; - OpenLayers.Format.prototype.destroy.apply(this, arguments); - }, - - /** - * Method: setNamespace - * Set a namespace alias and URI for the format. - * - * Parameters: - * alias - {String} The namespace alias (prefix). - * uri - {String} The namespace URI. - */ - setNamespace: function(alias, uri) { - this.namespaces[alias] = uri; - this.namespaceAlias[uri] = alias; - }, - - /** - * APIMethod: read - * Deserialize a XML string and return a DOM node. - * - * Parameters: - * text - {String} A XML string - - * Returns: - * {DOMElement} A DOM node - */ - read: function(text) { - var index = text.indexOf('<'); - if(index > 0) { - text = text.substring(index); - } - var node = OpenLayers.Util.Try( - OpenLayers.Function.bind(( - function() { - var xmldom; - /** - * Since we want to be able to call this method on the prototype - * itself, this.xmldom may not exist even if in IE. - */ - if(window.ActiveXObject && !this.xmldom) { - xmldom = new ActiveXObject("Microsoft.XMLDOM"); - } else { - xmldom = this.xmldom; - - } - xmldom.loadXML(text); - return xmldom; - } - ), this), - function() { - return new DOMParser().parseFromString(text, 'text/xml'); - }, - function() { - var req = new XMLHttpRequest(); - req.open("GET", "data:" + "text/xml" + - ";charset=utf-8," + encodeURIComponent(text), false); - if(req.overrideMimeType) { - req.overrideMimeType("text/xml"); - } - req.send(null); - return req.responseXML; - } - ); - - if(this.keepData) { - this.data = node; - } - - return node; - }, - - /** - * APIMethod: write - * Serialize a DOM node into a XML string. - * - * Parameters: - * node - {DOMElement} A DOM node. - * - * Returns: - * {String} The XML string representation of the input node. - */ - write: function(node) { - var data; - if(this.xmldom) { - data = node.xml; - } else { - var serializer = new XMLSerializer(); - if (node.nodeType == 1) { - // Add nodes to a document before serializing. Everything else - // is serialized as is. This may need more work. See #1218 . - var doc = document.implementation.createDocument("", "", null); - if (doc.importNode) { - node = doc.importNode(node, true); - } - doc.appendChild(node); - data = serializer.serializeToString(doc); - } else { - data = serializer.serializeToString(node); - } - } - return data; - }, - - /** - * APIMethod: createElementNS - * Create a new element with namespace. This node can be appended to - * another node with the standard node.appendChild method. For - * cross-browser support, this method must be used instead of - * document.createElementNS. - * - * Parameters: - * uri - {String} Namespace URI for the element. - * name - {String} The qualified name of the element (prefix:localname). - * - * Returns: - * {Element} A DOM element with namespace. - */ - createElementNS: function(uri, name) { - var element; - if(this.xmldom) { - if(typeof uri == "string") { - element = this.xmldom.createNode(1, name, uri); - } else { - element = this.xmldom.createNode(1, name, ""); - } - } else { - element = document.createElementNS(uri, name); - } - return element; - }, - - /** - * APIMethod: createDocumentFragment - * Create a document fragment node that can be appended to another node - * created by createElementNS. This will call - * document.createDocumentFragment outside of IE. In IE, the ActiveX - * object's createDocumentFragment method is used. - * - * Returns: - * {Element} A document fragment. - */ - createDocumentFragment: function() { - var element; - if (this.xmldom) { - element = this.xmldom.createDocumentFragment(); - } else { - element = document.createDocumentFragment(); - } - return element; - }, - - /** - * APIMethod: createTextNode - * Create a text node. This node can be appended to another node with - * the standard node.appendChild method. For cross-browser support, - * this method must be used instead of document.createTextNode. - * - * Parameters: - * text - {String} The text of the node. - * - * Returns: - * {DOMElement} A DOM text node. - */ - createTextNode: function(text) { - var node; - if (typeof text !== "string") { - text = String(text); - } - if(this.xmldom) { - node = this.xmldom.createTextNode(text); - } else { - node = document.createTextNode(text); - } - return node; - }, - - /** - * APIMethod: getElementsByTagNameNS - * Get a list of elements on a node given the namespace URI and local name. - * To return all nodes in a given namespace, use '*' for the name - * argument. To return all nodes of a given (local) name, regardless - * of namespace, use '*' for the uri argument. - * - * Parameters: - * node - {Element} Node on which to search for other nodes. - * uri - {String} Namespace URI. - * name - {String} Local name of the tag (without the prefix). - * - * Returns: - * {NodeList} A node list or array of elements. - */ - getElementsByTagNameNS: function(node, uri, name) { - var elements = []; - if(node.getElementsByTagNameNS) { - elements = node.getElementsByTagNameNS(uri, name); - } else { - // brute force method - var allNodes = node.getElementsByTagName("*"); - var potentialNode, fullName; - for(var i=0, len=allNodes.length; i method. - * value - {String} Optional text to be appended as a text node. - * - * Returns: - * {Element} An element node. - */ - createElementNSPlus: function(name, options) { - options = options || {}; - // order of prefix preference - // 1. in the uri option - // 2. in the prefix option - // 3. in the qualified name - // 4. from the defaultPrefix - var uri = options.uri || this.namespaces[options.prefix]; - if(!uri) { - var loc = name.indexOf(":"); - uri = this.namespaces[name.substring(0, loc)]; - } - if(!uri) { - uri = this.namespaces[this.defaultPrefix]; - } - var node = this.createElementNS(uri, name); - if(options.attributes) { - this.setAttributes(node, options.attributes); - } - var value = options.value; - if(value != null) { - node.appendChild(this.createTextNode(value)); - } - return node; - }, - - /** - * Method: setAttributes - * Set multiple attributes given key value pairs from an object. - * - * Parameters: - * node - {Element} An element node. - * obj - {Object || Array} An object whose properties represent attribute - * names and values represent attribute values. If an attribute name - * is a qualified name ("prefix:local"), the prefix will be looked up - * in the parsers {namespaces} object. If the prefix is found, - * setAttributeNS will be used instead of setAttribute. - */ - setAttributes: function(node, obj) { - var value, uri; - for(var name in obj) { - if(obj[name] != null && obj[name].toString) { - value = obj[name].toString(); - // check for qualified attribute name ("prefix:local") - uri = this.namespaces[name.substring(0, name.indexOf(":"))] || null; - this.setAttributeNS(node, uri, name, value); - } - } - }, - - /** - * Method: readNode - * Shorthand for applying one of the named readers given the node - * namespace and local name. Readers take two args (node, obj) and - * generally extend or modify the second. - * - * Parameters: - * node - {DOMElement} The node to be read (required). - * obj - {Object} The object to be modified (optional). - * - * Returns: - * {Object} The input object, modified (or a new one if none was provided). - */ - readNode: function(node, obj) { - if(!obj) { - obj = {}; - } - var group = this.readers[node.namespaceURI ? this.namespaceAlias[node.namespaceURI]: this.defaultPrefix]; - if(group) { - var local = node.localName || node.nodeName.split(":").pop(); - var reader = group[local] || group["*"]; - if(reader) { - reader.apply(this, [node, obj]); - } - } - return obj; - }, - - /** - * Method: readChildNodes - * Shorthand for applying the named readers to all children of a node. - * For each child of type 1 (element), is called. - * - * Parameters: - * node - {DOMElement} The node to be read (required). - * obj - {Object} The object to be modified (optional). - * - * Returns: - * {Object} The input object, modified. - */ - readChildNodes: function(node, obj) { - if(!obj) { - obj = {}; - } - var children = node.childNodes; - var child; - for(var i=0, len=children.length; i group. If a local name is used (e.g. "Name") then - * the namespace of the parent is assumed. If a local name is used - * and no parent is supplied, then the default namespace is assumed. - * obj - {Object} Structure containing data for the writer. - * parent - {DOMElement} Result will be appended to this node. If no parent - * is supplied, the node will not be appended to anything. - * - * Returns: - * {DOMElement} The child node. - */ - writeNode: function(name, obj, parent) { - var prefix, local; - var split = name.indexOf(":"); - if(split > 0) { - prefix = name.substring(0, split); - local = name.substring(split + 1); - } else { - if(parent) { - prefix = this.namespaceAlias[parent.namespaceURI]; - } else { - prefix = this.defaultPrefix; - } - local = name; - } - var child = this.writers[prefix][local].apply(this, [obj]); - if(parent) { - parent.appendChild(child); - } - return child; - }, - - /** - * APIMethod: getChildEl - * Get the first child element. Optionally only return the first child - * if it matches the given name and namespace URI. - * - * Parameters: - * node - {DOMElement} The parent node. - * name - {String} Optional node name (local) to search for. - * uri - {String} Optional namespace URI to search for. - * - * Returns: - * {DOMElement} The first child. Returns null if no element is found, if - * something significant besides an element is found, or if the element - * found does not match the optional name and uri. - */ - getChildEl: function(node, name, uri) { - return node && this.getThisOrNextEl(node.firstChild, name, uri); - }, - - /** - * APIMethod: getNextEl - * Get the next sibling element. Optionally get the first sibling only - * if it matches the given local name and namespace URI. - * - * Parameters: - * node - {DOMElement} The node. - * name - {String} Optional local name of the sibling to search for. - * uri - {String} Optional namespace URI of the sibling to search for. - * - * Returns: - * {DOMElement} The next sibling element. Returns null if no element is - * found, something significant besides an element is found, or the - * found element does not match the optional name and uri. - */ - getNextEl: function(node, name, uri) { - return node && this.getThisOrNextEl(node.nextSibling, name, uri); - }, - - /** - * Method: getThisOrNextEl - * Return this node or the next element node. Optionally get the first - * sibling with the given local name or namespace URI. - * - * Parameters: - * node - {DOMElement} The node. - * name - {String} Optional local name of the sibling to search for. - * uri - {String} Optional namespace URI of the sibling to search for. - * - * Returns: - * {DOMElement} The next sibling element. Returns null if no element is - * found, something significant besides an element is found, or the - * found element does not match the query. - */ - getThisOrNextEl: function(node, name, uri) { - outer: for(var sibling=node; sibling; sibling=sibling.nextSibling) { - switch(sibling.nodeType) { - case 1: // Element - if((!name || name === (sibling.localName || sibling.nodeName.split(":").pop())) && - (!uri || uri === sibling.namespaceURI)) { - // matches - break outer; - } - sibling = null; - break outer; - case 3: // Text - if(/^\s*$/.test(sibling.nodeValue)) { - break; - } - case 4: // CDATA - case 6: // ENTITY_NODE - case 12: // NOTATION_NODE - case 10: // DOCUMENT_TYPE_NODE - case 11: // DOCUMENT_FRAGMENT_NODE - sibling = null; - break outer; - } // ignore comments and processing instructions - } - return sibling || null; - }, - - /** - * APIMethod: lookupNamespaceURI - * Takes a prefix and returns the namespace URI associated with it on the given - * node if found (and null if not). Supplying null for the prefix will - * return the default namespace. - * - * For browsers that support it, this calls the native lookupNamesapceURI - * function. In other browsers, this is an implementation of - * http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI. - * - * For browsers that don't support the attribute.ownerElement property, this - * method cannot be called on attribute nodes. - * - * Parameters: - * node - {DOMElement} The node from which to start looking. - * prefix - {String} The prefix to lookup or null to lookup the default namespace. - * - * Returns: - * {String} The namespace URI for the given prefix. Returns null if the prefix - * cannot be found or the node is the wrong type. - */ - lookupNamespaceURI: function(node, prefix) { - var uri = null; - if(node) { - if(node.lookupNamespaceURI) { - uri = node.lookupNamespaceURI(prefix); - } else { - outer: switch(node.nodeType) { - case 1: // ELEMENT_NODE - if(node.namespaceURI !== null && node.prefix === prefix) { - uri = node.namespaceURI; - break outer; - } - var len = node.attributes.length; - if(len) { - var attr; - for(var i=0; i on the instance. On other browsers, this will - * either return an existing or create a new shared document (see - * ). - * - * Returns: - * {XMLDocument} - */ - getXMLDoc: function() { - if (!OpenLayers.Format.XML.document && !this.xmldom) { - if (document.implementation && document.implementation.createDocument) { - OpenLayers.Format.XML.document = - document.implementation.createDocument("", "", null); - } else if (!this.xmldom && window.ActiveXObject) { - this.xmldom = new ActiveXObject("Microsoft.XMLDOM"); - } - } - return OpenLayers.Format.XML.document || this.xmldom; - }, - - CLASS_NAME: "OpenLayers.Format.XML" - -}); - -OpenLayers.Format.XML.CONTENT_TYPE = {EMPTY: 0, SIMPLE: 1, COMPLEX: 2, MIXED: 3}; - -/** - * APIFunction: OpenLayers.Format.XML.lookupNamespaceURI - * Takes a prefix and returns the namespace URI associated with it on the given - * node if found (and null if not). Supplying null for the prefix will - * return the default namespace. - * - * For browsers that support it, this calls the native lookupNamesapceURI - * function. In other browsers, this is an implementation of - * http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI. - * - * For browsers that don't support the attribute.ownerElement property, this - * method cannot be called on attribute nodes. - * - * Parameters: - * node - {DOMElement} The node from which to start looking. - * prefix - {String} The prefix to lookup or null to lookup the default namespace. - * - * Returns: - * {String} The namespace URI for the given prefix. Returns null if the prefix - * cannot be found or the node is the wrong type. - */ -OpenLayers.Format.XML.lookupNamespaceURI = OpenLayers.Function.bind( - OpenLayers.Format.XML.prototype.lookupNamespaceURI, - OpenLayers.Format.XML.prototype -); - -/** - * Property: OpenLayers.Format.XML.document - * {XMLDocument} XML document to reuse for creating non-HTML compliant nodes, - * like document.createCDATASection. - */ -OpenLayers.Format.XML.document = null; -/* ====================================================================== - OpenLayers/Format/OGCExceptionReport.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 - */ - -/** - * Class: OpenLayers.Format.OGCExceptionReport - * Class to read exception reports for various OGC services and versions. - * - * Inherits from: - * - - */ -OpenLayers.Format.OGCExceptionReport = OpenLayers.Class(OpenLayers.Format.XML, { - - /** - * Property: namespaces - * {Object} Mapping of namespace aliases to namespace URIs. - */ - namespaces: { - ogc: "http://www.opengis.net/ogc" - }, - - /** - * Property: regExes - * Compiled regular expressions for manipulating strings. - */ - regExes: { - trimSpace: (/^\s*|\s*$/g), - removeSpace: (/\s*/g), - splitSpace: (/\s+/), - trimComma: (/\s*,\s*/g) - }, - - /** - * Property: defaultPrefix - */ - defaultPrefix: "ogc", - - /** - * Constructor: OpenLayers.Format.OGCExceptionReport - * Create a new parser for OGC exception reports. - * - * Parameters: - * options - {Object} An optional object whose properties will be set on - * this instance. - */ - - /** - * APIMethod: read - * Read OGC exception report data from a string, and return an object with - * information about the exceptions. - * - * Parameters: - * data - {String} or {DOMElement} data to read/parse. - * - * Returns: - * {Object} Information about the exceptions that occurred. - */ - read: function(data) { - var result; - if(typeof data == "string") { - data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); - } - var root = data.documentElement; - var exceptionInfo = {exceptionReport: null}; - if (root) { - this.readChildNodes(data, exceptionInfo); - if (exceptionInfo.exceptionReport === null) { - // fall-back to OWSCommon since this is a common output format for exceptions - // we cannot easily use the ows readers directly since they differ for 1.0 and 1.1 - exceptionInfo = new OpenLayers.Format.OWSCommon().read(data); - } - } - return exceptionInfo; - }, - - /** - * 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: { - "ogc": { - "ServiceExceptionReport": function(node, obj) { - obj.exceptionReport = {exceptions: []}; - this.readChildNodes(node, obj.exceptionReport); - }, - "ServiceException": function(node, exceptionReport) { - var exception = { - code: node.getAttribute("code"), - locator: node.getAttribute("locator"), - text: this.getChildValue(node) - }; - exceptionReport.exceptions.push(exception); - } - } - }, - - CLASS_NAME: "OpenLayers.Format.OGCExceptionReport" - -}); -/* ====================================================================== - OpenLayers/Format/XML/VersionedOGC.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/OGCExceptionReport.js - */ - -/** - * Class: OpenLayers.Format.XML.VersionedOGC - * Base class for versioned formats, i.e. a format which supports multiple - * versions. - * - * To enable checking if parsing succeeded, you will need to define a property - * called errorProperty on the parser you want to check. The parser will then - * check the returned object to see if that property is present. If it is, it - * assumes the parsing was successful. If it is not present (or is null), it will - * pass the document through an OGCExceptionReport parser. - * - * If errorProperty is undefined for the parser, this error checking mechanism - * will be disabled. - * - * - * - * Inherits from: - * - - */ -OpenLayers.Format.XML.VersionedOGC = OpenLayers.Class(OpenLayers.Format.XML, { - - /** - * APIProperty: defaultVersion - * {String} Version number to assume if none found. - */ - defaultVersion: null, - - /** - * APIProperty: version - * {String} Specify a version string if one is known. - */ - version: null, - - /** - * APIProperty: profile - * {String} If provided, use a custom profile. - */ - profile: null, - - /** - * APIProperty: allowFallback - * {Boolean} If a profiled parser cannot be found for the returned version, - * use a non-profiled parser as the fallback. Application code using this - * should take into account that the return object structure might be - * missing the specifics of the profile. Defaults to false. - */ - allowFallback: false, - - /** - * Property: name - * {String} The name of this parser, this is the part of the CLASS_NAME - * except for "OpenLayers.Format." - */ - name: null, - - /** - * APIProperty: stringifyOutput - * {Boolean} If true, write will return a string otherwise a DOMElement. - * Default is false. - */ - stringifyOutput: false, - - /** - * Property: parser - * {Object} Instance of the versioned parser. Cached for multiple read and - * write calls of the same version. - */ - parser: null, - - /** - * Constructor: OpenLayers.Format.XML.VersionedOGC. - * Constructor. - * - * Parameters: - * options - {Object} Optional object whose properties will be set on - * the object. - */ - initialize: function(options) { - OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); - var className = this.CLASS_NAME; - this.name = className.substring(className.lastIndexOf(".")+1); - }, - - /** - * Method: getVersion - * Returns the version to use. Subclasses can override this function - * if a different version detection is needed. - * - * Parameters: - * root - {DOMElement} - * options - {Object} Optional configuration object. - * - * Returns: - * {String} The version to use. - */ - getVersion: function(root, options) { - var version; - // read - if (root) { - version = this.version; - if(!version) { - version = root.getAttribute("version"); - if(!version) { - version = this.defaultVersion; - } - } - } else { // write - version = (options && options.version) || - this.version || this.defaultVersion; - } - return version; - }, - - /** - * Method: getParser - * Get an instance of the cached parser if available, otherwise create one. - * - * Parameters: - * version - {String} - * - * Returns: - * {} - */ - getParser: function(version) { - version = version || this.defaultVersion; - var profile = this.profile ? "_" + this.profile : ""; - if(!this.parser || this.parser.VERSION != version) { - var format = OpenLayers.Format[this.name][ - "v" + version.replace(/\./g, "_") + profile - ]; - if(!format) { - if (profile !== "" && this.allowFallback) { - // fallback to the non-profiled version of the parser - profile = ""; - format = OpenLayers.Format[this.name][ - "v" + version.replace(/\./g, "_") - ]; - } - if (!format) { - throw "Can't find a " + this.name + " parser for version " + - version + profile; - } - } - this.parser = new format(this.options); - } - return this.parser; - }, - - /** - * APIMethod: write - * Write a document. - * - * Parameters: - * obj - {Object} An object representing the document. - * options - {Object} Optional configuration object. - * - * Returns: - * {String} The document as a string - */ - write: function(obj, options) { - var version = this.getVersion(null, options); - this.parser = this.getParser(version); - var root = this.parser.write(obj, options); - if (this.stringifyOutput === false) { - return root; - } else { - return OpenLayers.Format.XML.prototype.write.apply(this, [root]); - } - }, - - /** - * APIMethod: read - * Read a doc and return an object representing the document. - * - * Parameters: - * data - {String | DOMElement} Data to read. - * options - {Object} Options for the reader. - * - * Returns: - * {Object} An object representing the document. - */ - read: function(data, options) { - if(typeof data == "string") { - data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); - } - var root = data.documentElement; - var version = this.getVersion(root); - this.parser = this.getParser(version); // Select the parser - var obj = this.parser.read(data, options); // Parse the data - - var errorProperty = this.parser.errorProperty || null; - if (errorProperty !== null && obj[errorProperty] === undefined) { - // an error must have happened, so parse it and report back - var format = new OpenLayers.Format.OGCExceptionReport(); - obj.error = format.read(data); - } - obj.version = version; - return obj; - }, - - CLASS_NAME: "OpenLayers.Format.XML.VersionedOGC" -}); -/* ====================================================================== - 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. */ - - -/** - * @requires OpenLayers/BaseTypes/Class.js - * @requires OpenLayers/Util.js - */ - -/** - * Class: OpenLayers.Feature - * Features are combinations of geography and attributes. The OpenLayers.Feature - * class specifically combines a marker and a lonlat. - */ -OpenLayers.Feature = OpenLayers.Class({ - - /** - * Property: layer - * {} - */ - layer: null, - - /** - * Property: id - * {String} - */ - id: null, - - /** - * Property: lonlat - * {} - */ - lonlat: null, - - /** - * Property: data - * {Object} - */ - data: null, - - /** - * Property: marker - * {} - */ - marker: null, - - /** - * APIProperty: popupClass - * {} The class which will be used to instantiate - * a new Popup. Default is . - */ - popupClass: null, - - /** - * Property: popup - * {} - */ - popup: null, - - /** - * Constructor: OpenLayers.Feature - * Constructor for features. - * - * Parameters: - * layer - {} - * lonlat - {} - * data - {Object} - * - * Returns: - * {} - */ - initialize: function(layer, lonlat, data) { - this.layer = layer; - this.lonlat = lonlat; - this.data = (data != null) ? data : {}; - this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); - }, - - /** - * Method: destroy - * nullify references to prevent circular references and memory leaks - */ - destroy: function() { - - //remove the popup from the map - if ((this.layer != null) && (this.layer.map != null)) { - if (this.popup != null) { - this.layer.map.removePopup(this.popup); - } - } - // remove the marker from the layer - if (this.layer != null && this.marker != null) { - this.layer.removeMarker(this.marker); - } - - this.layer = null; - this.id = null; - this.lonlat = null; - this.data = null; - if (this.marker != null) { - this.destroyMarker(this.marker); - this.marker = null; - } - if (this.popup != null) { - this.destroyPopup(this.popup); - this.popup = null; - } - }, - - /** - * Method: onScreen - * - * Returns: - * {Boolean} Whether or not the feature is currently visible on screen - * (based on its 'lonlat' property) - */ - onScreen:function() { - - var onScreen = false; - if ((this.layer != null) && (this.layer.map != null)) { - var screenBounds = this.layer.map.getExtent(); - onScreen = screenBounds.containsLonLat(this.lonlat); - } - return onScreen; - }, - - - /** - * Method: createMarker - * Based on the data associated with the Feature, create and return a marker object. - * - * Returns: - * {} A Marker Object created from the 'lonlat' and 'icon' properties - * set in this.data. If no 'lonlat' is set, returns null. If no - * 'icon' is set, OpenLayers.Marker() will load the default image. - * - * Note - this.marker is set to return value - * - */ - createMarker: function() { - - if (this.lonlat != null) { - this.marker = new OpenLayers.Marker(this.lonlat, this.data.icon); - } - return this.marker; - }, - - /** - * Method: destroyMarker - * Destroys marker. - * If user overrides the createMarker() function, s/he should be able - * to also specify an alternative function for destroying it - */ - destroyMarker: function() { - this.marker.destroy(); - }, - - /** - * Method: createPopup - * Creates a popup object created from the 'lonlat', 'popupSize', - * and 'popupContentHTML' properties set in this.data. It uses - * this.marker.icon as default anchor. - * - * If no 'lonlat' is set, returns null. - * If no this.marker has been created, no anchor is sent. - * - * Note - the returned popup object is 'owned' by the feature, so you - * cannot use the popup's destroy method to discard the popup. - * Instead, you must use the feature's destroyPopup - * - * Note - this.popup is set to return value - * - * Parameters: - * closeBox - {Boolean} create popup with closebox or not - * - * Returns: - * {} Returns the created popup, which is also set - * as 'popup' property of this feature. Will be of whatever type - * specified by this feature's 'popupClass' property, but must be - * of type . - * - */ - createPopup: function(closeBox) { - - if (this.lonlat != null) { - if (!this.popup) { - var anchor = (this.marker) ? this.marker.icon : null; - var popupClass = this.popupClass ? - this.popupClass : OpenLayers.Popup.Anchored; - this.popup = new popupClass(this.id + "_popup", - this.lonlat, - this.data.popupSize, - this.data.popupContentHTML, - anchor, - closeBox); - } - if (this.data.overflow != null) { - this.popup.contentDiv.style.overflow = this.data.overflow; - } - - this.popup.feature = this; - } - return this.popup; - }, - - - /** - * Method: destroyPopup - * Destroys the popup created via createPopup. - * - * As with the marker, if user overrides the createPopup() function, s/he - * should also be able to override the destruction - */ - destroyPopup: function() { - if (this.popup) { - this.popup.feature = null; - this.popup.destroy(); - this.popup = null; - } - }, - - CLASS_NAME: "OpenLayers.Feature" -}); -/* ====================================================================== - OpenLayers/Feature/Vector.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. */ - -// TRASH THIS -OpenLayers.State = { - /** states */ - UNKNOWN: 'Unknown', - INSERT: 'Insert', - UPDATE: 'Update', - DELETE: 'Delete' -}; - -/** - * @requires OpenLayers/Feature.js - * @requires OpenLayers/Util.js - */ - -/** - * Class: OpenLayers.Feature.Vector - * Vector features use the OpenLayers.Geometry classes as geometry description. - * They have an 'attributes' property, which is the data object, and a 'style' - * property, the default values of which are defined in the - * objects. - * - * Inherits from: - * - - */ -OpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, { - - /** - * Property: fid - * {String} - */ - fid: null, - - /** - * APIProperty: geometry - * {} - */ - geometry: null, - - /** - * APIProperty: attributes - * {Object} This object holds arbitrary, serializable properties that - * describe the feature. - */ - attributes: null, - - /** - * Property: bounds - * {} The box bounding that feature's geometry, that - * property can be set by an object when - * deserializing the feature, so in most cases it represents an - * information set by the server. - */ - bounds: null, - - /** - * Property: state - * {String} - */ - state: null, - - /** - * APIProperty: style - * {Object} - */ - style: null, - - /** - * APIProperty: url - * {String} If this property is set it will be taken into account by - * {} when upadting or deleting the feature. - */ - url: null, - - /** - * Property: renderIntent - * {String} rendering intent currently being used - */ - renderIntent: "default", - - /** - * APIProperty: modified - * {Object} An object with the originals of the geometry and attributes of - * the feature, if they were changed. Currently this property is only read - * by , and written by - * , which sets the geometry property. - * Applications can set the originals of modified attributes in the - * attributes property. Note that applications have to check if this - * object and the attributes property is already created before using it. - * After a change made with ModifyFeature, this object could look like - * - * (code) - * { - * geometry: >Object - * } - * (end) - * - * When an application has made changes to feature attributes, it could - * have set the attributes to something like this: - * - * (code) - * { - * attributes: { - * myAttribute: "original" - * } - * } - * (end) - * - * Note that only checks for truthy values in - * *modified.geometry* and the attribute names in *modified.attributes*, - * but it is recommended to set the original values (and not just true) as - * attribute value, so applications could use this information to undo - * changes. - */ - modified: null, - - /** - * Constructor: OpenLayers.Feature.Vector - * Create a vector feature. - * - * Parameters: - * geometry - {} The geometry that this feature - * represents. - * attributes - {Object} An optional object that will be mapped to the - * property. - * style - {Object} An optional style object. - */ - initialize: function(geometry, attributes, style) { - OpenLayers.Feature.prototype.initialize.apply(this, - [null, null, attributes]); - this.lonlat = null; - this.geometry = geometry ? geometry : null; - this.state = null; - this.attributes = {}; - if (attributes) { - this.attributes = OpenLayers.Util.extend(this.attributes, - attributes); - } - this.style = style ? style : null; - }, - - /** - * Method: destroy - * nullify references to prevent circular references and memory leaks - */ - destroy: function() { - if (this.layer) { - this.layer.removeFeatures(this); - this.layer = null; - } - - this.geometry = null; - this.modified = null; - OpenLayers.Feature.prototype.destroy.apply(this, arguments); - }, - - /** - * Method: clone - * Create a clone of this vector feature. Does not set any non-standard - * properties. - * - * Returns: - * {} An exact clone of this vector feature. - */ - clone: function () { - return new OpenLayers.Feature.Vector( - this.geometry ? this.geometry.clone() : null, - this.attributes, - this.style); - }, - - /** - * Method: onScreen - * Determine whether the feature is within the map viewport. This method - * tests for an intersection between the geometry and the viewport - * bounds. If a more effecient but less precise geometry bounds - * intersection is desired, call the method with the boundsOnly - * parameter true. - * - * Parameters: - * boundsOnly - {Boolean} Only test whether a feature's bounds intersects - * the viewport bounds. Default is false. If false, the feature's - * geometry must intersect the viewport for onScreen to return true. - * - * Returns: - * {Boolean} The feature is currently visible on screen (optionally - * based on its bounds if boundsOnly is true). - */ - onScreen:function(boundsOnly) { - var onScreen = false; - if(this.layer && this.layer.map) { - var screenBounds = this.layer.map.getExtent(); - if(boundsOnly) { - var featureBounds = this.geometry.getBounds(); - onScreen = screenBounds.intersectsBounds(featureBounds); - } else { - var screenPoly = screenBounds.toGeometry(); - onScreen = screenPoly.intersects(this.geometry); - } - } - return onScreen; - }, - - /** - * Method: getVisibility - * Determine whether the feature is displayed or not. It may not displayed - * because: - * - its style display property is set to 'none', - * - it doesn't belong to any layer, - * - the styleMap creates a symbolizer with display property set to 'none' - * for it, - * - the layer which it belongs to is not visible. - * - * Returns: - * {Boolean} The feature is currently displayed. - */ - getVisibility: function() { - return !(this.style && this.style.display == 'none' || - !this.layer || - this.layer && this.layer.styleMap && - this.layer.styleMap.createSymbolizer(this, this.renderIntent).display == 'none' || - this.layer && !this.layer.getVisibility()); - }, - - /** - * Method: createMarker - * HACK - we need to decide if all vector features should be able to - * create markers - * - * Returns: - * {} For now just returns null - */ - createMarker: function() { - return null; - }, - - /** - * Method: destroyMarker - * HACK - we need to decide if all vector features should be able to - * delete markers - * - * If user overrides the createMarker() function, s/he should be able - * to also specify an alternative function for destroying it - */ - destroyMarker: function() { - // pass - }, - - /** - * Method: createPopup - * HACK - we need to decide if all vector features should be able to - * create popups - * - * Returns: - * {} For now just returns null - */ - createPopup: function() { - return null; - }, - - /** - * Method: atPoint - * Determins whether the feature intersects with the specified location. - * - * 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 feature is at the specified location - */ - atPoint: function(lonlat, toleranceLon, toleranceLat) { - var atPoint = false; - if(this.geometry) { - atPoint = this.geometry.atPoint(lonlat, toleranceLon, - toleranceLat); - } - return atPoint; - }, - - /** - * Method: destroyPopup - * HACK - we need to decide if all vector features should be able to - * delete popups - */ - destroyPopup: function() { - // pass - }, - - /** - * Method: move - * Moves the feature and redraws it at its new location - * - * Parameters: - * location - { or } the - * location to which to move the feature. - */ - move: function(location) { - - if(!this.layer || !this.geometry.move){ - //do nothing if no layer or immoveable geometry - return undefined; - } - - var pixel; - if (location.CLASS_NAME == "OpenLayers.LonLat") { - pixel = this.layer.getViewPortPxFromLonLat(location); - } else { - pixel = location; - } - - var lastPixel = this.layer.getViewPortPxFromLonLat(this.geometry.getBounds().getCenterLonLat()); - var res = this.layer.map.getResolution(); - this.geometry.move(res * (pixel.x - lastPixel.x), - res * (lastPixel.y - pixel.y)); - this.layer.drawFeature(this); - return lastPixel; - }, - - /** - * Method: toState - * Sets the new state - * - * Parameters: - * state - {String} - */ - toState: function(state) { - if (state == OpenLayers.State.UPDATE) { - switch (this.state) { - case OpenLayers.State.UNKNOWN: - case OpenLayers.State.DELETE: - this.state = state; - break; - case OpenLayers.State.UPDATE: - case OpenLayers.State.INSERT: - break; - } - } else if (state == OpenLayers.State.INSERT) { - switch (this.state) { - case OpenLayers.State.UNKNOWN: - break; - default: - this.state = state; - break; - } - } else if (state == OpenLayers.State.DELETE) { - switch (this.state) { - case OpenLayers.State.INSERT: - // the feature should be destroyed - break; - case OpenLayers.State.DELETE: - break; - case OpenLayers.State.UNKNOWN: - case OpenLayers.State.UPDATE: - this.state = state; - break; - } - } else if (state == OpenLayers.State.UNKNOWN) { - this.state = state; - } - }, - - CLASS_NAME: "OpenLayers.Feature.Vector" -}); - - -/** - * Constant: OpenLayers.Feature.Vector.style - * OpenLayers features can have a number of style attributes. The 'default' - * style will typically be used if no other style is specified. These - * styles correspond for the most part, to the styling properties defined - * by the SVG standard. - * Information on fill properties: http://www.w3.org/TR/SVG/painting.html#FillProperties - * Information on stroke properties: http://www.w3.org/TR/SVG/painting.html#StrokeProperties - * - * Symbolizer properties: - * fill - {Boolean} Set to false if no fill is desired. - * fillColor - {String} Hex fill color. Default is "#ee9900". - * fillOpacity - {Number} Fill opacity (0-1). Default is 0.4 - * stroke - {Boolean} Set to false if no stroke is desired. - * strokeColor - {String} Hex stroke color. Default is "#ee9900". - * strokeOpacity - {Number} Stroke opacity (0-1). Default is 1. - * strokeWidth - {Number} Pixel stroke width. Default is 1. - * strokeLinecap - {String} Stroke cap type. Default is "round". [butt | round | square] - * strokeDashstyle - {String} Stroke dash style. Default is "solid". [dot | dash | dashdot | longdash | longdashdot | solid] - * graphic - {Boolean} Set to false if no graphic is desired. - * pointRadius - {Number} Pixel point radius. Default is 6. - * pointerEvents - {String} Default is "visiblePainted". - * cursor - {String} Default is "". - * externalGraphic - {String} Url to an external graphic that will be used for rendering points. - * graphicWidth - {Number} Pixel width for sizing an external graphic. - * graphicHeight - {Number} Pixel height for sizing an external graphic. - * graphicOpacity - {Number} Opacity (0-1) for an external graphic. - * graphicXOffset - {Number} Pixel offset along the positive x axis for displacing an external graphic. - * graphicYOffset - {Number} Pixel offset along the positive y axis for displacing an external graphic. - * rotation - {Number} For point symbolizers, this is the rotation of a graphic in the clockwise direction about its center point (or any point off center as specified by graphicXOffset and graphicYOffset). - * graphicZIndex - {Number} The integer z-index value to use in rendering. - * graphicName - {String} Named graphic to use when rendering points. Supported values include "circle" (default), - * "square", "star", "x", "cross", "triangle". - * graphicTitle - {String} Tooltip when hovering over a feature. *deprecated*, use title instead - * title - {String} Tooltip when hovering over a feature. Not supported by the canvas renderer. - * backgroundGraphic - {String} Url to a graphic to be used as the background under an externalGraphic. - * backgroundGraphicZIndex - {Number} The integer z-index value to use in rendering the background graphic. - * backgroundXOffset - {Number} The x offset (in pixels) for the background graphic. - * backgroundYOffset - {Number} The y offset (in pixels) for the background graphic. - * backgroundHeight - {Number} The height of the background graphic. If not provided, the graphicHeight will be used. - * backgroundWidth - {Number} The width of the background width. If not provided, the graphicWidth will be used. - * label - {String} The text for an optional label. For browsers that use the canvas renderer, this requires either - * fillText or mozDrawText to be available. - * labelAlign - {String} Label alignment. This specifies the insertion point relative to the text. It is a string - * composed of two characters. The first character is for the horizontal alignment, the second for the vertical - * alignment. Valid values for horizontal alignment: "l"=left, "c"=center, "r"=right. Valid values for vertical - * alignment: "t"=top, "m"=middle, "b"=bottom. Example values: "lt", "cm", "rb". Default is "cm". - * labelXOffset - {Number} Pixel offset along the positive x axis for displacing the label. Not supported by the canvas renderer. - * labelYOffset - {Number} Pixel offset along the positive y axis for displacing the label. Not supported by the canvas renderer. - * labelSelect - {Boolean} If set to true, labels will be selectable using SelectFeature or similar controls. - * Default is false. - * labelOutlineColor - {String} The color of the label outline. Default is 'white'. Only supported by the canvas & SVG renderers. - * labelOutlineWidth - {Number} The width of the label outline. Default is 3, set to 0 or null to disable. Only supported by the SVG renderers. - * labelOutlineOpacity - {Number} The opacity (0-1) of the label outline. Default is fontOpacity. Only supported by the canvas & SVG renderers. - * fontColor - {String} The font color for the label, to be provided like CSS. - * fontOpacity - {Number} Opacity (0-1) for the label - * fontFamily - {String} The font family for the label, to be provided like in CSS. - * fontSize - {String} The font size for the label, to be provided like in CSS. - * fontStyle - {String} The font style for the label, to be provided like in CSS. - * fontWeight - {String} The font weight for the label, to be provided like in CSS. - * display - {String} Symbolizers will have no effect if display is set to "none". All other values have no effect. - */ -OpenLayers.Feature.Vector.style = { - 'default': { - fillColor: "#ee9900", - fillOpacity: 0.4, - hoverFillColor: "white", - hoverFillOpacity: 0.8, - strokeColor: "#ee9900", - strokeOpacity: 1, - strokeWidth: 1, - strokeLinecap: "round", - strokeDashstyle: "solid", - hoverStrokeColor: "red", - hoverStrokeOpacity: 1, - hoverStrokeWidth: 0.2, - pointRadius: 6, - hoverPointRadius: 1, - hoverPointUnit: "%", - pointerEvents: "visiblePainted", - cursor: "inherit", - fontColor: "#000000", - labelAlign: "cm", - labelOutlineColor: "white", - labelOutlineWidth: 3 - }, - 'select': { - fillColor: "blue", - fillOpacity: 0.4, - hoverFillColor: "white", - hoverFillOpacity: 0.8, - strokeColor: "blue", - strokeOpacity: 1, - strokeWidth: 2, - strokeLinecap: "round", - strokeDashstyle: "solid", - hoverStrokeColor: "red", - hoverStrokeOpacity: 1, - hoverStrokeWidth: 0.2, - pointRadius: 6, - hoverPointRadius: 1, - hoverPointUnit: "%", - pointerEvents: "visiblePainted", - cursor: "pointer", - fontColor: "#000000", - labelAlign: "cm", - labelOutlineColor: "white", - labelOutlineWidth: 3 - - }, - 'temporary': { - fillColor: "#66cccc", - fillOpacity: 0.2, - hoverFillColor: "white", - hoverFillOpacity: 0.8, - strokeColor: "#66cccc", - strokeOpacity: 1, - strokeLinecap: "round", - strokeWidth: 2, - strokeDashstyle: "solid", - hoverStrokeColor: "red", - hoverStrokeOpacity: 1, - hoverStrokeWidth: 0.2, - pointRadius: 6, - hoverPointRadius: 1, - hoverPointUnit: "%", - pointerEvents: "visiblePainted", - cursor: "inherit", - fontColor: "#000000", - labelAlign: "cm", - labelOutlineColor: "white", - labelOutlineWidth: 3 - - }, - 'delete': { - display: "none" - } -}; -/* ====================================================================== - 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} 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 0) { - appliedRules = true; - for(var i=0, len=elseRules.length; i 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)} - */ - 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} 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} 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. */ - - -/** - * @requires OpenLayers/BaseTypes/Class.js - * @requires OpenLayers/Util.js - * @requires OpenLayers/Style.js - */ - -/** - * Class: OpenLayers.Filter - * This class represents an OGC Filter. - */ -OpenLayers.Filter = OpenLayers.Class({ - - /** - * Constructor: OpenLayers.Filter - * This class represents a generic filter. - * - * Parameters: - * options - {Object} Optional object whose properties will be set on the - * instance. - * - * Returns: - * {} - */ - initialize: function(options) { - OpenLayers.Util.extend(this, options); - }, - - /** - * APIMethod: destroy - * Remove reference to anything added. - */ - destroy: function() { - }, - - /** - * APIMethod: evaluate - * Evaluates this filter in a specific context. Instances or subclasses - * are supposed to override this method. - * - * Parameters: - * context - {Object} Context to use in evaluating the filter. If a vector - * feature is provided, the feature.attributes will be used as context. - * - * Returns: - * {Boolean} The filter applies. - */ - evaluate: function(context) { - return true; - }, - - /** - * APIMethod: clone - * Clones this filter. Should be implemented by subclasses. - * - * Returns: - * {} Clone of this filter. - */ - clone: function() { - return null; - }, - - /** - * APIMethod: toString - * - * Returns: - * {String} Include in your build to get a CQL - * representation of the filter returned. Otherwise "[Object object]" - * will be returned. - */ - toString: function() { - var string; - if (OpenLayers.Format && OpenLayers.Format.CQL) { - string = OpenLayers.Format.CQL.prototype.write(this); - } else { - string = Object.prototype.toString.call(this); - } - return string; - }, - - CLASS_NAME: "OpenLayers.Filter" -}); -/* ====================================================================== - OpenLayers/Filter/FeatureId.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/Filter.js - */ - -/** - * Class: OpenLayers.Filter.FeatureId - * This class represents a ogc:FeatureId Filter, as being used for rule-based SLD - * styling - * - * Inherits from: - * - - */ -OpenLayers.Filter.FeatureId = OpenLayers.Class(OpenLayers.Filter, { - - /** - * APIProperty: fids - * {Array(String)} Feature Ids to evaluate this rule against. - * To be passed inside the params object. - */ - fids: null, - - /** - * Property: type - * {String} Type to identify this filter. - */ - type: "FID", - - /** - * Constructor: OpenLayers.Filter.FeatureId - * Creates an ogc:FeatureId rule. - * - * Parameters: - * options - {Object} An optional object with properties to set on the - * rule - * - * Returns: - * {} - */ - initialize: function(options) { - this.fids = []; - OpenLayers.Filter.prototype.initialize.apply(this, [options]); - }, - - /** - * APIMethod: evaluate - * evaluates this rule for a specific feature - * - * Parameters: - * feature - {} feature to apply the rule to. - * For vector features, the check is run against the fid, - * for plain features against the id. - * - * Returns: - * {Boolean} true if the rule applies, false if it does not - */ - evaluate: function(feature) { - for (var i=0, len=this.fids.length; i} Clone of this filter. - */ - clone: function() { - var filter = new OpenLayers.Filter.FeatureId(); - OpenLayers.Util.extend(filter, this); - filter.fids = this.fids.slice(); - return filter; - }, - - CLASS_NAME: "OpenLayers.Filter.FeatureId" -}); -/* ====================================================================== - OpenLayers/Filter/Logical.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/Filter.js - */ - -/** - * Class: OpenLayers.Filter.Logical - * This class represents ogc:And, ogc:Or and ogc:Not rules. - * - * Inherits from: - * - - */ -OpenLayers.Filter.Logical = OpenLayers.Class(OpenLayers.Filter, { - - /** - * APIProperty: filters - * {Array()} Child filters for this filter. - */ - filters: null, - - /** - * APIProperty: type - * {String} type of logical operator. Available types are: - * - OpenLayers.Filter.Logical.AND = "&&"; - * - OpenLayers.Filter.Logical.OR = "||"; - * - OpenLayers.Filter.Logical.NOT = "!"; - */ - type: null, - - /** - * Constructor: OpenLayers.Filter.Logical - * Creates a logical filter (And, Or, Not). - * - * Parameters: - * options - {Object} An optional object with properties to set on the - * filter. - * - * Returns: - * {} - */ - initialize: function(options) { - this.filters = []; - OpenLayers.Filter.prototype.initialize.apply(this, [options]); - }, - - /** - * APIMethod: destroy - * Remove reference to child filters. - */ - destroy: function() { - this.filters = null; - OpenLayers.Filter.prototype.destroy.apply(this); - }, - - /** - * APIMethod: evaluate - * Evaluates this filter in a specific context. - * - * Parameters: - * context - {Object} Context to use in evaluating the filter. A vector - * feature may also be provided to evaluate feature attributes in - * comparison filters or geometries in spatial filters. - * - * Returns: - * {Boolean} The filter applies. - */ - evaluate: function(context) { - var i, len; - switch(this.type) { - case OpenLayers.Filter.Logical.AND: - for (i=0, len=this.filters.length; i} Clone of this filter. - */ - clone: function() { - var filters = []; - for(var i=0, len=this.filters.length; i - */ -OpenLayers.Filter.Comparison = OpenLayers.Class(OpenLayers.Filter, { - - /** - * APIProperty: type - * {String} type: type of the comparison. This is one of - * - OpenLayers.Filter.Comparison.EQUAL_TO = "=="; - * - OpenLayers.Filter.Comparison.NOT_EQUAL_TO = "!="; - * - OpenLayers.Filter.Comparison.LESS_THAN = "<"; - * - OpenLayers.Filter.Comparison.GREATER_THAN = ">"; - * - OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO = "<="; - * - OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO = ">="; - * - OpenLayers.Filter.Comparison.BETWEEN = ".."; - * - OpenLayers.Filter.Comparison.LIKE = "~"; - * - OpenLayers.Filter.Comparison.IS_NULL = "NULL"; - */ - type: null, - - /** - * APIProperty: property - * {String} - * name of the context property to compare - */ - property: null, - - /** - * APIProperty: value - * {Number} or {String} - * comparison value for binary comparisons. In the case of a String, this - * can be a combination of text and propertyNames in the form - * "literal ${propertyName}" - */ - value: null, - - /** - * Property: matchCase - * {Boolean} Force case sensitive searches for EQUAL_TO and NOT_EQUAL_TO - * comparisons. The Filter Encoding 1.1 specification added a matchCase - * attribute to ogc:PropertyIsEqualTo and ogc:PropertyIsNotEqualTo - * elements. This property will be serialized with those elements only - * if using the v1.1.0 filter format. However, when evaluating filters - * here, the matchCase property will always be respected (for EQUAL_TO - * and NOT_EQUAL_TO). Default is true. - */ - matchCase: true, - - /** - * APIProperty: lowerBoundary - * {Number} or {String} - * lower boundary for between comparisons. In the case of a String, this - * can be a combination of text and propertyNames in the form - * "literal ${propertyName}" - */ - lowerBoundary: null, - - /** - * APIProperty: upperBoundary - * {Number} or {String} - * upper boundary for between comparisons. In the case of a String, this - * can be a combination of text and propertyNames in the form - * "literal ${propertyName}" - */ - upperBoundary: null, - - /** - * Constructor: OpenLayers.Filter.Comparison - * Creates a comparison rule. - * - * Parameters: - * options - {Object} An optional object with properties to set on the - * rule - * - * Returns: - * {} - */ - initialize: function(options) { - OpenLayers.Filter.prototype.initialize.apply(this, [options]); - // since matchCase on PropertyIsLike is not schema compliant, we only - // want to use this if explicitly asked for - if (this.type === OpenLayers.Filter.Comparison.LIKE - && options.matchCase === undefined) { - this.matchCase = null; - } - }, - - /** - * APIMethod: evaluate - * Evaluates this filter in a specific context. - * - * Parameters: - * context - {Object} Context to use in evaluating the filter. If a vector - * feature is provided, the feature.attributes will be used as context. - * - * Returns: - * {Boolean} The filter applies. - */ - evaluate: function(context) { - if (context instanceof OpenLayers.Feature.Vector) { - context = context.attributes; - } - var result = false; - var got = context[this.property]; - var exp; - switch(this.type) { - case OpenLayers.Filter.Comparison.EQUAL_TO: - exp = this.value; - if(!this.matchCase && - typeof got == "string" && typeof exp == "string") { - result = (got.toUpperCase() == exp.toUpperCase()); - } else { - result = (got == exp); - } - break; - case OpenLayers.Filter.Comparison.NOT_EQUAL_TO: - exp = this.value; - if(!this.matchCase && - typeof got == "string" && typeof exp == "string") { - result = (got.toUpperCase() != exp.toUpperCase()); - } else { - result = (got != exp); - } - break; - case OpenLayers.Filter.Comparison.LESS_THAN: - result = got < this.value; - break; - case OpenLayers.Filter.Comparison.GREATER_THAN: - result = got > this.value; - break; - case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO: - result = got <= this.value; - break; - case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO: - result = got >= this.value; - break; - case OpenLayers.Filter.Comparison.BETWEEN: - result = (got >= this.lowerBoundary) && - (got <= this.upperBoundary); - break; - case OpenLayers.Filter.Comparison.LIKE: - var regexp = new RegExp(this.value, "gi"); - result = regexp.test(got); - break; - case OpenLayers.Filter.Comparison.IS_NULL: - result = (got === null); - break; - } - return result; - }, - - /** - * APIMethod: value2regex - * Converts the value of this rule into a regular expression string, - * according to the wildcard characters specified. This method has to - * be called after instantiation of this class, if the value is not a - * regular expression already. - * - * Parameters: - * wildCard - {Char} wildcard character in the above value, default - * is "*" - * singleChar - {Char} single-character wildcard in the above value - * default is "." - * escapeChar - {Char} escape character in the above value, default is - * "!" - * - * Returns: - * {String} regular expression string - */ - value2regex: function(wildCard, singleChar, escapeChar) { - if (wildCard == ".") { - throw new Error("'.' is an unsupported wildCard character for " + - "OpenLayers.Filter.Comparison"); - } - - - // set UMN MapServer defaults for unspecified parameters - wildCard = wildCard ? wildCard : "*"; - singleChar = singleChar ? singleChar : "."; - escapeChar = escapeChar ? escapeChar : "!"; - - this.value = this.value.replace( - new RegExp("\\"+escapeChar+"(.|$)", "g"), "\\$1"); - this.value = this.value.replace( - new RegExp("\\"+singleChar, "g"), "."); - this.value = this.value.replace( - new RegExp("\\"+wildCard, "g"), ".*"); - this.value = this.value.replace( - new RegExp("\\\\.\\*", "g"), "\\"+wildCard); - this.value = this.value.replace( - new RegExp("\\\\\\.", "g"), "\\"+singleChar); - - return this.value; - }, - - /** - * Method: regex2value - * Convert the value of this rule from a regular expression string into an - * ogc literal string using a wildCard of *, a singleChar of ., and an - * escape of !. Leaves the property unmodified. - * - * Returns: - * {String} A string value. - */ - regex2value: function() { - - var value = this.value; - - // replace ! with !! - value = value.replace(/!/g, "!!"); - - // replace \. with !. (watching out for \\.) - value = value.replace(/(\\)?\\\./g, function($0, $1) { - return $1 ? $0 : "!."; - }); - - // replace \* with #* (watching out for \\*) - value = value.replace(/(\\)?\\\*/g, function($0, $1) { - return $1 ? $0 : "!*"; - }); - - // replace \\ with \ - value = value.replace(/\\\\/g, "\\"); - - // convert .* to * (the sequence #.* is not allowed) - value = value.replace(/\.\*/g, "*"); - - return value; - }, - - /** - * APIMethod: clone - * Clones this filter. - * - * Returns: - * {} Clone of this filter. - */ - clone: function() { - return OpenLayers.Util.extend(new OpenLayers.Filter.Comparison(), this); - }, - - CLASS_NAME: "OpenLayers.Filter.Comparison" -}); - - -OpenLayers.Filter.Comparison.EQUAL_TO = "=="; -OpenLayers.Filter.Comparison.NOT_EQUAL_TO = "!="; -OpenLayers.Filter.Comparison.LESS_THAN = "<"; -OpenLayers.Filter.Comparison.GREATER_THAN = ">"; -OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO = "<="; -OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO = ">="; -OpenLayers.Filter.Comparison.BETWEEN = ".."; -OpenLayers.Filter.Comparison.LIKE = "~"; -OpenLayers.Filter.Comparison.IS_NULL = "NULL"; -/* ====================================================================== - OpenLayers/Format/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. */ - -/** - * @requires OpenLayers/Format/XML/VersionedOGC.js - * @requires OpenLayers/Filter/FeatureId.js - * @requires OpenLayers/Filter/Logical.js - * @requires OpenLayers/Filter/Comparison.js - */ - -/** - * Class: OpenLayers.Format.Filter - * Read/Write ogc:Filter. Create a new instance with the - * constructor. - * - * Inherits from: - * - - */ -OpenLayers.Format.Filter = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, { - - /** - * APIProperty: defaultVersion - * {String} Version number to assume if none found. Default is "1.0.0". - */ - defaultVersion: "1.0.0", - - /** - * APIMethod: write - * Write an ogc:Filter given a filter object. - * - * Parameters: - * filter - {} An filter. - * options - {Object} Optional configuration object. - * - * Returns: - * {Elment} An ogc:Filter element node. - */ - - /** - * APIMethod: read - * Read and Filter doc and return an object representing the Filter. - * - * Parameters: - * data - {String | DOMElement} Data to read. - * - * Returns: - * {} A filter object. - */ - - CLASS_NAME: "OpenLayers.Format.Filter" -}); -/* ====================================================================== - OpenLayers/Format/WFST.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.js - */ - -/** - * Function: OpenLayers.Format.WFST - * Used to create a versioned WFS protocol. Default version is 1.0.0. - * - * Returns: - * {} A WFST format of the given version. - */ -OpenLayers.Format.WFST = function(options) { - options = OpenLayers.Util.applyDefaults( - options, OpenLayers.Format.WFST.DEFAULTS - ); - var cls = OpenLayers.Format.WFST["v"+options.version.replace(/\./g, "_")]; - if(!cls) { - throw "Unsupported WFST version: " + options.version; - } - return new cls(options); -}; - -/** - * Constant: OpenLayers.Format.WFST.DEFAULTS - * {Object} Default properties for the WFST format. - */ -OpenLayers.Format.WFST.DEFAULTS = { - "version": "1.0.0" -}; -/* ====================================================================== - OpenLayers/Filter/Spatial.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/Filter.js - */ - -/** - * Class: OpenLayers.Filter.Spatial - * This class represents a spatial filter. - * Currently implemented: BBOX, DWithin and Intersects - * - * Inherits from: - * - - */ -OpenLayers.Filter.Spatial = OpenLayers.Class(OpenLayers.Filter, { - - /** - * APIProperty: type - * {String} Type of spatial filter. - * - * The type should be one of: - * - OpenLayers.Filter.Spatial.BBOX - * - OpenLayers.Filter.Spatial.INTERSECTS - * - OpenLayers.Filter.Spatial.DWITHIN - * - OpenLayers.Filter.Spatial.WITHIN - * - OpenLayers.Filter.Spatial.CONTAINS - */ - type: null, - - /** - * APIProperty: property - * {String} Name of the context property to compare. - */ - property: null, - - /** - * APIProperty: value - * { || } The bounds or geometry - * to be used by the filter. Use bounds for BBOX filters and geometry - * for INTERSECTS or DWITHIN filters. - */ - value: null, - - /** - * APIProperty: distance - * {Number} The distance to use in a DWithin spatial filter. - */ - distance: null, - - /** - * APIProperty: distanceUnits - * {String} The units to use for the distance, e.g. 'm'. - */ - distanceUnits: null, - - /** - * Constructor: OpenLayers.Filter.Spatial - * Creates a spatial filter. - * - * Parameters: - * options - {Object} An optional object with properties to set on the - * filter. - * - * Returns: - * {} - */ - - /** - * Method: evaluate - * Evaluates this filter for a specific feature. - * - * Parameters: - * feature - {} feature to apply the filter to. - * - * Returns: - * {Boolean} The feature meets filter criteria. - */ - evaluate: function(feature) { - var intersect = false; - switch(this.type) { - case OpenLayers.Filter.Spatial.BBOX: - case OpenLayers.Filter.Spatial.INTERSECTS: - if(feature.geometry) { - var geom = this.value; - if(this.value.CLASS_NAME == "OpenLayers.Bounds") { - geom = this.value.toGeometry(); - } - if(feature.geometry.intersects(geom)) { - intersect = true; - } - } - break; - default: - throw new Error('evaluate is not implemented for this filter type.'); - } - return intersect; - }, - - /** - * APIMethod: clone - * Clones this filter. - * - * Returns: - * {} Clone of this filter. - */ - clone: function() { - var options = OpenLayers.Util.applyDefaults({ - value: this.value && this.value.clone && this.value.clone() - }, this); - return new OpenLayers.Filter.Spatial(options); - }, - CLASS_NAME: "OpenLayers.Filter.Spatial" -}); - -OpenLayers.Filter.Spatial.BBOX = "BBOX"; -OpenLayers.Filter.Spatial.INTERSECTS = "INTERSECTS"; -OpenLayers.Filter.Spatial.DWITHIN = "DWITHIN"; -OpenLayers.Filter.Spatial.WITHIN = "WITHIN"; -OpenLayers.Filter.Spatial.CONTAINS = "CONTAINS"; -/* ====================================================================== - OpenLayers/Format/WFST/v1.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/WFST.js - * @requires OpenLayers/Filter/Spatial.js - * @requires OpenLayers/Filter/FeatureId.js - */ - -/** - * Class: OpenLayers.Format.WFST.v1 - * Superclass for WFST parsers. - * - * Inherits from: - * - - */ -OpenLayers.Format.WFST.v1 = OpenLayers.Class(OpenLayers.Format.XML, { - - /** - * Property: namespaces - * {Object} Mapping of namespace aliases to namespace URIs. - */ - namespaces: { - xlink: "http://www.w3.org/1999/xlink", - xsi: "http://www.w3.org/2001/XMLSchema-instance", - wfs: "http://www.opengis.net/wfs", - gml: "http://www.opengis.net/gml", - ogc: "http://www.opengis.net/ogc", - ows: "http://www.opengis.net/ows" - }, - - /** - * Property: defaultPrefix - */ - defaultPrefix: "wfs", - - /** - * Property: version - * {String} WFS version number. - */ - version: null, - - /** - * Property: schemaLocation - * {String} Schema location for a particular minor version. - */ - schemaLocations: null, - - /** - * APIProperty: srsName - * {String} URI for spatial reference system. - */ - srsName: null, - - /** - * APIProperty: extractAttributes - * {Boolean} Extract attributes from GML. Default is true. - */ - extractAttributes: true, - - /** - * APIProperty: xy - * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x) - * Changing is not recommended, a new Format should be instantiated. - */ - xy: true, - - /** - * Property: stateName - * {Object} Maps feature states to node names. - */ - stateName: null, - - /** - * Constructor: OpenLayers.Format.WFST.v1 - * Instances of this class are not created directly. Use the - * or - * constructor instead. - * - * Parameters: - * options - {Object} An optional object whose properties will be set on - * this instance. - */ - initialize: function(options) { - // set state name mapping - this.stateName = {}; - this.stateName[OpenLayers.State.INSERT] = "wfs:Insert"; - this.stateName[OpenLayers.State.UPDATE] = "wfs:Update"; - this.stateName[OpenLayers.State.DELETE] = "wfs:Delete"; - OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); - }, - - /** - * Method: getSrsName - */ - getSrsName: function(feature, options) { - var srsName = options && options.srsName; - if(!srsName) { - if(feature && feature.layer) { - srsName = feature.layer.projection.getCode(); - } else { - srsName = this.srsName; - } - } - return srsName; - }, - - /** - * APIMethod: read - * Parse the response from a transaction. Because WFS is split into - * Transaction requests (create, update, and delete) and GetFeature - * requests (read), this method handles parsing of both types of - * responses. - * - * Parameters: - * data - {String | Document} The WFST document to read - * options - {Object} Options for the reader - * - * Valid options properties: - * output - {String} either "features" or "object". The default is - * "features", which means that the method will return an array of - * features. If set to "object", an object with a "features" property - * and other properties read by the parser will be returned. - * - * Returns: - * {Array | Object} Output depending on the output option. - */ - read: function(data, options) { - options = options || {}; - OpenLayers.Util.applyDefaults(options, { - output: "features" - }); - - if(typeof data == "string") { - data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); - } - if(data && data.nodeType == 9) { - data = data.documentElement; - } - var obj = {}; - if(data) { - this.readNode(data, obj, true); - } - if(obj.features && options.output === "features") { - obj = obj.features; - } - return obj; - }, - - /** - * 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: { - "wfs": { - "FeatureCollection": function(node, obj) { - obj.features = []; - this.readChildNodes(node, obj); - } - } - }, - - /** - * Method: write - * Given an array of features, write a WFS transaction. This assumes - * the features have a state property that determines the operation - * type - insert, update, or delete. - * - * Parameters: - * features - {Array()} A list of features. See - * below for a more detailed description of the influence of the - * feature's *modified* property. - * options - {Object} - * - * feature.modified rules: - * If a feature has a modified property set, the following checks will be - * made before a feature's geometry or attribute is included in an Update - * transaction: - * - *modified* is not set at all: The geometry and all attributes will be - * included. - * - *modified.geometry* is set (null or a geometry): The geometry will be - * included. If *modified.attributes* is not set, all attributes will - * be included. - * - *modified.attributes* is set: Only the attributes set (i.e. to null or - * a value) in *modified.attributes* will be included. - * If *modified.geometry* is not set, the geometry will not be included. - * - * Valid options include: - * - *multi* {Boolean} If set to true, geometries will be casted to - * Multi geometries before writing. - * - * Returns: - * {String} A serialized WFS transaction. - */ - write: function(features, options) { - var node = this.writeNode("wfs:Transaction", { - features:features, - options: options - }); - var value = this.schemaLocationAttr(); - if(value) { - this.setAttributeNS( - node, this.namespaces["xsi"], "xsi:schemaLocation", value - ); - } - return OpenLayers.Format.XML.prototype.write.apply(this, [node]); - }, - - /** - * Property: writers - * As a compliment to the readers property, this structure contains public - * writing functions grouped by namespace alias and named like the - * node names they produce. - */ - writers: { - "wfs": { - "GetFeature": function(options) { - var node = this.createElementNSPlus("wfs:GetFeature", { - attributes: { - service: "WFS", - version: this.version, - handle: options && options.handle, - outputFormat: options && options.outputFormat, - maxFeatures: options && options.maxFeatures, - "xsi:schemaLocation": this.schemaLocationAttr(options) - } - }); - if (typeof this.featureType == "string") { - this.writeNode("Query", options, node); - } else { - for (var i=0,len = this.featureType.length; i} - */ - setFilterProperty: function(filter) { - if(filter.filters) { - for(var i=0, len=filter.filters.length; i - * - - */ -OpenLayers.Geometry.Polygon = 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.LinearRing"], - - /** - * Constructor: OpenLayers.Geometry.Polygon - * Constructor for a Polygon geometry. - * The first ring (this.component[0])is the outer bounds of the polygon and - * all subsequent rings (this.component[1-n]) are internal holes. - * - * - * Parameters: - * components - {Array()} - */ - - /** - * APIMethod: getArea - * Calculated by subtracting the areas of the internal holes from the - * area of the outer hole. - * - * Returns: - * {float} The area of the geometry - */ - getArea: function() { - var area = 0.0; - if ( this.components && (this.components.length > 0)) { - area += Math.abs(this.components[0].getArea()); - for (var i=1, len=this.components.length; i} 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 polygon in square meters. - */ - getGeodesicArea: function(projection) { - var area = 0.0; - if(this.components && (this.components.length > 0)) { - area += Math.abs(this.components[0].getGeodesicArea(projection)); - for(var i=1, len=this.components.length; i} - * - * Returns: - * {Boolean | Number} The point is inside the polygon. Returns 1 if the - * point is on an edge. Returns boolean otherwise. - */ - containsPoint: function(point) { - var numRings = this.components.length; - var contained = false; - if(numRings > 0) { - // check exterior ring - 1 means on edge, boolean otherwise - contained = this.components[0].containsPoint(point); - if(contained !== 1) { - if(contained && numRings > 1) { - // check interior rings - var hole; - for(var i=1; i} Any type of geometry. - * - * Returns: - * {Boolean} The input geometry intersects this one. - */ - intersects: function(geometry) { - var intersect = false; - var i, len; - if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { - intersect = this.containsPoint(geometry); - } else if(geometry.CLASS_NAME == "OpenLayers.Geometry.LineString" || - geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") { - // check if rings/linestrings intersect - for(i=0, len=this.components.length; i} 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 result; - // this is the case where we might not be looking for distance to edge - if(!edge && this.intersects(geometry)) { - result = 0; - } else { - result = OpenLayers.Geometry.Collection.prototype.distanceTo.apply( - this, [geometry, options] - ); - } - return result; - }, - - CLASS_NAME: "OpenLayers.Geometry.Polygon" -}); - -/** - * APIMethod: createRegularPolygon - * Create a regular polygon around a radius. Useful for creating circles - * and the like. - * - * Parameters: - * origin - {} center of polygon. - * radius - {Float} distance to vertex, in map units. - * sides - {Integer} Number of sides. 20 approximates a circle. - * rotation - {Float} original angle of rotation, in degrees. - */ -OpenLayers.Geometry.Polygon.createRegularPolygon = function(origin, radius, sides, rotation) { - var angle = Math.PI * ((1/sides) - (1/2)); - if(rotation) { - angle += (rotation / 180) * Math.PI; - } - var rotatedAngle, x, y; - var points = []; - for(var i=0; i - * components. Create a new instance with the - * constructor. - * - * Inherits from: - * - - */ -OpenLayers.Geometry.MultiPolygon = 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.Polygon"], - - /** - * Constructor: OpenLayers.Geometry.MultiPolygon - * Create a new MultiPolygon geometry - * - * Parameters: - * components - {Array()} An array of polygons - * used to generate the MultiPolygon - * - */ - - CLASS_NAME: "OpenLayers.Geometry.MultiPolygon" -}); -/* ====================================================================== - OpenLayers/Format/GML.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/Feature/Vector.js - * @requires OpenLayers/Geometry/Point.js - * @requires OpenLayers/Geometry/MultiPoint.js - * @requires OpenLayers/Geometry/LineString.js - * @requires OpenLayers/Geometry/MultiLineString.js - * @requires OpenLayers/Geometry/Polygon.js - * @requires OpenLayers/Geometry/MultiPolygon.js - */ - -/** - * Class: OpenLayers.Format.GML - * Read/Write GML. Create a new instance with the - * constructor. Supports the GML simple features profile. - * - * Inherits from: - * - - */ -OpenLayers.Format.GML = OpenLayers.Class(OpenLayers.Format.XML, { - - /** - * APIProperty: featureNS - * {String} Namespace used for feature attributes. Default is - * "http://mapserver.gis.umn.edu/mapserver". - */ - featureNS: "http://mapserver.gis.umn.edu/mapserver", - - /** - * APIProperty: featurePrefix - * {String} Namespace alias (or prefix) for feature nodes. Default is - * "feature". - */ - featurePrefix: "feature", - - /** - * APIProperty: featureName - * {String} Element name for features. Default is "featureMember". - */ - featureName: "featureMember", - - /** - * APIProperty: layerName - * {String} Name of data layer. Default is "features". - */ - layerName: "features", - - /** - * APIProperty: geometryName - * {String} Name of geometry element. Defaults to "geometry". - */ - geometryName: "geometry", - - /** - * APIProperty: collectionName - * {String} Name of featureCollection element. - */ - collectionName: "FeatureCollection", - - /** - * APIProperty: gmlns - * {String} GML Namespace. - */ - gmlns: "http://www.opengis.net/gml", - - /** - * APIProperty: extractAttributes - * {Boolean} Extract attributes from GML. - */ - extractAttributes: true, - - /** - * APIProperty: xy - * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x) - * Changing is not recommended, a new Format should be instantiated. - */ - xy: true, - - /** - * Constructor: OpenLayers.Format.GML - * Create a new parser for GML. - * - * Parameters: - * options - {Object} An optional object whose properties will be set on - * this instance. - */ - 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) - }; - OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); - }, - - /** - * APIMethod: read - * Read data from a string, and return a list of features. - * - * Parameters: - * data - {String} or {DOMElement} data to read/parse. - * - * Returns: - * {Array()} An array of features. - */ - read: function(data) { - if(typeof data == "string") { - data = OpenLayers.Format.XML.prototype.read.apply(this, [data]); - } - var featureNodes = this.getElementsByTagNameNS(data.documentElement, - this.gmlns, - this.featureName); - var features = []; - for(var i=0; i 0) { - // only deal with first geometry of this type - parser = this.parseGeometry[type.toLowerCase()]; - if(parser) { - geometry = parser.apply(this, [nodeList[0]]); - if (this.internalProjection && this.externalProjection) { - geometry.transform(this.externalProjection, - this.internalProjection); - } - } else { - throw new TypeError("Unsupported geometry type: " + type); - } - // stop looking for different geometry types - break; - } - } - - var bounds; - var boxNodes = this.getElementsByTagNameNS(node, this.gmlns, "Box"); - for(i=0; i} A point geometry. - */ - point: function(node) { - /** - * Three coordinate variations to consider: - * 1) x y z - * 2) x, y, z - * 3) xy - */ - var nodeList, coordString; - var coords = []; - - // look for - var nodeList = this.getElementsByTagNameNS(node, this.gmlns, "pos"); - if(nodeList.length > 0) { - coordString = nodeList[0].firstChild.nodeValue; - coordString = coordString.replace(this.regExes.trimSpace, ""); - coords = coordString.split(this.regExes.splitSpace); - } - - // look for - if(coords.length == 0) { - nodeList = this.getElementsByTagNameNS(node, this.gmlns, - "coordinates"); - if(nodeList.length > 0) { - coordString = nodeList[0].firstChild.nodeValue; - coordString = coordString.replace(this.regExes.removeSpace, - ""); - coords = coordString.split(","); - } - } - - // look for - if(coords.length == 0) { - nodeList = this.getElementsByTagNameNS(node, this.gmlns, - "coord"); - if(nodeList.length > 0) { - var xList = this.getElementsByTagNameNS(nodeList[0], - this.gmlns, "X"); - var yList = this.getElementsByTagNameNS(nodeList[0], - this.gmlns, "Y"); - if(xList.length > 0 && yList.length > 0) { - coords = [xList[0].firstChild.nodeValue, - yList[0].firstChild.nodeValue]; - } - } - } - - // preserve third dimension - if(coords.length == 2) { - coords[2] = null; - } - - if (this.xy) { - return new OpenLayers.Geometry.Point(coords[0], coords[1], - coords[2]); - } - else{ - return new OpenLayers.Geometry.Point(coords[1], coords[0], - coords[2]); - } - }, - - /** - * Method: parseGeometry.multipoint - * Given a GML node representing a multipoint geometry, create an - * OpenLayers multipoint geometry. - * - * Parameters: - * node - {DOMElement} A GML node. - * - * Returns: - * {} A multipoint geometry. - */ - multipoint: function(node) { - var nodeList = this.getElementsByTagNameNS(node, this.gmlns, - "Point"); - var components = []; - if(nodeList.length > 0) { - var point; - for(var i=0; i} A linestring geometry. - */ - linestring: function(node, ring) { - /** - * Two coordinate variations to consider: - * 1) x0 y0 z0 x1 y1 z1 - * 2) x0, y0, z0 x1, y1, z1 - */ - var nodeList, coordString; - var coords = []; - var points = []; - - // look for - nodeList = this.getElementsByTagNameNS(node, this.gmlns, "posList"); - if(nodeList.length > 0) { - coordString = this.getChildValue(nodeList[0]); - coordString = coordString.replace(this.regExes.trimSpace, ""); - coords = coordString.split(this.regExes.splitSpace); - var dim = parseInt(nodeList[0].getAttribute("dimension")); - var j, x, y, z; - for(var i=0; i - if(coords.length == 0) { - nodeList = this.getElementsByTagNameNS(node, this.gmlns, - "coordinates"); - if(nodeList.length > 0) { - coordString = this.getChildValue(nodeList[0]); - coordString = coordString.replace(this.regExes.trimSpace, - ""); - coordString = coordString.replace(this.regExes.trimComma, - ","); - var pointList = coordString.split(this.regExes.splitSpace); - for(var i=0; i} A multilinestring geometry. - */ - multilinestring: function(node) { - var nodeList = this.getElementsByTagNameNS(node, this.gmlns, - "LineString"); - var components = []; - if(nodeList.length > 0) { - var line; - for(var i=0; i} A polygon geometry. - */ - polygon: function(node) { - var nodeList = this.getElementsByTagNameNS(node, this.gmlns, - "LinearRing"); - var components = []; - if(nodeList.length > 0) { - // this assumes exterior ring first, inner rings after - var ring; - for(var i=0; i} A multipolygon geometry. - */ - multipolygon: function(node) { - var nodeList = this.getElementsByTagNameNS(node, this.gmlns, - "Polygon"); - var components = []; - if(nodeList.length > 0) { - var polygon; - for(var i=0; i 0) { - var coords = []; - - if(lpoint.length > 0) { - coordString = lpoint[0].firstChild.nodeValue; - coordString = coordString.replace(this.regExes.trimSpace, ""); - coords = coordString.split(this.regExes.splitSpace); - } - - if(coords.length == 2) { - coords[2] = null; - } - if (this.xy) { - var lowerPoint = new OpenLayers.Geometry.Point(coords[0], coords[1],coords[2]); - } else { - var lowerPoint = new OpenLayers.Geometry.Point(coords[1], coords[0],coords[2]); - } - } - - var upoint = this.getElementsByTagNameNS(node, this.gmlns, "upperCorner"); - if (upoint.length > 0) { - var coords = []; - - if(upoint.length > 0) { - coordString = upoint[0].firstChild.nodeValue; - coordString = coordString.replace(this.regExes.trimSpace, ""); - coords = coordString.split(this.regExes.splitSpace); - } - - if(coords.length == 2) { - coords[2] = null; - } - if (this.xy) { - var upperPoint = new OpenLayers.Geometry.Point(coords[0], coords[1],coords[2]); - } else { - var upperPoint = new OpenLayers.Geometry.Point(coords[1], coords[0],coords[2]); - } - } - - if (lowerPoint && upperPoint) { - components.push(new OpenLayers.Geometry.Point(lowerPoint.x, lowerPoint.y)); - components.push(new OpenLayers.Geometry.Point(upperPoint.x, lowerPoint.y)); - components.push(new OpenLayers.Geometry.Point(upperPoint.x, upperPoint.y)); - components.push(new OpenLayers.Geometry.Point(lowerPoint.x, upperPoint.y)); - components.push(new OpenLayers.Geometry.Point(lowerPoint.x, lowerPoint.y)); - - var ring = new OpenLayers.Geometry.LinearRing(components); - envelope = new OpenLayers.Geometry.Polygon([ring]); - } - return envelope; - }, - - /** - * Method: parseGeometry.box - * Given a GML node representing a box geometry, create an - * OpenLayers.Bounds. - * - * Parameters: - * node - {DOMElement} A GML node. - * - * Returns: - * {} A bounds representing the box. - */ - box: function(node) { - var nodeList = this.getElementsByTagNameNS(node, this.gmlns, - "coordinates"); - var coordString; - var coords, beginPoint = null, endPoint = null; - if (nodeList.length > 0) { - coordString = nodeList[0].firstChild.nodeValue; - coords = coordString.split(" "); - if (coords.length == 2) { - beginPoint = coords[0].split(","); - endPoint = coords[1].split(","); - } - } - if (beginPoint !== null && endPoint !== null) { - return new OpenLayers.Bounds(parseFloat(beginPoint[0]), - parseFloat(beginPoint[1]), - parseFloat(endPoint[0]), - parseFloat(endPoint[1]) ); - } - } - - }, - - /** - * Method: parseAttributes - * - * Parameters: - * node - {DOMElement} - * - * Returns: - * {Object} An attributes object. - */ - parseAttributes: function(node) { - var attributes = {}; - // assume attributes are children of the first type 1 child - var childNode = node.firstChild; - var children, i, child, grandchildren, grandchild, name, value; - while(childNode) { - if(childNode.nodeType == 1) { - // attributes are type 1 children with one type 3 child - children = childNode.childNodes; - for(i=0; i becomes - // {fieldname: null} - attributes[child.nodeName.split(":").pop()] = null; - } - } - } - break; - } - childNode = childNode.nextSibling; - } - return attributes; - }, - - /** - * APIMethod: write - * Generate a GML document string given a list of features. - * - * Parameters: - * features - {Array()} List of features to - * serialize into a string. - * - * Returns: - * {String} A string representing the GML document. - */ - write: function(features) { - if(!(OpenLayers.Util.isArray(features))) { - features = [features]; - } - var gml = this.createElementNS("http://www.opengis.net/wfs", - "wfs:" + this.collectionName); - for(var i=0; i} The feature to be built as GML. - * - * Returns: - * {DOMElement} A node reprensting the feature in GML. - */ - createFeatureXML: function(feature) { - var geometry = feature.geometry; - var geometryNode = this.buildGeometryNode(geometry); - var geomContainer = this.createElementNS(this.featureNS, - this.featurePrefix + ":" + - this.geometryName); - geomContainer.appendChild(geometryNode); - var featureNode = this.createElementNS(this.gmlns, - "gml:" + this.featureName); - var featureContainer = this.createElementNS(this.featureNS, - this.featurePrefix + ":" + - this.layerName); - var fid = feature.fid || feature.id; - featureContainer.setAttribute("fid", fid); - featureContainer.appendChild(geomContainer); - for(var attr in feature.attributes) { - var attrText = this.createTextNode(feature.attributes[attr]); - var nodename = attr.substring(attr.lastIndexOf(":") + 1); - var attrContainer = this.createElementNS(this.featureNS, - this.featurePrefix + ":" + - nodename); - attrContainer.appendChild(attrText); - featureContainer.appendChild(attrContainer); - } - featureNode.appendChild(featureContainer); - return featureNode; - }, - - /** - * APIMethod: buildGeometryNode - */ - buildGeometryNode: function(geometry) { - if (this.externalProjection && this.internalProjection) { - geometry = geometry.clone(); - geometry.transform(this.internalProjection, - this.externalProjection); - } - var className = geometry.CLASS_NAME; - var type = className.substring(className.lastIndexOf(".") + 1); - var builder = this.buildGeometry[type.toLowerCase()]; - return builder.apply(this, [geometry]); - }, - - /** - * Property: buildGeometry - * Object containing methods to do the actual geometry node building - * based on geometry type. - */ - buildGeometry: { - // TBD retrieve the srs from layer - // srsName is non-standard, so not including it until it's right. - // gml.setAttribute("srsName", - // "http://www.opengis.net/gml/srs/epsg.xml#4326"); - - /** - * Method: buildGeometry.point - * Given an OpenLayers point geometry, create a GML point. - * - * Parameters: - * geometry - {} A point geometry. - * - * Returns: - * {DOMElement} A GML point node. - */ - point: function(geometry) { - var gml = this.createElementNS(this.gmlns, "gml:Point"); - gml.appendChild(this.buildCoordinatesNode(geometry)); - return gml; - }, - - /** - * Method: buildGeometry.multipoint - * Given an OpenLayers multipoint geometry, create a GML multipoint. - * - * Parameters: - * geometry - {} A multipoint geometry. - * - * Returns: - * {DOMElement} A GML multipoint node. - */ - multipoint: function(geometry) { - var gml = this.createElementNS(this.gmlns, "gml:MultiPoint"); - var points = geometry.components; - var pointMember, pointGeom; - for(var i=0; i} A linestring geometry. - * - * Returns: - * {DOMElement} A GML linestring node. - */ - linestring: function(geometry) { - var gml = this.createElementNS(this.gmlns, "gml:LineString"); - gml.appendChild(this.buildCoordinatesNode(geometry)); - return gml; - }, - - /** - * Method: buildGeometry.multilinestring - * Given an OpenLayers multilinestring geometry, create a GML - * multilinestring. - * - * Parameters: - * geometry - {} A multilinestring - * geometry. - * - * Returns: - * {DOMElement} A GML multilinestring node. - */ - multilinestring: function(geometry) { - var gml = this.createElementNS(this.gmlns, "gml:MultiLineString"); - var lines = geometry.components; - var lineMember, lineGeom; - for(var i=0; i} A linearring geometry. - * - * Returns: - * {DOMElement} A GML linearring node. - */ - linearring: function(geometry) { - var gml = this.createElementNS(this.gmlns, "gml:LinearRing"); - gml.appendChild(this.buildCoordinatesNode(geometry)); - return gml; - }, - - /** - * Method: buildGeometry.polygon - * Given an OpenLayers polygon geometry, create a GML polygon. - * - * Parameters: - * geometry - {} A polygon geometry. - * - * Returns: - * {DOMElement} A GML polygon node. - */ - polygon: function(geometry) { - var gml = this.createElementNS(this.gmlns, "gml:Polygon"); - var rings = geometry.components; - var ringMember, ringGeom, type; - for(var i=0; i} A multipolygon - * geometry. - * - * Returns: - * {DOMElement} A GML multipolygon node. - */ - multipolygon: function(geometry) { - var gml = this.createElementNS(this.gmlns, "gml:MultiPolygon"); - var polys = geometry.components; - var polyMember, polyGeom; - for(var i=0; i} A bounds object. - * - * Returns: - * {DOMElement} A GML box node. - */ - bounds: function(bounds) { - var gml = this.createElementNS(this.gmlns, "gml:Box"); - gml.appendChild(this.buildCoordinatesNode(bounds)); - return gml; - } - }, - - /** - * Method: buildCoordinates - * builds the coordinates XmlNode - * (code) - * ... - * (end) - * - * Parameters: - * geometry - {} - * - * Returns: - * {XmlNode} created xmlNode - */ - buildCoordinatesNode: function(geometry) { - var coordinatesNode = this.createElementNS(this.gmlns, - "gml:coordinates"); - coordinatesNode.setAttribute("decimal", "."); - coordinatesNode.setAttribute("cs", ","); - coordinatesNode.setAttribute("ts", " "); - - var parts = []; - - if(geometry instanceof OpenLayers.Bounds){ - parts.push(geometry.left + "," + geometry.bottom); - parts.push(geometry.right + "," + geometry.top); - } else { - var points = (geometry.components) ? geometry.components : [geometry]; - for(var i=0; i - */ -OpenLayers.Format.GML.Base = OpenLayers.Class(OpenLayers.Format.XML, { - - /** - * Property: namespaces - * {Object} Mapping of namespace aliases to namespace URIs. - */ - namespaces: { - gml: "http://www.opengis.net/gml", - xlink: "http://www.w3.org/1999/xlink", - xsi: "http://www.w3.org/2001/XMLSchema-instance", - wfs: "http://www.opengis.net/wfs" // this is a convenience for reading wfs:FeatureCollection - }, - - /** - * Property: defaultPrefix - */ - defaultPrefix: "gml", - - /** - * Property: schemaLocation - * {String} Schema location for a particular minor version. - */ - schemaLocation: null, - - /** - * APIProperty: featureType - * {Array(String) or String} The local (without prefix) feature typeName(s). - */ - featureType: null, - - /** - * APIProperty: featureNS - * {String} The feature namespace. Must be set in the options at - * construction. - */ - featureNS: null, - - /** - * APIProperty: geometry - * {String} Name of geometry element. Defaults to "geometry". If null, it - * will be set on when the first geometry is parsed. - */ - geometryName: "geometry", - - /** - * APIProperty: extractAttributes - * {Boolean} Extract attributes from GML. Default is true. - */ - extractAttributes: true, - - /** - * APIProperty: srsName - * {String} URI for spatial reference system. This is optional for - * single part geometries and mandatory for collections and multis. - * If set, the srsName attribute will be written for all geometries. - * Default is null. - */ - srsName: null, - - /** - * APIProperty: xy - * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x) - * Changing is not recommended, a new Format should be instantiated. - */ - xy: true, - - /** - * Property: geometryTypes - * {Object} Maps OpenLayers geometry class names to GML element names. - * Use before accessing this property. - */ - geometryTypes: null, - - /** - * Property: singleFeatureType - * {Boolean} True if there is only 1 featureType, and not an array - * of featuretypes. - */ - singleFeatureType: null, - - /** - * Property: autoConfig - * {Boolean} Indicates if the format was configured without a , - * but auto-configured and during read. - * Subclasses making use of auto-configuration should make - * the first call to the method (usually in the read method) - * with true as 3rd argument, so the auto-configured featureType can be - * reset and the format can be reused for subsequent reads with data from - * different featureTypes. Set to false after read if you want to keep the - * auto-configured values. - */ - - /** - * Property: regExes - * Compiled regular expressions for manipulating strings. - */ - regExes: { - trimSpace: (/^\s*|\s*$/g), - removeSpace: (/\s*/g), - splitSpace: (/\s+/), - trimComma: (/\s*,\s*/g), - featureMember: (/^(.*:)?featureMembers?$/) - }, - - /** - * Constructor: OpenLayers.Format.GML.Base - * Instances of this class are not created directly. Use the - * or constructor - * instead. - * - * Parameters: - * options - {Object} An optional object whose properties will be set on - * this instance. - * - * Valid options properties: - * featureType - {Array(String) or String} Local (without prefix) feature - * typeName(s) (required for write). - * featureNS - {String} Feature namespace (required for write). - * geometryName - {String} Geometry element name (required for write). - */ - initialize: function(options) { - OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); - this.setGeometryTypes(); - if(options && options.featureNS) { - this.setNamespace("feature", options.featureNS); - } - this.singleFeatureType = !options || (typeof options.featureType === "string"); - }, - - /** - * Method: read - * - * Parameters: - * data - {DOMElement} A gml:featureMember element, a gml:featureMembers - * element, or an element containing either of the above at any level. - * - * Returns: - * {Array()} An array of features. - */ - 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 features = []; - this.readNode(data, {features: features}, true); - if(features.length == 0) { - // look for gml:featureMember elements - var elements = this.getElementsByTagNameNS( - data, this.namespaces.gml, "featureMember" - ); - if(elements.length) { - for(var i=0, len=elements.length; i 0) { - obj.bounds = container.components[0]; - } - }, - "Point": function(node, container) { - var obj = {points: []}; - this.readChildNodes(node, obj); - if(!container.components) { - container.components = []; - } - container.components.push(obj.points[0]); - }, - "coordinates": function(node, obj) { - var str = this.getChildValue(node).replace( - this.regExes.trimSpace, "" - ); - str = str.replace(this.regExes.trimComma, ","); - var pointList = str.split(this.regExes.splitSpace); - var coords; - var numPoints = pointList.length; - var points = new Array(numPoints); - for(var i=0; i) | OpenLayers.Feature.Vector} - * An array of features or a single feature. - * - * Returns: - * {String} Given an array of features, a doc with a gml:featureMembers - * element will be returned. Given a single feature, a doc with a - * gml:featureMember element will be returned. - */ - write: function(features) { - var name; - if(OpenLayers.Util.isArray(features)) { - name = "featureMembers"; - } else { - name = "featureMember"; - } - var root = this.writeNode("gml:" + name, features); - this.setAttributeNS( - root, this.namespaces["xsi"], - "xsi:schemaLocation", this.schemaLocation - ); - - return OpenLayers.Format.XML.prototype.write.apply(this, [root]); - }, - - /** - * Property: writers - * As a compliment to the readers property, this structure contains public - * writing functions grouped by namespace alias and named like the - * node names they produce. - */ - writers: { - "gml": { - "featureMember": function(feature) { - var node = this.createElementNSPlus("gml:featureMember"); - this.writeNode("feature:_typeName", feature, node); - return node; - }, - "MultiPoint": function(geometry) { - var node = this.createElementNSPlus("gml:MultiPoint"); - var components = geometry.components || [geometry]; - for(var i=0, ii=components.length; i mapping. - */ - setGeometryTypes: function() { - this.geometryTypes = { - "OpenLayers.Geometry.Point": "Point", - "OpenLayers.Geometry.MultiPoint": "MultiPoint", - "OpenLayers.Geometry.LineString": "LineString", - "OpenLayers.Geometry.MultiLineString": "MultiLineString", - "OpenLayers.Geometry.Polygon": "Polygon", - "OpenLayers.Geometry.MultiPolygon": "MultiPolygon", - "OpenLayers.Geometry.Collection": "GeometryCollection" - }; - }, - - CLASS_NAME: "OpenLayers.Format.GML.Base" - -}); -/* ====================================================================== - OpenLayers/Format/GML/v2.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/GML/Base.js - */ - -/** - * Class: OpenLayers.Format.GML.v2 - * Parses GML version 2. - * - * Inherits from: - * - - */ -OpenLayers.Format.GML.v2 = OpenLayers.Class(OpenLayers.Format.GML.Base, { - - /** - * Property: schemaLocation - * {String} Schema location for a particular minor version. - */ - schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd", - - /** - * Constructor: OpenLayers.Format.GML.v2 - * Create a parser for GML v2. - * - * Parameters: - * options - {Object} An optional object whose properties will be set on - * this instance. - * - * Valid options properties: - * featureType - {String} Local (without prefix) feature typeName (required). - * featureNS - {String} Feature namespace (required). - * geometryName - {String} Geometry element name. - */ - initialize: function(options) { - OpenLayers.Format.GML.Base.prototype.initialize.apply(this, [options]); - }, - - /** - * 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: { - "gml": OpenLayers.Util.applyDefaults({ - "outerBoundaryIs": function(node, container) { - var obj = {}; - this.readChildNodes(node, obj); - container.outer = obj.components[0]; - }, - "innerBoundaryIs": function(node, container) { - var obj = {}; - this.readChildNodes(node, obj); - container.inner.push(obj.components[0]); - }, - "Box": function(node, container) { - var obj = {}; - this.readChildNodes(node, obj); - if(!container.components) { - container.components = []; - } - var min = obj.points[0]; - var max = obj.points[1]; - container.components.push( - new OpenLayers.Bounds(min.x, min.y, max.x, max.y) - ); - } - }, OpenLayers.Format.GML.Base.prototype.readers["gml"]), - "feature": OpenLayers.Format.GML.Base.prototype.readers["feature"], - "wfs": OpenLayers.Format.GML.Base.prototype.readers["wfs"] - }, - - /** - * Method: write - * - * Parameters: - * features - {Array() | OpenLayers.Feature.Vector} - * An array of features or a single feature. - * - * Returns: - * {String} Given an array of features, a doc with a gml:featureMembers - * element will be returned. Given a single feature, a doc with a - * gml:featureMember element will be returned. - */ - write: function(features) { - var name; - if(OpenLayers.Util.isArray(features)) { - // GML2 only has abstract feature collections - // wfs provides a feature collection from a well-known schema - name = "wfs:FeatureCollection"; - } else { - name = "gml:featureMember"; - } - var root = this.writeNode(name, features); - this.setAttributeNS( - root, this.namespaces["xsi"], - "xsi:schemaLocation", this.schemaLocation - ); - - return OpenLayers.Format.XML.prototype.write.apply(this, [root]); - }, - - /** - * Property: writers - * As a compliment to the readers property, this structure contains public - * writing functions grouped by namespace alias and named like the - * node names they produce. - */ - writers: { - "gml": OpenLayers.Util.applyDefaults({ - "Point": function(geometry) { - var node = this.createElementNSPlus("gml:Point"); - this.writeNode("coordinates", [geometry], node); - return node; - }, - "coordinates": function(points) { - var numPoints = points.length; - var parts = new Array(numPoints); - var point; - for(var i=0; i - */ -OpenLayers.Filter.Function = OpenLayers.Class(OpenLayers.Filter, { - - /** - * APIProperty: name - * {String} Name of the function. - */ - name: null, - - /** - * APIProperty: params - * {Array( || String || Number)} Function parameters - * For now support only other Functions, String or Number - */ - params: null, - - /** - * Constructor: OpenLayers.Filter.Function - * Creates a filter function. - * - * Parameters: - * options - {Object} An optional object with properties to set on the - * function. - * - * Returns: - * {} - */ - - CLASS_NAME: "OpenLayers.Filter.Function" -}); - -/* ====================================================================== - OpenLayers/BaseTypes/Date.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: OpenLayers.Date - * Contains implementations of Date.parse and date.toISOString that match the - * ECMAScript 5 specification for parsing RFC 3339 dates. - * http://tools.ietf.org/html/rfc3339 - */ -OpenLayers.Date = { - - /** - * APIProperty: dateRegEx - * The regex to be used for validating dates. You can provide your own - * regex for instance for adding support for years before BC. Default - * value is: /^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:(?:T(\d{1,2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|(?:[+-]\d{1,2}(?::(\d{2}))?)))|Z)?$/ - */ - dateRegEx: /^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:(?:T(\d{1,2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|(?:[+-]\d{1,2}(?::(\d{2}))?)))|Z)?$/, - - /** - * APIMethod: toISOString - * Generates a string representing a date. The format of the string follows - * the profile of ISO 8601 for date and time on the Internet (see - * http://tools.ietf.org/html/rfc3339). If the toISOString method is - * available on the Date prototype, that is used. The toISOString - * method for Date instances is defined in ECMA-262. - * - * Parameters: - * date - {Date} A date object. - * - * Returns: - * {String} A string representing the date (e.g. - * "2010-08-07T16:58:23.123Z"). If the date does not have a valid time - * (i.e. isNaN(date.getTime())) this method returns the string "Invalid - * Date". The ECMA standard says the toISOString method should throw - * RangeError in this case, but Firefox returns a string instead. For - * best results, use isNaN(date.getTime()) to determine date validity - * before generating date strings. - */ - toISOString: (function() { - if ("toISOString" in Date.prototype) { - return function(date) { - return date.toISOString(); - }; - } else { - return function(date) { - var str; - if (isNaN(date.getTime())) { - // ECMA-262 says throw RangeError, Firefox returns - // "Invalid Date" - str = "Invalid Date"; - } else { - str = - date.getUTCFullYear() + "-" + - OpenLayers.Number.zeroPad(date.getUTCMonth() + 1, 2) + "-" + - OpenLayers.Number.zeroPad(date.getUTCDate(), 2) + "T" + - OpenLayers.Number.zeroPad(date.getUTCHours(), 2) + ":" + - OpenLayers.Number.zeroPad(date.getUTCMinutes(), 2) + ":" + - OpenLayers.Number.zeroPad(date.getUTCSeconds(), 2) + "." + - OpenLayers.Number.zeroPad(date.getUTCMilliseconds(), 3) + "Z"; - } - return str; - }; - } - - })(), - - /** - * APIMethod: parse - * Generate a date object from a string. The format for the string follows - * the profile of ISO 8601 for date and time on the Internet (see - * http://tools.ietf.org/html/rfc3339). We don't call the native - * Date.parse because of inconsistency between implmentations. In - * Chrome, calling Date.parse with a string that doesn't contain any - * indication of the timezone (e.g. "2011"), the date is interpreted - * in local time. On Firefox, the assumption is UTC. - * - * Parameters: - * str - {String} A string representing the date (e.g. - * "2010", "2010-08", "2010-08-07", "2010-08-07T16:58:23.123Z", - * "2010-08-07T11:58:23.123-06"). - * - * Returns: - * {Date} A date object. If the string could not be parsed, an invalid - * date is returned (i.e. isNaN(date.getTime())). - */ - parse: function(str) { - var date; - var match = str.match(this.dateRegEx); - if (match && (match[1] || match[7])) { // must have at least year or time - var year = parseInt(match[1], 10) || 0; - var month = (parseInt(match[2], 10) - 1) || 0; - var day = parseInt(match[3], 10) || 1; - date = new Date(Date.UTC(year, month, day)); - // optional time - var type = match[7]; - if (type) { - var hours = parseInt(match[4], 10); - var minutes = parseInt(match[5], 10); - var secFrac = parseFloat(match[6]); - var seconds = secFrac | 0; - var milliseconds = Math.round(1000 * (secFrac - seconds)); - date.setUTCHours(hours, minutes, seconds, milliseconds); - // check offset - if (type !== "Z") { - var hoursOffset = parseInt(type, 10); - var minutesOffset = parseInt(match[8], 10) || 0; - var offset = -1000 * (60 * (hoursOffset * 60) + minutesOffset * 60); - date = new Date(date.getTime() + offset); - } - } - } else { - date = new Date("invalid"); - } - return date; - } -}; -/* ====================================================================== - OpenLayers/Format/Filter/v1.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/Filter.js - * @requires OpenLayers/Format/XML.js - * @requires OpenLayers/Filter/Function.js - * @requires OpenLayers/BaseTypes/Date.js - */ - -/** - * Class: OpenLayers.Format.Filter.v1 - * Superclass for Filter version 1 parsers. - * - * Inherits from: - * - - */ -OpenLayers.Format.Filter.v1 = OpenLayers.Class(OpenLayers.Format.XML, { - - /** - * Property: namespaces - * {Object} Mapping of namespace aliases to namespace URIs. - */ - namespaces: { - ogc: "http://www.opengis.net/ogc", - gml: "http://www.opengis.net/gml", - xlink: "http://www.w3.org/1999/xlink", - xsi: "http://www.w3.org/2001/XMLSchema-instance" - }, - - /** - * Property: defaultPrefix - */ - defaultPrefix: "ogc", - - /** - * Property: schemaLocation - * {String} Schema location for a particular minor version. - */ - schemaLocation: null, - - /** - * Constructor: OpenLayers.Format.Filter.v1 - * Instances of this class are not created directly. Use the - * constructor instead. - * - * Parameters: - * options - {Object} An optional object whose properties will be set on - * this instance. - */ - initialize: function(options) { - OpenLayers.Format.XML.prototype.initialize.apply(this, [options]); - }, - - /** - * Method: read - * - * Parameters: - * data - {DOMElement} A Filter document element. - * - * Returns: - * {} A filter object. - */ - read: function(data) { - var obj = {}; - this.readers.ogc["Filter"].apply(this, [data, obj]); - return obj.filter; - }, - - /** - * 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: { - "ogc": { - "_expression": function(node) { - // only the simplest of ogc:expression handled - // "some text and an attribute"} - var obj, value = ""; - for(var child=node.firstChild; child; child=child.nextSibling) { - switch(child.nodeType) { - case 1: - obj = this.readNode(child); - if (obj.property) { - value += "${" + obj.property + "}"; - } else if (obj.value !== undefined) { - value += obj.value; - } - break; - case 3: // text node - case 4: // cdata section - value += child.nodeValue; - } - } - return value; - }, - "Filter": function(node, parent) { - // Filters correspond to subclasses of OpenLayers.Filter. - // Since they contain information we don't persist, we - // create a temporary object and then pass on the filter - // (ogc:Filter) to the parent obj. - var obj = { - fids: [], - filters: [] - }; - this.readChildNodes(node, obj); - if(obj.fids.length > 0) { - parent.filter = new OpenLayers.Filter.FeatureId({ - fids: obj.fids - }); - } else if(obj.filters.length > 0) { - parent.filter = obj.filters[0]; - } - }, - "FeatureId": function(node, obj) { - var fid = node.getAttribute("fid"); - if(fid) { - obj.fids.push(fid); - } - }, - "And": function(node, obj) { - var filter = new OpenLayers.Filter.Logical({ - type: OpenLayers.Filter.Logical.AND - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - }, - "Or": function(node, obj) { - var filter = new OpenLayers.Filter.Logical({ - type: OpenLayers.Filter.Logical.OR - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - }, - "Not": function(node, obj) { - var filter = new OpenLayers.Filter.Logical({ - type: OpenLayers.Filter.Logical.NOT - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - }, - "PropertyIsLessThan": function(node, obj) { - var filter = new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.LESS_THAN - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - }, - "PropertyIsGreaterThan": function(node, obj) { - var filter = new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.GREATER_THAN - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - }, - "PropertyIsLessThanOrEqualTo": function(node, obj) { - var filter = new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - }, - "PropertyIsGreaterThanOrEqualTo": function(node, obj) { - var filter = new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - }, - "PropertyIsBetween": function(node, obj) { - var filter = new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.BETWEEN - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - }, - "Literal": function(node, obj) { - obj.value = OpenLayers.String.numericIf( - this.getChildValue(node), true); - }, - "PropertyName": function(node, filter) { - filter.property = this.getChildValue(node); - }, - "LowerBoundary": function(node, filter) { - filter.lowerBoundary = OpenLayers.String.numericIf( - this.readers.ogc._expression.call(this, node), true); - }, - "UpperBoundary": function(node, filter) { - filter.upperBoundary = OpenLayers.String.numericIf( - this.readers.ogc._expression.call(this, node), true); - }, - "Intersects": function(node, obj) { - this.readSpatial(node, obj, OpenLayers.Filter.Spatial.INTERSECTS); - }, - "Within": function(node, obj) { - this.readSpatial(node, obj, OpenLayers.Filter.Spatial.WITHIN); - }, - "Contains": function(node, obj) { - this.readSpatial(node, obj, OpenLayers.Filter.Spatial.CONTAINS); - }, - "DWithin": function(node, obj) { - this.readSpatial(node, obj, OpenLayers.Filter.Spatial.DWITHIN); - }, - "Distance": function(node, obj) { - obj.distance = parseInt(this.getChildValue(node)); - obj.distanceUnits = node.getAttribute("units"); - }, - "Function": function(node, obj) { - //TODO write decoder for it - return; - }, - "PropertyIsNull": function(node, obj) { - var filter = new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.IS_NULL - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - } - } - }, - - /** - * Method: readSpatial - * - * Read a {} filter. - * - * Parameters: - * node - {DOMElement} A DOM element that contains an ogc:expression. - * obj - {Object} The target object. - * type - {String} One of the OpenLayers.Filter.Spatial.* constants. - * - * Returns: - * {} The created filter. - */ - readSpatial: function(node, obj, type) { - var filter = new OpenLayers.Filter.Spatial({ - type: type - }); - this.readChildNodes(node, filter); - filter.value = filter.components[0]; - delete filter.components; - obj.filters.push(filter); - }, - - /** - * APIMethod: encodeLiteral - * Generates the string representation of a value for use in - * elements. The default encoder writes Date values as ISO 8601 - * strings. - * - * Parameters: - * value - {Object} Literal value to encode - * - * Returns: - * {String} String representation of the provided value. - */ - encodeLiteral: function(value) { - if (value instanceof Date) { - value = OpenLayers.Date.toISOString(value); - } - return value; - }, - - /** - * Method: writeOgcExpression - * Limited support for writing OGC expressions. Currently it supports - * ( || String || Number) - * - * Parameters: - * value - ( || String || Number) - * node - {DOMElement} A parent DOM element - * - * Returns: - * {DOMElement} Updated node element. - */ - writeOgcExpression: function(value, node) { - if (value instanceof OpenLayers.Filter.Function){ - this.writeNode("Function", value, node); - } else { - this.writeNode("Literal", value, node); - } - return node; - }, - - /** - * Method: write - * - * Parameters: - * filter - {} A filter object. - * - * Returns: - * {DOMElement} An ogc:Filter element. - */ - write: function(filter) { - return this.writers.ogc["Filter"].apply(this, [filter]); - }, - - /** - * Property: writers - * As a compliment to the readers property, this structure contains public - * writing functions grouped by namespace alias and named like the - * node names they produce. - */ - writers: { - "ogc": { - "Filter": function(filter) { - var node = this.createElementNSPlus("ogc:Filter"); - this.writeNode(this.getFilterType(filter), filter, node); - return node; - }, - "_featureIds": function(filter) { - var node = this.createDocumentFragment(); - for (var i=0, ii=filter.fids.length; i": "PropertyIsGreaterThan", - "<=": "PropertyIsLessThanOrEqualTo", - ">=": "PropertyIsGreaterThanOrEqualTo", - "..": "PropertyIsBetween", - "~": "PropertyIsLike", - "NULL": "PropertyIsNull", - "BBOX": "BBOX", - "DWITHIN": "DWITHIN", - "WITHIN": "WITHIN", - "CONTAINS": "CONTAINS", - "INTERSECTS": "INTERSECTS", - "FID": "_featureIds" - }, - - CLASS_NAME: "OpenLayers.Format.Filter.v1" - -}); -/* ====================================================================== - OpenLayers/Format/Filter/v1_0_0.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/GML/v2.js - * @requires OpenLayers/Format/Filter/v1.js - */ - -/** - * Class: OpenLayers.Format.Filter.v1_0_0 - * Write ogc:Filter version 1.0.0. - * - * Inherits from: - * - - * - - */ -OpenLayers.Format.Filter.v1_0_0 = OpenLayers.Class( - OpenLayers.Format.GML.v2, OpenLayers.Format.Filter.v1, { - - /** - * Constant: VERSION - * {String} 1.0.0 - */ - VERSION: "1.0.0", - - /** - * Property: schemaLocation - * {String} http://www.opengis.net/ogc/filter/1.0.0/filter.xsd - */ - schemaLocation: "http://www.opengis.net/ogc/filter/1.0.0/filter.xsd", - - /** - * Constructor: OpenLayers.Format.Filter.v1_0_0 - * Instances of this class are not created directly. Use the - * constructor instead. - * - * Parameters: - * options - {Object} An optional object whose properties will be set on - * this instance. - */ - initialize: function(options) { - OpenLayers.Format.GML.v2.prototype.initialize.apply( - this, [options] - ); - }, - - /** - * 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: { - "ogc": OpenLayers.Util.applyDefaults({ - "PropertyIsEqualTo": function(node, obj) { - var filter = new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.EQUAL_TO - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - }, - "PropertyIsNotEqualTo": function(node, obj) { - var filter = new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO - }); - this.readChildNodes(node, filter); - obj.filters.push(filter); - }, - "PropertyIsLike": function(node, obj) { - var filter = new OpenLayers.Filter.Comparison({ - type: OpenLayers.Filter.Comparison.LIKE - }); - this.readChildNodes(node, filter); - var wildCard = node.getAttribute("wildCard"); - var singleChar = node.getAttribute("singleChar"); - var esc = node.getAttribute("escape"); - filter.value2regex(wildCard, singleChar, esc); - obj.filters.push(filter); - } - }, OpenLayers.Format.Filter.v1.prototype.readers["ogc"]), - "gml": OpenLayers.Format.GML.v2.prototype.readers["gml"], - "feature": OpenLayers.Format.GML.v2.prototype.readers["feature"] - }, - - /** - * Property: writers - * As a compliment to the readers property, this structure contains public - * writing functions grouped by namespace alias and named like the - * node names they produce. - */ - writers: { - "ogc": OpenLayers.Util.applyDefaults({ - "PropertyIsEqualTo": function(filter) { - var node = this.createElementNSPlus("ogc:PropertyIsEqualTo"); - // no ogc:expression handling for PropertyName for now - this.writeNode("PropertyName", filter, node); - // handle Literals or Functions for now - this.writeOgcExpression(filter.value, node); - return node; - }, - "PropertyIsNotEqualTo": function(filter) { - var node = this.createElementNSPlus("ogc:PropertyIsNotEqualTo"); - // no ogc:expression handling for PropertyName for now - this.writeNode("PropertyName", filter, node); - // handle Literals or Functions for now - this.writeOgcExpression(filter.value, node); - return node; - }, - "PropertyIsLike": function(filter) { - var node = this.createElementNSPlus("ogc:PropertyIsLike", { - attributes: { - wildCard: "*", singleChar: ".", escape: "!" - } - }); - // no ogc:expression handling for now - this.writeNode("PropertyName", filter, node); - // convert regex string to ogc string - this.writeNode("Literal", filter.regex2value(), node); - return node; - }, - "BBOX": function(filter) { - var node = this.createElementNSPlus("ogc:BBOX"); - // PropertyName is mandatory in 1.0.0, but e.g. GeoServer also - // accepts filters without it. When this is used with - // OpenLayers.Protocol.WFS, OpenLayers.Format.WFST will set a - // missing filter.property to the geometryName that is - // configured with the protocol, which defaults to "the_geom". - // So the only way to omit this mandatory property is to not - // set the property on the filter and to set the geometryName - // on the WFS protocol to null. The latter also happens when - // the protocol is configured without a geometryName and a - // featureNS. - filter.property && this.writeNode("PropertyName", filter, node); - var box = this.writeNode("gml:Box", filter.value, node); - if(filter.projection) { - box.setAttribute("srsName", filter.projection); - } - return node; - } - }, OpenLayers.Format.Filter.v1.prototype.writers["ogc"]), - "gml": OpenLayers.Format.GML.v2.prototype.writers["gml"], - "feature": OpenLayers.Format.GML.v2.prototype.writers["feature"] - }, - - /** - * Method: writeSpatial - * - * Read a {} filter and converts it into XML. - * - * Parameters: - * filter - {} The filter. - * name - {String} Name of the generated XML element. - * - * Returns: - * {DOMElement} The created XML element. - */ - writeSpatial: function(filter, name) { - var node = this.createElementNSPlus("ogc:"+name); - this.writeNode("PropertyName", filter, node); - if(filter.value instanceof OpenLayers.Filter.Function) { - this.writeNode("Function", filter.value, node); - } else { - var child; - if(filter.value instanceof OpenLayers.Geometry) { - child = this.writeNode("feature:_geometry", filter.value).firstChild; - } else { - child = this.writeNode("gml:Box", filter.value); - } - if(filter.projection) { - child.setAttribute("srsName", filter.projection); - } - node.appendChild(child); - } - return node; - }, - - - CLASS_NAME: "OpenLayers.Format.Filter.v1_0_0" - -}); -/* ====================================================================== - OpenLayers/Format/WFST/v1_0_0.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/WFST/v1.js - * @requires OpenLayers/Format/Filter/v1_0_0.js - */ - -/** - * Class: OpenLayers.Format.WFST.v1_0_0 - * A format for creating WFS v1.0.0 transactions. Create a new instance with the - * constructor. - * - * Inherits from: - * - - * - - */ -OpenLayers.Format.WFST.v1_0_0 = OpenLayers.Class( - OpenLayers.Format.Filter.v1_0_0, OpenLayers.Format.WFST.v1, { - - /** - * Property: version - * {String} WFS version number. - */ - version: "1.0.0", - - /** - * APIProperty: srsNameInQuery - * {Boolean} If true the reference system is passed in Query requests - * via the "srsName" attribute to the "wfs:Query" element, this - * property defaults to false as it isn't WFS 1.0.0 compliant. - */ - srsNameInQuery: false, - - /** - * Property: schemaLocations - * {Object} Properties are namespace aliases, values are schema locations. - */ - schemaLocations: { - "wfs": "http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd" - }, - - /** - * Constructor: OpenLayers.Format.WFST.v1_0_0 - * A class for parsing and generating WFS v1.0.0 transactions. - * - * Parameters: - * options - {Object} Optional object whose properties will be set on the - * instance. - * - * Valid options properties: - * featureType - {String} Local (without prefix) feature typeName (required). - * featureNS - {String} Feature namespace (optional). - * featurePrefix - {String} Feature namespace alias (optional - only used - * if featureNS is provided). Default is 'feature'. - * geometryName - {String} Name of geometry attribute. Default is 'the_geom'. - */ - initialize: function(options) { - OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this, [options]); - OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]); - }, - - /** - * Method: readNode - * Shorthand for applying one of the named readers given the node - * namespace and local name. Readers take two args (node, obj) and - * generally extend or modify the second. - * - * Parameters: - * node - {DOMElement} The node to be read (required). - * obj - {Object} The object to be modified (optional). - * first - {Boolean} Should be set to true for the first node read. This - * is usually the readNode call in the read method. Without this being - * set, auto-configured properties will stick on subsequent reads. - * - * Returns: - * {Object} The input object, modified (or a new one if none was provided). - */ - readNode: function(node, obj, first) { - // Not the superclass, only the mixin classes inherit from - // Format.GML.v2. We need this because we don't want to get readNode - // from the superclass's superclass, which is OpenLayers.Format.XML. - return OpenLayers.Format.GML.v2.prototype.readNode.apply(this, arguments); - }, - - /** - * 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: { - "wfs": OpenLayers.Util.applyDefaults({ - "WFS_TransactionResponse": function(node, obj) { - obj.insertIds = []; - obj.success = false; - this.readChildNodes(node, obj); - }, - "InsertResult": function(node, container) { - var obj = {fids: []}; - this.readChildNodes(node, obj); - container.insertIds = container.insertIds.concat(obj.fids); - }, - "TransactionResult": function(node, obj) { - this.readChildNodes(node, obj); - }, - "Status": function(node, obj) { - this.readChildNodes(node, obj); - }, - "SUCCESS": function(node, obj) { - obj.success = true; - } - }, OpenLayers.Format.WFST.v1.prototype.readers["wfs"]), - "gml": OpenLayers.Format.GML.v2.prototype.readers["gml"], - "feature": OpenLayers.Format.GML.v2.prototype.readers["feature"], - "ogc": OpenLayers.Format.Filter.v1_0_0.prototype.readers["ogc"] - }, - - /** - * Property: writers - * As a compliment to the readers property, this structure contains public - * writing functions grouped by namespace alias and named like the - * node names they produce. - */ - writers: { - "wfs": OpenLayers.Util.applyDefaults({ - "Query": function(options) { - options = OpenLayers.Util.extend({ - featureNS: this.featureNS, - featurePrefix: this.featurePrefix, - featureType: this.featureType, - srsName: this.srsName, - srsNameInQuery: this.srsNameInQuery - }, options); - var prefix = options.featurePrefix; - var node = this.createElementNSPlus("wfs:Query", { - attributes: { - typeName: (prefix ? prefix + ":" : "") + - options.featureType - } - }); - if(options.srsNameInQuery && options.srsName) { - node.setAttribute("srsName", options.srsName); - } - if(options.featureNS) { - node.setAttribute("xmlns:" + prefix, options.featureNS); - } - if(options.propertyNames) { - for(var i=0,len = options.propertyNames.length; i} This is an array of node id's stored in the - * order that they should show up on screen. Id's higher up in the - * array (higher array index) represent nodes with higher z-indeces. - */ - order: null, - - /** - * Property: indices - * {Object} This is a hash that maps node ids to their z-index value - * stored in the indexer. This is done to make finding a nodes z-index - * value O(1). - */ - indices: null, - - /** - * Property: compare - * {Function} This is the function used to determine placement of - * of a new node within the indexer. If null, this defaults to to - * the Z_ORDER_DRAWING_ORDER comparison method. - */ - compare: null, - - /** - * APIMethod: initialize - * Create a new indexer with - * - * Parameters: - * yOrdering - {Boolean} Whether to use y-ordering. - */ - initialize: function(yOrdering) { - - this.compare = yOrdering ? - OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER : - OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER; - - this.clear(); - }, - - /** - * APIMethod: insert - * Insert a new node into the indexer. In order to find the correct - * positioning for the node to be inserted, this method uses a binary - * search. This makes inserting O(log(n)). - * - * Parameters: - * newNode - {DOMElement} The new node to be inserted. - * - * Returns - * {DOMElement} the node before which we should insert our newNode, or - * null if newNode can just be appended. - */ - insert: function(newNode) { - // If the node is known to the indexer, remove it so we can - // recalculate where it should go. - if (this.exists(newNode)) { - this.remove(newNode); - } - - var nodeId = newNode.id; - - this.determineZIndex(newNode); - - var leftIndex = -1; - var rightIndex = this.order.length; - var middle; - - while (rightIndex - leftIndex > 1) { - middle = parseInt((leftIndex + rightIndex) / 2); - - var placement = this.compare(this, newNode, - OpenLayers.Util.getElement(this.order[middle])); - - if (placement > 0) { - leftIndex = middle; - } else { - rightIndex = middle; - } - } - - this.order.splice(rightIndex, 0, nodeId); - this.indices[nodeId] = this.getZIndex(newNode); - - // If the new node should be before another in the index - // order, return the node before which we have to insert the new one; - // else, return null to indicate that the new node can be appended. - return this.getNextElement(rightIndex); - }, - - /** - * APIMethod: remove - * - * Parameters: - * node - {DOMElement} The node to be removed. - */ - remove: function(node) { - var nodeId = node.id; - var arrayIndex = OpenLayers.Util.indexOf(this.order, nodeId); - if (arrayIndex >= 0) { - // Remove it from the order array, as well as deleting the node - // from the indeces hash. - this.order.splice(arrayIndex, 1); - delete this.indices[nodeId]; - - // Reset the maxium z-index based on the last item in the - // order array. - if (this.order.length > 0) { - var lastId = this.order[this.order.length - 1]; - this.maxZIndex = this.indices[lastId]; - } else { - this.maxZIndex = 0; - } - } - }, - - /** - * APIMethod: clear - */ - clear: function() { - this.order = []; - this.indices = {}; - this.maxZIndex = 0; - }, - - /** - * APIMethod: exists - * - * Parameters: - * node - {DOMElement} The node to test for existence. - * - * Returns: - * {Boolean} Whether or not the node exists in the indexer? - */ - exists: function(node) { - return (this.indices[node.id] != null); - }, - - /** - * APIMethod: getZIndex - * Get the z-index value for the current node from the node data itself. - * - * Parameters: - * node - {DOMElement} The node whose z-index to get. - * - * Returns: - * {Integer} The z-index value for the specified node (from the node - * data itself). - */ - getZIndex: function(node) { - return node._style.graphicZIndex; - }, - - /** - * Method: determineZIndex - * Determine the z-index for the current node if there isn't one, - * and set the maximum value if we've found a new maximum. - * - * Parameters: - * node - {DOMElement} - */ - determineZIndex: function(node) { - var zIndex = node._style.graphicZIndex; - - // Everything must have a zIndex. If none is specified, - // this means the user *must* (hint: assumption) want this - // node to succomb to drawing order. To enforce drawing order - // over all indexing methods, we'll create a new z-index that's - // greater than any currently in the indexer. - if (zIndex == null) { - zIndex = this.maxZIndex; - node._style.graphicZIndex = zIndex; - } else if (zIndex > this.maxZIndex) { - this.maxZIndex = zIndex; - } - }, - - /** - * APIMethod: getNextElement - * Get the next element in the order stack. - * - * Parameters: - * index - {Integer} The index of the current node in this.order. - * - * Returns: - * {DOMElement} the node following the index passed in, or - * null. - */ - getNextElement: function(index) { - var nextIndex = index + 1; - if (nextIndex < this.order.length) { - var nextElement = OpenLayers.Util.getElement(this.order[nextIndex]); - if (nextElement == undefined) { - nextElement = this.getNextElement(nextIndex); - } - return nextElement; - } else { - return null; - } - }, - - CLASS_NAME: "OpenLayers.ElementsIndexer" -}); - -/** - * Namespace: OpenLayers.ElementsIndexer.IndexingMethods - * These are the compare methods for figuring out where a new node should be - * placed within the indexer. These methods are very similar to general - * sorting methods in that they return -1, 0, and 1 to specify the - * direction in which new nodes fall in the ordering. - */ -OpenLayers.ElementsIndexer.IndexingMethods = { - - /** - * Method: Z_ORDER - * This compare method is used by other comparison methods. - * It can be used individually for ordering, but is not recommended, - * because it doesn't subscribe to drawing order. - * - * Parameters: - * indexer - {} - * newNode - {DOMElement} - * nextNode - {DOMElement} - * - * Returns: - * {Integer} - */ - Z_ORDER: function(indexer, newNode, nextNode) { - var newZIndex = indexer.getZIndex(newNode); - - var returnVal = 0; - if (nextNode) { - var nextZIndex = indexer.getZIndex(nextNode); - returnVal = newZIndex - nextZIndex; - } - - return returnVal; - }, - - /** - * APIMethod: Z_ORDER_DRAWING_ORDER - * This method orders nodes by their z-index, but does so in a way - * that, if there are other nodes with the same z-index, the newest - * drawn will be the front most within that z-index. This is the - * default indexing method. - * - * Parameters: - * indexer - {} - * newNode - {DOMElement} - * nextNode - {DOMElement} - * - * Returns: - * {Integer} - */ - Z_ORDER_DRAWING_ORDER: function(indexer, newNode, nextNode) { - var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER( - indexer, - newNode, - nextNode - ); - - // Make Z_ORDER subscribe to drawing order by pushing it above - // all of the other nodes with the same z-index. - if (nextNode && returnVal == 0) { - returnVal = 1; - } - - return returnVal; - }, - - /** - * APIMethod: Z_ORDER_Y_ORDER - * This one should really be called Z_ORDER_Y_ORDER_DRAWING_ORDER, as it - * best describes which ordering methods have precedence (though, the - * name would be too long). This method orders nodes by their z-index, - * but does so in a way that, if there are other nodes with the same - * z-index, the nodes with the lower y position will be "closer" than - * those with a higher y position. If two nodes have the exact same y - * position, however, then this method will revert to using drawing - * order to decide placement. - * - * Parameters: - * indexer - {} - * newNode - {DOMElement} - * nextNode - {DOMElement} - * - * Returns: - * {Integer} - */ - Z_ORDER_Y_ORDER: function(indexer, newNode, nextNode) { - var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER( - indexer, - newNode, - nextNode - ); - - if (nextNode && returnVal === 0) { - var result = nextNode._boundsBottom - newNode._boundsBottom; - returnVal = (result === 0) ? 1 : result; - } - - return returnVal; - } -}; - -/** - * Class: OpenLayers.Renderer.Elements - * This is another virtual class in that it should never be instantiated by - * itself as a Renderer. It exists because there is *tons* of shared - * functionality between different vector libraries which use nodes/elements - * as a base for rendering vectors. - * - * The highlevel bits of code that are implemented here are the adding and - * removing of geometries, which is essentially the same for any - * element-based renderer. The details of creating each node and drawing the - * paths are of course different, but the machinery is the same. - * - * Inherits: - * - - */ -OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, { - - /** - * Property: rendererRoot - * {DOMElement} - */ - rendererRoot: null, - - /** - * Property: root - * {DOMElement} - */ - root: null, - - /** - * Property: vectorRoot - * {DOMElement} - */ - vectorRoot: null, - - /** - * Property: textRoot - * {DOMElement} - */ - textRoot: null, - - /** - * Property: xmlns - * {String} - */ - xmlns: null, - - /** - * Property: xOffset - * {Number} Offset to apply to the renderer viewport translation in x - * direction. If the renderer extent's center is on the right of the - * dateline (i.e. exceeds the world bounds), we shift the viewport to the - * left by one world width. This avoids that features disappear from the - * map viewport. Because our dateline handling logic in other places - * ensures that extents crossing the dateline always have a center - * exceeding the world bounds on the left, we need this offset to make sure - * that the same is true for the renderer extent in pixel space as well. - */ - xOffset: 0, - - /** - * Property: rightOfDateLine - * {Boolean} Keeps track of the location of the map extent relative to the - * date line. The method compares this value (which is the one - * from the previous call) with the current position of the map - * extent relative to the date line and updates the xOffset when the extent - * has moved from one side of the date line to the other. - */ - - /** - * Property: Indexer - * {} An instance of OpenLayers.ElementsIndexer - * created upon initialization if the zIndexing or yOrdering options - * passed to this renderer's constructor are set to true. - */ - indexer: null, - - /** - * Constant: BACKGROUND_ID_SUFFIX - * {String} - */ - BACKGROUND_ID_SUFFIX: "_background", - - /** - * Constant: LABEL_ID_SUFFIX - * {String} - */ - LABEL_ID_SUFFIX: "_label", - - /** - * Constant: LABEL_OUTLINE_SUFFIX - * {String} - */ - LABEL_OUTLINE_SUFFIX: "_outline", - - /** - * Constructor: OpenLayers.Renderer.Elements - * - * Parameters: - * containerID - {String} - * options - {Object} options for this renderer. - * - * Supported options are: - * yOrdering - {Boolean} Whether to use y-ordering - * zIndexing - {Boolean} Whether to use z-indexing. Will be ignored - * if yOrdering is set to true. - */ - initialize: function(containerID, options) { - OpenLayers.Renderer.prototype.initialize.apply(this, arguments); - - this.rendererRoot = this.createRenderRoot(); - this.root = this.createRoot("_root"); - this.vectorRoot = this.createRoot("_vroot"); - this.textRoot = this.createRoot("_troot"); - - this.root.appendChild(this.vectorRoot); - this.root.appendChild(this.textRoot); - - this.rendererRoot.appendChild(this.root); - this.container.appendChild(this.rendererRoot); - - if(options && (options.zIndexing || options.yOrdering)) { - this.indexer = new OpenLayers.ElementsIndexer(options.yOrdering); - } - }, - - /** - * Method: destroy - */ - destroy: function() { - - this.clear(); - - this.rendererRoot = null; - this.root = null; - this.xmlns = null; - - OpenLayers.Renderer.prototype.destroy.apply(this, arguments); - }, - - /** - * Method: clear - * Remove all the elements from the root - */ - clear: function() { - var child; - var root = this.vectorRoot; - if (root) { - while (child = root.firstChild) { - root.removeChild(child); - } - } - root = this.textRoot; - if (root) { - while (child = root.firstChild) { - root.removeChild(child); - } - } - if (this.indexer) { - this.indexer.clear(); - } - }, - - /** - * Method: setExtent - * Set the visible part of the layer. - * - * 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) { - var coordSysUnchanged = OpenLayers.Renderer.prototype.setExtent.apply(this, arguments); - var resolution = this.getResolution(); - if (this.map.baseLayer && this.map.baseLayer.wrapDateLine) { - var rightOfDateLine, - ratio = extent.getWidth() / this.map.getExtent().getWidth(), - extent = extent.scale(1 / ratio), - world = this.map.getMaxExtent(); - if (world.right > extent.left && world.right < extent.right) { - rightOfDateLine = true; - } else if (world.left > extent.left && world.left < extent.right) { - rightOfDateLine = false; - } - if (rightOfDateLine !== this.rightOfDateLine || resolutionChanged) { - coordSysUnchanged = false; - this.xOffset = rightOfDateLine === true ? - world.getWidth() / resolution : 0; - } - this.rightOfDateLine = rightOfDateLine; - } - return coordSysUnchanged; - }, - - /** - * Method: getNodeType - * This function is in charge of asking the specific renderer which type - * of node to create for the given geometry and style. All geometries - * in an Elements-based renderer consist of one node and some - * attributes. We have the nodeFactory() function which creates a node - * for us, but it takes a 'type' as input, and that is precisely what - * this function tells us. - * - * Parameters: - * geometry - {} - * style - {Object} - * - * Returns: - * {String} The corresponding node type for the specified geometry - */ - getNodeType: function(geometry, style) { }, - - /** - * Method: drawGeometry - * Draw the geometry, creating new nodes, setting paths, setting style, - * setting featureId on the node. This method should only be called - * by the renderer itself. - * - * Parameters: - * geometry - {} - * style - {Object} - * featureId - {String} - * - * Returns: - * {Boolean} true if the geometry has been drawn completely; null if - * incomplete; false otherwise - */ - drawGeometry: function(geometry, style, featureId) { - var className = geometry.CLASS_NAME; - var rendered = true; - if ((className == "OpenLayers.Geometry.Collection") || - (className == "OpenLayers.Geometry.MultiPoint") || - (className == "OpenLayers.Geometry.MultiLineString") || - (className == "OpenLayers.Geometry.MultiPolygon")) { - for (var i = 0, len=geometry.components.length; i} - * style - {Object} - * featureId - {String} - * - * Returns: - * {Boolean} true if the complete geometry could be drawn, null if parts of - * the geometry could not be drawn, false otherwise - */ - redrawNode: function(id, geometry, style, featureId) { - style = this.applyDefaultSymbolizer(style); - // Get the node if it's already on the map. - var node = this.nodeFactory(id, this.getNodeType(geometry, style)); - - // Set the data for the node, then draw it. - node._featureId = featureId; - node._boundsBottom = geometry.getBounds().bottom; - node._geometryClass = geometry.CLASS_NAME; - node._style = style; - - var drawResult = this.drawGeometryNode(node, geometry, style); - if(drawResult === false) { - return false; - } - - node = drawResult.node; - - // Insert the node into the indexer so it can show us where to - // place it. Note that this operation is O(log(n)). If there's a - // performance problem (when dragging, for instance) this is - // likely where it would be. - if (this.indexer) { - var insert = this.indexer.insert(node); - if (insert) { - this.vectorRoot.insertBefore(node, insert); - } else { - this.vectorRoot.appendChild(node); - } - } else { - // if there's no indexer, simply append the node to root, - // but only if the node is a new one - if (node.parentNode !== this.vectorRoot){ - this.vectorRoot.appendChild(node); - } - } - - this.postDraw(node); - - return drawResult.complete; - }, - - /** - * Method: redrawBackgroundNode - * Redraws the node using special 'background' style properties. Basically - * just calls redrawNode(), but instead of directly using the - * 'externalGraphic', 'graphicXOffset', 'graphicYOffset', and - * 'graphicZIndex' properties directly from the specified 'style' - * parameter, we create a new style object and set those properties - * from the corresponding 'background'-prefixed properties from - * specified 'style' parameter. - * - * Parameters: - * id - {String} - * geometry - {} - * style - {Object} - * featureId - {String} - * - * Returns: - * {Boolean} true if the complete geometry could be drawn, null if parts of - * the geometry could not be drawn, false otherwise - */ - redrawBackgroundNode: function(id, geometry, style, featureId) { - var backgroundStyle = OpenLayers.Util.extend({}, style); - - // Set regular style attributes to apply to the background styles. - backgroundStyle.externalGraphic = backgroundStyle.backgroundGraphic; - backgroundStyle.graphicXOffset = backgroundStyle.backgroundXOffset; - backgroundStyle.graphicYOffset = backgroundStyle.backgroundYOffset; - backgroundStyle.graphicZIndex = backgroundStyle.backgroundGraphicZIndex; - backgroundStyle.graphicWidth = backgroundStyle.backgroundWidth || backgroundStyle.graphicWidth; - backgroundStyle.graphicHeight = backgroundStyle.backgroundHeight || backgroundStyle.graphicHeight; - - // Erase background styles. - backgroundStyle.backgroundGraphic = null; - backgroundStyle.backgroundXOffset = null; - backgroundStyle.backgroundYOffset = null; - backgroundStyle.backgroundGraphicZIndex = null; - - return this.redrawNode( - id + this.BACKGROUND_ID_SUFFIX, - geometry, - backgroundStyle, - null - ); - }, - - /** - * Method: drawGeometryNode - * Given a node, draw a geometry on the specified layer. - * node and geometry are required arguments, style is optional. - * This method is only called by the render itself. - * - * Parameters: - * node - {DOMElement} - * geometry - {} - * style - {Object} - * - * Returns: - * {Object} a hash with properties "node" (the drawn node) and "complete" - * (null if parts of the geometry could not be drawn, false if nothing - * could be drawn) - */ - drawGeometryNode: function(node, geometry, style) { - style = style || node._style; - - var options = { - 'isFilled': style.fill === undefined ? - true : - style.fill, - 'isStroked': style.stroke === undefined ? - !!style.strokeWidth : - style.stroke - }; - var drawn; - switch (geometry.CLASS_NAME) { - case "OpenLayers.Geometry.Point": - if(style.graphic === false) { - options.isFilled = false; - options.isStroked = false; - } - drawn = this.drawPoint(node, geometry); - break; - case "OpenLayers.Geometry.LineString": - options.isFilled = false; - drawn = this.drawLineString(node, geometry); - break; - case "OpenLayers.Geometry.LinearRing": - drawn = this.drawLinearRing(node, geometry); - break; - case "OpenLayers.Geometry.Polygon": - drawn = this.drawPolygon(node, geometry); - break; - case "OpenLayers.Geometry.Rectangle": - drawn = this.drawRectangle(node, geometry); - break; - default: - break; - } - - node._options = options; - - //set style - //TBD simplify this - if (drawn != false) { - return { - node: this.setStyle(node, style, options, geometry), - complete: drawn - }; - } else { - return false; - } - }, - - /** - * Method: postDraw - * Things that have do be done after the geometry node is appended - * to its parent node. To be overridden by subclasses. - * - * Parameters: - * node - {DOMElement} - */ - postDraw: function(node) {}, - - /** - * Method: drawPoint - * Virtual function for drawing Point Geometry. - * Should be implemented by subclasses. - * This method is only called by the renderer itself. - * - * Parameters: - * node - {DOMElement} - * geometry - {} - * - * Returns: - * {DOMElement} or false if the renderer could not draw the point - */ - drawPoint: function(node, geometry) {}, - - /** - * Method: drawLineString - * Virtual function for drawing LineString Geometry. - * Should be implemented by subclasses. - * This method is only called by the renderer itself. - * - * Parameters: - * node - {DOMElement} - * geometry - {} - * - * Returns: - * {DOMElement} or null if the renderer could not draw all components of - * the linestring, or false if nothing could be drawn - */ - drawLineString: function(node, geometry) {}, - - /** - * Method: drawLinearRing - * Virtual function for drawing LinearRing Geometry. - * Should be implemented by subclasses. - * This method is only called by the renderer itself. - * - * Parameters: - * node - {DOMElement} - * geometry - {} - * - * Returns: - * {DOMElement} or null if the renderer could not draw all components - * of the linear ring, or false if nothing could be drawn - */ - drawLinearRing: function(node, geometry) {}, - - /** - * Method: drawPolygon - * Virtual function for drawing Polygon Geometry. - * Should be implemented by subclasses. - * This method is only called by the renderer itself. - * - * Parameters: - * node - {DOMElement} - * geometry - {} - * - * Returns: - * {DOMElement} or null if the renderer could not draw all components - * of the polygon, or false if nothing could be drawn - */ - drawPolygon: function(node, geometry) {}, - - /** - * Method: drawRectangle - * Virtual function for drawing Rectangle Geometry. - * Should be implemented by subclasses. - * This method is only called by the renderer itself. - * - * Parameters: - * node - {DOMElement} - * geometry - {} - * - * Returns: - * {DOMElement} or false if the renderer could not draw the rectangle - */ - drawRectangle: function(node, geometry) {}, - - /** - * Method: drawCircle - * Virtual function for drawing Circle Geometry. - * Should be implemented by subclasses. - * This method is only called by the renderer itself. - * - * Parameters: - * node - {DOMElement} - * geometry - {} - * - * Returns: - * {DOMElement} or false if the renderer could not draw the circle - */ - drawCircle: function(node, geometry) {}, - - /** - * Method: removeText - * Removes a label - * - * Parameters: - * featureId - {String} - */ - removeText: function(featureId) { - var label = document.getElementById(featureId + this.LABEL_ID_SUFFIX); - if (label) { - this.textRoot.removeChild(label); - } - var outline = document.getElementById(featureId + this.LABEL_OUTLINE_SUFFIX); - if (outline) { - this.textRoot.removeChild(outline); - } - }, - - /** - * Method: getFeatureIdFromEvent - * - * Parameters: - * evt - {Object} An object - * - * Returns: - * {String} A feature id or undefined. - */ - getFeatureIdFromEvent: function(evt) { - var target = evt.target; - var useElement = target && target.correspondingUseElement; - var node = useElement ? useElement : (target || evt.srcElement); - return node._featureId; - }, - - /** - * Method: eraseGeometry - * Erase a geometry from the renderer. In the case of a multi-geometry, - * we cycle through and recurse on ourselves. Otherwise, we look for a - * node with the geometry.id, destroy its geometry, and remove it from - * the DOM. - * - * Parameters: - * geometry - {} - * featureId - {String} - */ - eraseGeometry: function(geometry, featureId) { - if ((geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPoint") || - (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiLineString") || - (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon") || - (geometry.CLASS_NAME == "OpenLayers.Geometry.Collection")) { - for (var i=0, len=geometry.components.length; i} target renderer for the moved root - */ - moveRoot: function(renderer) { - var root = this.root; - if(renderer.root.parentNode == this.rendererRoot) { - root = renderer.root; - } - root.parentNode.removeChild(root); - renderer.rendererRoot.appendChild(root); - }, - - /** - * 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.root.parentNode.parentNode.id; - }, - - /** - * Method: isComplexSymbol - * Determines if a symbol cannot be rendered using drawCircle - * - * Parameters: - * graphicName - {String} - * - * Returns - * {Boolean} true if the symbol is complex, false if not - */ - isComplexSymbol: function(graphicName) { - return (graphicName != "circle") && !!graphicName; - }, - - CLASS_NAME: "OpenLayers.Renderer.Elements" -}); - -/* ====================================================================== - OpenLayers/Control/Panel.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/Events/buttonclick.js - */ - -/** - * Class: OpenLayers.Control.Panel - * The Panel control is a container for other controls. With it toolbars - * may be composed. - * - * Inherits from: - * - - */ -OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, { - /** - * Property: controls - * {Array()} - */ - controls: null, - - /** - * APIProperty: autoActivate - * {Boolean} Activate the control when it is added to a map. Default is - * true. - */ - autoActivate: true, - - /** - * APIProperty: defaultControl - * {} The control which is activated when the control is - * activated (turned on), which also happens at instantiation. - * If is true, will be nullified after the - * first activation of the panel. - */ - defaultControl: null, - - /** - * APIProperty: saveState - * {Boolean} If set to true, the active state of this panel's controls will - * be stored on panel deactivation, and restored on reactivation. Default - * is false. - */ - saveState: false, - - /** - * APIProperty: allowDepress - * {Boolean} If is true the controls can - * be deactivated by clicking the icon that represents them. Default - * is false. - */ - allowDepress: false, - - /** - * Property: activeState - * {Object} stores the active state of this panel's controls. - */ - activeState: null, - - /** - * Constructor: OpenLayers.Control.Panel - * Create a new control panel. - * - * Each control in the panel is represented by an icon. When clicking - * on an icon, the method is called. - * - * Specific properties for controls on a panel: - * type - {Number} One of , - * , . - * If not provided, is assumed. - * title - {string} Text displayed when mouse is over the icon that - * represents the control. - * - * The of a control determines the behavior when - * clicking its icon: - * - The control is activated and other - * controls of this type in the same panel are deactivated. This is - * the default type. - * - The active state of the control is - * toggled. - * - The - * method of the control is called, - * but its active state is not changed. - * - * If a control is , it will be drawn with the - * olControl[Name]ItemActive class, otherwise with the - * olControl[Name]ItemInactive class. - * - * Parameters: - * options - {Object} An optional object whose properties will be used - * to extend the control. - */ - initialize: function(options) { - OpenLayers.Control.prototype.initialize.apply(this, [options]); - this.controls = []; - this.activeState = {}; - }, - - /** - * APIMethod: destroy - */ - destroy: function() { - if (this.map) { - this.map.events.unregister("buttonclick", this, this.onButtonClick); - } - OpenLayers.Control.prototype.destroy.apply(this, arguments); - for (var ctl, i = this.controls.length - 1; i >= 0; i--) { - ctl = this.controls[i]; - if (ctl.events) { - ctl.events.un({ - activate: this.iconOn, - deactivate: this.iconOff - }); - } - ctl.panel_div = null; - } - this.activeState = null; - }, - - /** - * APIMethod: activate - */ - activate: function() { - if (OpenLayers.Control.prototype.activate.apply(this, arguments)) { - var control; - for (var i=0, len=this.controls.length; i=0; i--) { - this.div.removeChild(this.div.childNodes[i]); - } - this.div.innerHTML = ""; - if (this.active) { - for (var i=0, len=this.controls.length; i} - */ - activateControl: function (control) { - if (!this.active) { return false; } - if (control.type == OpenLayers.Control.TYPE_BUTTON) { - control.trigger(); - return; - } - if (control.type == OpenLayers.Control.TYPE_TOGGLE) { - if (control.active) { - control.deactivate(); - } else { - control.activate(); - } - return; - } - if (this.allowDepress && control.active) { - control.deactivate(); - } else { - var c; - for (var i=0, len=this.controls.length; i} Controls to add in the panel. - */ - addControls: function(controls) { - if (!(OpenLayers.Util.isArray(controls))) { - controls = [controls]; - } - this.controls = this.controls.concat(controls); - - for (var i=0, len=controls.length; i} The control to create the HTML - * markup for. - * - * Returns: - * {DOMElement} The markup. - */ - createControlMarkup: function(control) { - return document.createElement("div"); - }, - - /** - * Method: addControlsToMap - * Only for internal use in draw() and addControls() methods. - * - * Parameters: - * controls - {Array()} Controls to add into map. - */ - addControlsToMap: function (controls) { - var control; - for (var i=0, len=controls.length; i=0; --i) { - if (controls[i].panel_div === button) { - this.activateControl(controls[i]); - break; - } - } - }, - - /** - * APIMethod: getControlsBy - * Get a list of controls with properties matching the given criteria. - * - * Parameters: - * property - {String} A control property to be matched. - * match - {String | Object} A string to match. Can also be a regular - * expression literal or object. In addition, it can be any object - * with a method named test. For reqular expressions or other, if - * match.test(control[property]) evaluates to true, the control will be - * included in the array returned. If no controls are found, an empty - * array is returned. - * - * Returns: - * {Array()} A list of controls matching the given criteria. - * An empty array is returned if no matches are found. - */ - getControlsBy: function(property, match) { - var test = (typeof match.test == "function"); - var found = OpenLayers.Array.filter(this.controls, function(item) { - return item[property] == match || (test && match.test(item[property])); - }); - return found; - }, - - /** - * APIMethod: getControlsByName - * Get a list of contorls with names matching the given name. - * - * Parameters: - * match - {String | Object} A control name. The name can also be a regular - * expression literal or object. In addition, it can be any object - * with a method named test. For reqular expressions or other, if - * name.test(control.name) evaluates to true, the control will be included - * in the list of controls returned. If no controls are found, an empty - * array is returned. - * - * Returns: - * {Array()} A list of controls matching the given name. - * An empty array is returned if no matches are found. - */ - getControlsByName: function(match) { - return this.getControlsBy("name", match); - }, - - /** - * APIMethod: getControlsByClass - * Get a list of controls of a given type (CLASS_NAME). - * - * Parameters: - * match - {String | Object} A control class name. The type can also be a - * regular expression literal or object. In addition, it can be any - * object with a method named test. For reqular expressions or other, - * if type.test(control.CLASS_NAME) evaluates to true, the control will - * be included in the list of controls returned. If no controls are - * found, an empty array is returned. - * - * Returns: - * {Array()} A list of controls matching the given type. - * An empty array is returned if no matches are found. - */ - getControlsByClass: function(match) { - return this.getControlsBy("CLASS_NAME", match); - }, - - CLASS_NAME: "OpenLayers.Control.Panel" -}); - -/* ====================================================================== - 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/Strategy/Fixed.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/Strategy.js - */ - -/** - * Class: OpenLayers.Strategy.Fixed - * A simple strategy that requests features once and never requests new data. - * - * Inherits from: - * - - */ -OpenLayers.Strategy.Fixed = OpenLayers.Class(OpenLayers.Strategy, { - - /** - * APIProperty: preload - * {Boolean} Load data before layer made visible. Enabling this may result - * in considerable overhead if your application loads many data layers - * that are not visible by default. Default is false. - */ - preload: false, - - /** - * Constructor: OpenLayers.Strategy.Fixed - * Create a new Fixed strategy. - * - * Parameters: - * options - {Object} Optional object whose properties will be set on the - * instance. - */ - - /** - * Method: activate - * Activate the strategy: load data or add listener to load when visible - * - * Returns: - * {Boolean} True if the strategy was successfully activated or false if - * the strategy was already active. - */ - activate: function() { - var activated = OpenLayers.Strategy.prototype.activate.apply(this, arguments); - if(activated) { - this.layer.events.on({ - "refresh": this.load, - scope: this - }); - if(this.layer.visibility == true || this.preload) { - this.load(); - } else { - this.layer.events.on({ - "visibilitychanged": this.load, - scope: this - }); - } - } - return activated; - }, - - /** - * Method: deactivate - * Deactivate the strategy. Undo what is done in . - * - * Returns: - * {Boolean} The strategy was successfully deactivated. - */ - deactivate: function() { - var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this); - if(deactivated) { - this.layer.events.un({ - "refresh": this.load, - "visibilitychanged": this.load, - scope: this - }); - } - return deactivated; - }, - - /** - * Method: load - * Tells protocol to load data and unhooks the visibilitychanged event - * - * Parameters: - * options - {Object} options to pass to protocol read. - */ - load: function(options) { - var layer = this.layer; - layer.events.triggerEvent("loadstart", {filter: layer.filter}); - layer.protocol.read(OpenLayers.Util.applyDefaults({ - callback: this.merge, - filter: layer.filter, - scope: this - }, options)); - layer.events.un({ - "visibilitychanged": this.load, - scope: this - }); - }, - - /** - * Method: merge - * Add all features to the layer. - * If the layer projection differs from the map projection, features - * will be transformed from the layer projection to the map projection. - * - * Parameters: - * resp - {} The response object passed - * by the protocol. - */ - merge: function(resp) { - var layer = this.layer; - layer.destroyFeatures(); - var features = resp.features; - if (features && features.length > 0) { - var remote = layer.projection; - var local = layer.map.getProjectionObject(); - if(!local.equals(remote)) { - var geom; - for(var i=0, len=features.length; i - */ -OpenLayers.Control.Zoom = OpenLayers.Class(OpenLayers.Control, { - - /** - * APIProperty: zoomInText - * {String} - * Text for zoom-in link. Default is "+". - */ - zoomInText: "+", - - /** - * APIProperty: zoomInId - * {String} - * Instead of having the control create a zoom in link, you can provide - * the identifier for an anchor element already added to the document. - * By default, an element with id "olZoomInLink" will be searched for - * and used if it exists. - */ - zoomInId: "olZoomInLink", - - /** - * APIProperty: zoomOutText - * {String} - * Text for zoom-out link. Default is "\u2212". - */ - zoomOutText: "\u2212", - - /** - * APIProperty: zoomOutId - * {String} - * Instead of having the control create a zoom out link, you can provide - * the identifier for an anchor element already added to the document. - * By default, an element with id "olZoomOutLink" will be searched for - * and used if it exists. - */ - zoomOutId: "olZoomOutLink", - - /** - * Method: draw - * - * Returns: - * {DOMElement} A reference to the DOMElement containing the zoom links. - */ - draw: function() { - var div = OpenLayers.Control.prototype.draw.apply(this), - links = this.getOrCreateLinks(div), - zoomIn = links.zoomIn, - zoomOut = links.zoomOut, - eventsInstance = this.map.events; - - if (zoomOut.parentNode !== div) { - eventsInstance = this.events; - eventsInstance.attachToElement(zoomOut.parentNode); - } - eventsInstance.register("buttonclick", this, this.onZoomClick); - - this.zoomInLink = zoomIn; - this.zoomOutLink = zoomOut; - return div; - }, - - /** - * Method: getOrCreateLinks - * - * Parameters: - * el - {DOMElement} - * - * Return: - * {Object} Object with zoomIn and zoomOut properties referencing links. - */ - getOrCreateLinks: function(el) { - var zoomIn = document.getElementById(this.zoomInId), - zoomOut = document.getElementById(this.zoomOutId); - if (!zoomIn) { - zoomIn = document.createElement("a"); - zoomIn.href = "#zoomIn"; - zoomIn.appendChild(document.createTextNode(this.zoomInText)); - zoomIn.className = "olControlZoomIn"; - el.appendChild(zoomIn); - } - OpenLayers.Element.addClass(zoomIn, "olButton"); - if (!zoomOut) { - zoomOut = document.createElement("a"); - zoomOut.href = "#zoomOut"; - zoomOut.appendChild(document.createTextNode(this.zoomOutText)); - zoomOut.className = "olControlZoomOut"; - el.appendChild(zoomOut); - } - OpenLayers.Element.addClass(zoomOut, "olButton"); - return { - zoomIn: zoomIn, zoomOut: zoomOut - }; - }, - - /** - * Method: onZoomClick - * Called when zoomin/out link is clicked. - */ - onZoomClick: function(evt) { - var button = evt.buttonElement; - if (button === this.zoomInLink) { - this.map.zoomIn(); - } else if (button === this.zoomOutLink) { - this.map.zoomOut(); - } - }, - - /** - * Method: destroy - * Clean up. - */ - destroy: function() { - if (this.map) { - this.map.events.unregister("buttonclick", this, this.onZoomClick); - } - delete this.zoomInLink; - delete this.zoomOutLink; - OpenLayers.Control.prototype.destroy.apply(this); - }, - - CLASS_NAME: "OpenLayers.Control.Zoom" -}); -/* ====================================================================== - 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/Protocol/WFS.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/Protocol.js - */ - -/** - * Class: OpenLayers.Protocol.WFS - * Used to create a versioned WFS protocol. Default version is 1.0.0. - * - * Returns: - * {} A WFS protocol of the given version. - * - * Example: - * (code) - * var protocol = new OpenLayers.Protocol.WFS({ - * version: "1.1.0", - * url: "http://demo.opengeo.org/geoserver/wfs", - * featureType: "tasmania_roads", - * featureNS: "http://www.openplans.org/topp", - * geometryName: "the_geom" - * }); - * (end) - * - * See the protocols for specific WFS versions for more detail. - */ -OpenLayers.Protocol.WFS = function(options) { - options = OpenLayers.Util.applyDefaults( - options, OpenLayers.Protocol.WFS.DEFAULTS - ); - var cls = OpenLayers.Protocol.WFS["v"+options.version.replace(/\./g, "_")]; - if(!cls) { - throw "Unsupported WFS version: " + options.version; - } - return new cls(options); -}; - -/** - * Function: fromWMSLayer - * Convenience function to create a WFS protocol from a WMS layer. This makes - * the assumption that a WFS requests can be issued at the same URL as - * WMS requests and that a WFS featureType exists with the same name as the - * WMS layer. - * - * This function is designed to auto-configure , , - * and for WFS 1.1.0. Note that - * srsName matching with the WMS layer will not work with WFS 1.0.0. - * - * Parameters: - * layer - {} WMS layer that has a matching WFS - * FeatureType at the same server url with the same typename. - * options - {Object} Default properties to be set on the protocol. - * - * Returns: - * {} - */ -OpenLayers.Protocol.WFS.fromWMSLayer = function(layer, options) { - var typeName, featurePrefix; - var param = layer.params["LAYERS"]; - var parts = (OpenLayers.Util.isArray(param) ? param[0] : param).split(":"); - if(parts.length > 1) { - featurePrefix = parts[0]; - } - typeName = parts.pop(); - var protocolOptions = { - url: layer.url, - featureType: typeName, - featurePrefix: featurePrefix, - srsName: layer.projection && layer.projection.getCode() || - layer.map && layer.map.getProjectionObject().getCode(), - version: "1.1.0" - }; - return new OpenLayers.Protocol.WFS(OpenLayers.Util.applyDefaults( - options, protocolOptions - )); -}; - -/** - * Constant: OpenLayers.Protocol.WFS.DEFAULTS - */ -OpenLayers.Protocol.WFS.DEFAULTS = { - "version": "1.0.0" -}; -/* ====================================================================== - 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/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/Format/KML.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 - */ - -/** - * Class: OpenLayers.Format.KML - * Read/Write KML. Create a new instance with the - * constructor. - * - * Inherits from: - * - - */ -OpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, { - - /** - * Property: namespaces - * {Object} Mapping of namespace aliases to namespace URIs. - */ - namespaces: { - kml: "http://www.opengis.net/kml/2.2", - gx: "http://www.google.com/kml/ext/2.2" - }, - - /** - * 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. - */ - foldersDesc: "Exported on " + new Date(), - - /** - * 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. - */ - extractAttributes: true, - - /** - * 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. - */ - kvpAttributes: false, - - /** - * Property: extractStyles - * {Boolean} Extract styles from KML. Default is false. - * Extracting styleUrls also requires extractAttributes to be - * set to true - */ - extractStyles: false, - - /** - * 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. - */ - extractTracks: 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 . - */ - trackAttributes: null, - - /** - * Property: internalns - * {String} KML Namespace to use -- defaults to the namespace of the - * Placemark node being parsed, but falls back to kmlns. - */ - internalns: null, - - /** - * Property: features - * {Array} Array of features - * - */ - features: null, - - /** - * Property: styles - * {Object} Storage of style objects - * - */ - styles: null, - - /** - * Property: styleBaseUrl - * {String} - */ - styleBaseUrl: "", - - /** - * Property: fetched - * {Object} Storage of KML URLs that have been fetched before - * in order to prevent reloading them. - */ - fetched: null, - - /** - * APIProperty: maxDepth - * {Integer} Maximum depth for recursive loading external KML URLs - * Defaults to 0: do no external fetching - */ - maxDepth: 0, - - /** - * Constructor: OpenLayers.Format.KML - * Create a new parser for KML. - * - * Parameters: - * options - {Object} An optional object whose properties will be set on - * this instance. - */ - 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]); - }, - - /** - * APIMethod: read - * Read data from a string, and return a list of features. - * - * Parameters: - * data - {String} or {DOMElement} data to read/parse. - * - * Returns: - * {Array()} List of features. - */ - read: function(data) { - this.features = []; - this.styles = {}; - this.fetched = {}; - - // Set default options - var options = { - depth: 0, - styleBaseUrl: this.styleBaseUrl - }; - - return this.parseData(data, options); - }, - - /** - * 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 - * - * Returns: - * {Array()} List of features. - */ - 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 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++; - - for(var i=0, len=nodes.length; i nodes - * - * Parameters: - * nodes - {Array} of {DOMElement} data to read/parse. - * options - {Object} Hash of options - * - */ - parseStyles: function(nodes, options) { - for(var i=0, len=nodes.length; i node and builds the style hash - * accordingly - * - * Parameters: - * node - {DOMElement}