/* OpenLayers.js -- OpenLayers Map Viewer Library Copyright (c) 2006-2012 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. */ var OpenLayers = { VERSION_NUMBER: "Release 2.12", singleFile: true, _getScriptLocation: (function() { var r = new RegExp("(^|(.*?\\/))(OpenLayers[^\\/]*?\\.js)(\\?|$)"), s = document.getElementsByTagName("script"), src, m, l = ""; for (var i = 0, len = s.length; i < len; i++) { src = s[i].getAttribute("src"); if (src) { m = src.match(r); if (m) { l = m[1]; break; } } } return function() { return l; }; })(), ImgPath: "" }; OpenLayers.Class = function() { var len = arguments.length; var P = arguments[0]; var F = arguments[len - 1]; var C = typeof F.initialize == "function" ? F.initialize : function() { P.prototype.initialize.apply(this, arguments); }; if (len > 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; }; 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 < l; i++) { o = arguments[i]; if (typeof o === "function") { o = o.prototype; } OpenLayers.Util.extend(C.prototype, o); } }; OpenLayers.Util = OpenLayers.Util || {}; OpenLayers.Util.extend = function(destination, source) { destination = destination || {}; if (source) { for (var property in source) { var value = source[property]; if (value !== undefined) { destination[property] = value; } } var sourceIsEvt = typeof window.Event == "function" && source instanceof window.Event; if ( !sourceIsEvt && source.hasOwnProperty && source.hasOwnProperty("toString") ) { destination.toString = source.toString; } } return destination; }; OpenLayers.Pixel = OpenLayers.Class({ x: 0.0, y: 0.0, initialize: function(x, y) { this.x = parseFloat(x); this.y = parseFloat(y); }, toString: function() { return "x=" + this.x + ",y=" + this.y; }, clone: function() { return new OpenLayers.Pixel(this.x, this.y); }, 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; }, distanceTo: function(px) { return Math.sqrt(Math.pow(this.x - px.x, 2) + Math.pow(this.y - px.y, 2)); }, 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); }, offset: function(px) { var newPx = this.clone(); if (px) { newPx = this.add(px.x, px.y); } return newPx; }, CLASS_NAME: "OpenLayers.Pixel" }); OpenLayers.String = { startsWith: function(str, sub) { return str.indexOf(sub) == 0; }, contains: function(str, sub) { return str.indexOf(sub) != -1; }, trim: function(str) { return str.replace(/^\s\s*/, "").replace(/\s\s*$/, ""); }, camelize: function(str) { var oStringList = str.split("-"); var camelizedString = oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, format: function(template, context, args) { if (!context) { context = window; } var replacer = function(str, match) { var replacement; var subs = match.split(/\.+/); for (var i = 0; i < subs.length; i++) { if (i == 0) { replacement = context; } replacement = replacement[subs[i]]; } if (typeof replacement == "function") { replacement = args ? replacement.apply(null, args) : replacement(); } if (typeof replacement == "undefined") { return "undefined"; } else { return replacement; } }; return template.replace(OpenLayers.String.tokenRegEx, replacer); }, tokenRegEx: /\$\{([\w.]+?)\}/g, numberRegEx: /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/, isNumeric: function(value) { return OpenLayers.String.numberRegEx.test(value); }, numericIf: function(value) { return OpenLayers.String.isNumeric(value) ? parseFloat(value) : value; } }; OpenLayers.Number = { decimalSeparator: ".", thousandsSeparator: ",", limitSigDigs: function(num, sig) { var fig = 0; if (sig > 0) { fig = parseFloat(num.toPrecision(sig)); } return fig; }, 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) { 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; } }; OpenLayers.Function = { bind: function(func, object) { var args = Array.prototype.slice.apply(arguments, [2]); return function() { var newArgs = args.concat(Array.prototype.slice.apply(arguments, [0])); return func.apply(object, newArgs); }; }, bindAsEventListener: function(func, object) { return function(event) { return func.call(object, event || window.event); }; }, False: function() { return false; }, True: function() { return true; }, Void: function() {} }; OpenLayers.Array = { 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 < len; i++) { if (i in array) { var val = array[i]; if (callback.call(caller, val, i, array)) { selected.push(val); } } } } return selected; } }; OpenLayers.Bounds = OpenLayers.Class({ left: null, bottom: null, right: null, top: null, centerLonLat: null, 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); } }, clone: function() { return new OpenLayers.Bounds(this.left, this.bottom, this.right, this.top); }, 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; }, toString: function() { return [this.left, this.bottom, this.right, this.top].join(","); }, 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]; } }, 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; } }, 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) ]) ]); }, getWidth: function() { return this.right - this.left; }, getHeight: function() { return this.top - this.bottom; }, getSize: function() { return new OpenLayers.Size(this.getWidth(), this.getHeight()); }, getCenterPixel: function() { return new OpenLayers.Pixel( (this.left + this.right) / 2, (this.bottom + this.top) / 2 ); }, getCenterLonLat: function() { if (!this.centerLonLat) { this.centerLonLat = new OpenLayers.LonLat( (this.left + this.right) / 2, (this.bottom + this.top) / 2 ); } return this.centerLonLat; }, scale: function(ratio, origin) { if (origin == null) { origin = this.getCenterLonLat(); } var origx, origy; 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); }, 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 ); }, extend: function(object) { var bounds = null; if (object) { switch (object.CLASS_NAME) { case "OpenLayers.LonLat": bounds = new OpenLayers.Bounds( object.lon, object.lat, object.lon, object.lat ); break; case "OpenLayers.Geometry.Point": bounds = new OpenLayers.Bounds( object.x, object.y, object.x, object.y ); break; case "OpenLayers.Bounds": bounds = object; break; } if (bounds) { this.centerLonLat = null; if (this.left == null || bounds.left < this.left) { this.left = bounds.left; } if (this.bottom == null || bounds.bottom < this.bottom) { this.bottom = bounds.bottom; } if (this.right == null || bounds.right > this.right) { this.right = bounds.right; } if (this.top == null || bounds.top > this.top) { this.top = bounds.top; } } } }, 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; }, containsPixel: function(px, inclusive) { return this.contains(px.x, px.y, inclusive); }, contains: function(x, y, inclusive) { 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; }, 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 (options.inclusive || !mightTouch) { 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); } 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; }, 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; }, 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; }, transform: function(source, dest) { 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; }, 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(); while ( newBounds.left < maxExtent.left && newBounds.right - rightTolerance <= maxExtent.left ) { newBounds = newBounds.add(width, 0); } while ( newBounds.left + leftTolerance >= maxExtent.right && newBounds.right > maxExtent.right ) { newBounds = newBounds.add(-width, 0); } 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" }); OpenLayers.Bounds.fromString = function(str, reverseAxisOrder) { var bounds = str.split(","); return OpenLayers.Bounds.fromArray(bounds, reverseAxisOrder); }; 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]); }; OpenLayers.Bounds.fromSize = function(size) { return new OpenLayers.Bounds(0, size.h, size.w, 0); }; OpenLayers.Bounds.oppositeQuadrant = function(quadrant) { var opp = ""; opp += quadrant.charAt(0) == "t" ? "b" : "t"; opp += quadrant.charAt(1) == "l" ? "r" : "l"; return opp; }; OpenLayers.Element = { visible: function(element) { return OpenLayers.Util.getElement(element).style.display != "none"; }, toggle: function() { for (var i = 0, len = arguments.length; i < len; i++) { var element = OpenLayers.Util.getElement(arguments[i]); var display = OpenLayers.Element.visible(element) ? "none" : ""; element.style.display = display; } }, remove: function(element) { element = OpenLayers.Util.getElement(element); element.parentNode.removeChild(element); }, getHeight: function(element) { element = OpenLayers.Util.getElement(element); return element.offsetHeight; }, hasClass: function(element, name) { var names = element.className; return !!names && new RegExp("(^|\\s)" + name + "(\\s|$)").test(names); }, addClass: function(element, name) { if (!OpenLayers.Element.hasClass(element, name)) { element.className += (element.className ? " " : "") + name; } return element; }, removeClass: function(element, name) { var names = element.className; if (names) { element.className = OpenLayers.String.trim( names.replace(new RegExp("(^|\\s+)" + name + "(\\s+|$)"), " ") ); } return element; }, toggleClass: function(element, name) { if (OpenLayers.Element.hasClass(element, name)) { OpenLayers.Element.removeClass(element, name); } else { OpenLayers.Element.addClass(element, name); } return element; }, getStyle: function(element, style) { element = OpenLayers.Util.getElement(element); var value = null; if (element && element.style) { value = element.style[OpenLayers.String.camelize(style)]; if (!value) { if (document.defaultView && document.defaultView.getComputedStyle) { var css = document.defaultView.getComputedStyle(element, null); value = css ? css.getPropertyValue(style) : null; } else if (element.currentStyle) { value = element.currentStyle[OpenLayers.String.camelize(style)]; } } var positions = ["left", "top", "right", "bottom"]; if ( window.opera && OpenLayers.Util.indexOf(positions, style) != -1 && OpenLayers.Element.getStyle(element, "position") == "static" ) { value = "auto"; } } return value == "auto" ? null : value; } }; OpenLayers.LonLat = OpenLayers.Class({ lon: 0.0, lat: 0.0, initialize: function(lon, lat) { if (OpenLayers.Util.isArray(lon)) { lat = lon[1]; lon = lon[0]; } this.lon = OpenLayers.Util.toFloat(lon); this.lat = OpenLayers.Util.toFloat(lat); }, toString: function() { return "lon=" + this.lon + ",lat=" + this.lat; }, toShortString: function() { return this.lon + ", " + this.lat; }, clone: function() { return new OpenLayers.LonLat(this.lon, this.lat); }, 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) ); }, 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; }, 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; }, wrapDateLine: function(maxExtent) { var newLonLat = this.clone(); if (maxExtent) { while (newLonLat.lon < maxExtent.left) { newLonLat.lon += maxExtent.getWidth(); } while (newLonLat.lon > maxExtent.right) { newLonLat.lon -= maxExtent.getWidth(); } } return newLonLat; }, CLASS_NAME: "OpenLayers.LonLat" }); OpenLayers.LonLat.fromString = function(str) { var pair = str.split(","); return new OpenLayers.LonLat(pair[0], pair[1]); }; 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.Size = OpenLayers.Class({ w: 0.0, h: 0.0, initialize: function(w, h) { this.w = parseFloat(w); this.h = parseFloat(h); }, toString: function() { return "w=" + this.w + ",h=" + this.h; }, clone: function() { return new OpenLayers.Size(this.w, this.h); }, 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 = { log: function() {}, debug: function() {}, info: function() {}, warn: function() {}, error: function() {}, userError: function(error) { alert(error); }, assert: function() {}, dir: function() {}, dirxml: function() {}, trace: function() {}, group: function() {}, groupEnd: function() {}, time: function() {}, timeEnd: function() {}, profile: function() {}, profileEnd: function() {}, count: function() {}, CLASS_NAME: "OpenLayers.Console" }; (function() { var scripts = document.getElementsByTagName("script"); for (var i = 0, len = scripts.length; i < len; ++i) { if (scripts[i].src.indexOf("firebug.js") != -1) { if (console) { OpenLayers.Util.extend(OpenLayers.Console, console); break; } } } })(); OpenLayers.Lang = { code: null, defaultCode: "en", getCode: function() { if (!OpenLayers.Lang.code) { OpenLayers.Lang.setCode(); } return OpenLayers.Lang.code; }, 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]; } 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; }, translate: function(key, context) { var dictionary = OpenLayers.Lang[OpenLayers.Lang.getCode()]; var message = dictionary && dictionary[key]; if (!message) { message = key; } if (context) { message = OpenLayers.String.format(message, context); } return message; } }; OpenLayers.i18n = OpenLayers.Lang.translate; OpenLayers.Util = OpenLayers.Util || {}; OpenLayers.Util.getElement = function() { var elements = []; for (var i = 0, len = arguments.length; i < len; i++) { var element = arguments[i]; if (typeof element == "string") { element = document.getElementById(element); } if (arguments.length == 1) { return element; } elements.push(element); } return elements; }; OpenLayers.Util.isElement = function(o) { return !!(o && o.nodeType === 1); }; OpenLayers.Util.isArray = function(a) { return Object.prototype.toString.call(a) === "[object Array]"; }; if (typeof window.$ === "undefined") { window.$ = OpenLayers.Util.getElement; } OpenLayers.Util.removeItem = function(array, item) { for (var i = array.length - 1; i >= 0; i--) { if (array[i] == item) { array.splice(i, 1); } } return array; }; OpenLayers.Util.indexOf = function(array, obj) { 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; } }; OpenLayers.Util.modifyDOMElement = function( element, id, px, sz, position, border, overflow, opacity ) { if (id) { element.id = id; } 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 = ""; } }; OpenLayers.Util.createDiv = function( id, px, sz, imgURL, position, border, overflow, opacity ) { var dom = document.createElement("div"); if (imgURL) { dom.style.backgroundImage = "url(" + imgURL + ")"; } if (!id) { id = OpenLayers.Util.createUniqueID("OpenLayersDiv"); } if (!position) { position = "absolute"; } OpenLayers.Util.modifyDOMElement( dom, id, px, sz, position, border, overflow, opacity ); return dom; }; OpenLayers.Util.createImage = function( id, px, sz, imgURL, position, border, opacity, delayDisplay ) { var image = document.createElement("img"); 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); } image.style.alt = id; image.galleryImg = "no"; if (imgURL) { image.src = imgURL; } return image; }; OpenLayers.IMAGE_RELOAD_ATTEMPTS = 0; OpenLayers.Util.alphaHackNeeded = null; OpenLayers.Util.alphaHack = function() { if (OpenLayers.Util.alphaHackNeeded == null) { var arVersion = navigator.appVersion.split("MSIE"); var version = parseFloat(arVersion[1]); var filter = false; try { filter = !!document.body.filters; } catch (e) {} OpenLayers.Util.alphaHackNeeded = filter && version >= 5.5 && version < 7; } return OpenLayers.Util.alphaHackNeeded; }; 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)"; } }; 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; }; OpenLayers.Util.upperCaseObject = function(object) { var uObject = {}; for (var key in object) { uObject[key.toUpperCase()] = object[key]; } return uObject; }; OpenLayers.Util.applyDefaults = function(to, from) { to = to || {}; 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]; } } if ( !fromIsEvt && from && from.hasOwnProperty && from.hasOwnProperty("toString") && !to.hasOwnProperty("toString") ) { to.toString = from.toString; } return to; }; 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) { var encodedItemArray = []; var item; for ( var itemIndex = 0, len = value.length; itemIndex < len; itemIndex++ ) { item = value[itemIndex]; encodedItemArray.push( encodeURIComponent(item === null || item === undefined ? "" : item) ); } encodedValue = encodedItemArray.join(","); } else { encodedValue = encodeURIComponent(value); } paramsArray.push(encodeURIComponent(key) + "=" + encodedValue); } } return paramsArray.join("&"); }; OpenLayers.Util.urlAppend = function(url, paramStr) { var newUrl = url; if (paramStr) { var parts = (url + " ").split(/[?&]/); newUrl += parts.pop() === " " ? paramStr : parts.length ? "&" + paramStr : "?" + paramStr; } return newUrl; }; OpenLayers.Util.getImagesLocation = function() { return OpenLayers.ImgPath || OpenLayers._getScriptLocation() + "img/"; }; OpenLayers.Util.getImageLocation = function(image) { return OpenLayers.Util.getImagesLocation() + image; }; OpenLayers.Util.Try = function() { var returnValue = null; for (var i = 0, len = arguments.length; i < len; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; }; OpenLayers.Util.getXmlNodeValue = function(node) { var val = null; OpenLayers.Util.Try( function() { val = node.text; if (!val) { val = node.textContent; } if (!val) { val = node.firstChild.nodeValue; } }, function() { val = node.textContent; } ); return val; }; OpenLayers.Util.mouseLeft = function(evt, div) { var target = evt.relatedTarget ? evt.relatedTarget : evt.toElement; while (target != div && target != null) { target = target.parentNode; } return target != div; }; OpenLayers.Util.DEFAULT_PRECISION = 14; OpenLayers.Util.toFloat = function(number, precision) { if (precision == null) { precision = OpenLayers.Util.DEFAULT_PRECISION; } if (typeof number !== "number") { number = parseFloat(number); } return precision === 0 ? number : parseFloat(number.toPrecision(precision)); }; OpenLayers.Util.rad = function(x) { return (x * Math.PI) / 180; }; OpenLayers.Util.deg = function(x) { return (x * 180) / Math.PI; }; OpenLayers.Util.VincentyConstants = { a: 6378137, b: 6356752.3142, f: 1 / 298.257223563 }; 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; } 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; } 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; return d; }; 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); return new OpenLayers.LonLat(lon1 + u.deg(L), u.deg(lat2)); }; OpenLayers.Util.getParameters = function(url) { url = url === null || url === undefined ? window.location.href : url; 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 < len; ++i) { var keyValue = pairs[i].split("="); if (keyValue[0]) { var key = keyValue[0]; try { key = decodeURIComponent(key); } catch (err) { key = unescape(key); } var value = (keyValue[1] || "").replace(/\+/g, " "); try { value = decodeURIComponent(value); } catch (err) { value = unescape(value); } value = value.split(","); if (value.length == 1) { value = value[0]; } parameters[key] = value; } } return parameters; }; OpenLayers.Util.lastSeqID = 0; OpenLayers.Util.createUniqueID = function(prefix) { if (prefix == null) { prefix = "id_"; } OpenLayers.Util.lastSeqID += 1; return prefix + OpenLayers.Util.lastSeqID; }; OpenLayers.INCHES_PER_UNIT = { inches: 1.0, ft: 12.0, mi: 63360.0, m: 39.3701, km: 39370.1, dd: 4374754, yd: 36 }; OpenLayers.INCHES_PER_UNIT["in"] = OpenLayers.INCHES_PER_UNIT.inches; OpenLayers.INCHES_PER_UNIT["degrees"] = OpenLayers.INCHES_PER_UNIT.dd; OpenLayers.INCHES_PER_UNIT["nmi"] = 1852 * OpenLayers.INCHES_PER_UNIT.m; OpenLayers.METERS_PER_INCH = 0.0254000508001016002; OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT, { Inch: OpenLayers.INCHES_PER_UNIT.inches, Meter: 1.0 / OpenLayers.METERS_PER_INCH, Foot: 0.30480060960121920243 / OpenLayers.METERS_PER_INCH, IFoot: 0.3048 / OpenLayers.METERS_PER_INCH, ClarkeFoot: 0.3047972651151 / OpenLayers.METERS_PER_INCH, SearsFoot: 0.30479947153867624624 / OpenLayers.METERS_PER_INCH, GoldCoastFoot: 0.30479971018150881758 / OpenLayers.METERS_PER_INCH, IInch: 0.0254 / OpenLayers.METERS_PER_INCH, MicroInch: 0.0000254 / OpenLayers.METERS_PER_INCH, Mil: 0.0000000254 / OpenLayers.METERS_PER_INCH, Centimeter: 0.01 / OpenLayers.METERS_PER_INCH, Kilometer: 1000.0 / OpenLayers.METERS_PER_INCH, Yard: 0.91440182880365760731 / OpenLayers.METERS_PER_INCH, SearsYard: 0.914398414616029 / OpenLayers.METERS_PER_INCH, IndianYard: 0.91439853074444079983 / OpenLayers.METERS_PER_INCH, IndianYd37: 0.91439523 / OpenLayers.METERS_PER_INCH, IndianYd62: 0.9143988 / OpenLayers.METERS_PER_INCH, IndianYd75: 0.9143985 / OpenLayers.METERS_PER_INCH, IndianFoot: 0.30479951 / OpenLayers.METERS_PER_INCH, IndianFt37: 0.30479841 / OpenLayers.METERS_PER_INCH, IndianFt62: 0.3047996 / OpenLayers.METERS_PER_INCH, IndianFt75: 0.3047995 / OpenLayers.METERS_PER_INCH, Mile: 1609.34721869443738887477 / OpenLayers.METERS_PER_INCH, IYard: 0.9144 / OpenLayers.METERS_PER_INCH, IMile: 1609.344 / OpenLayers.METERS_PER_INCH, NautM: 1852.0 / OpenLayers.METERS_PER_INCH, "Lat-66": 110943.316488932731 / OpenLayers.METERS_PER_INCH, "Lat-83": 110946.25736872234125 / OpenLayers.METERS_PER_INCH, Decimeter: 0.1 / OpenLayers.METERS_PER_INCH, Millimeter: 0.001 / OpenLayers.METERS_PER_INCH, Dekameter: 10.0 / OpenLayers.METERS_PER_INCH, Decameter: 10.0 / OpenLayers.METERS_PER_INCH, Hectometer: 100.0 / OpenLayers.METERS_PER_INCH, GermanMeter: 1.0000135965 / OpenLayers.METERS_PER_INCH, CaGrid: 0.999738 / OpenLayers.METERS_PER_INCH, ClarkeChain: 20.1166194976 / OpenLayers.METERS_PER_INCH, GunterChain: 20.11684023368047 / OpenLayers.METERS_PER_INCH, BenoitChain: 20.116782494375872 / OpenLayers.METERS_PER_INCH, SearsChain: 20.11676512155 / OpenLayers.METERS_PER_INCH, ClarkeLink: 0.201166194976 / OpenLayers.METERS_PER_INCH, GunterLink: 0.2011684023368047 / OpenLayers.METERS_PER_INCH, BenoitLink: 0.20116782494375872 / OpenLayers.METERS_PER_INCH, SearsLink: 0.2011676512155 / OpenLayers.METERS_PER_INCH, Rod: 5.02921005842012 / OpenLayers.METERS_PER_INCH, IntnlChain: 20.1168 / OpenLayers.METERS_PER_INCH, IntnlLink: 0.201168 / OpenLayers.METERS_PER_INCH, Perch: 5.02921005842012 / OpenLayers.METERS_PER_INCH, Pole: 5.02921005842012 / OpenLayers.METERS_PER_INCH, Furlong: 201.1684023368046 / OpenLayers.METERS_PER_INCH, Rood: 3.778266898 / OpenLayers.METERS_PER_INCH, CapeFoot: 0.3047972615 / OpenLayers.METERS_PER_INCH, Brealey: 375.0 / OpenLayers.METERS_PER_INCH, ModAmFt: 0.304812252984505969011938 / OpenLayers.METERS_PER_INCH, Fathom: 1.8288 / OpenLayers.METERS_PER_INCH, "NautM-UK": 1853.184 / OpenLayers.METERS_PER_INCH, "50kilometers": 50000.0 / OpenLayers.METERS_PER_INCH, "150kilometers": 150000.0 / OpenLayers.METERS_PER_INCH }); OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT, { mm: OpenLayers.INCHES_PER_UNIT["Meter"] / 1000.0, cm: OpenLayers.INCHES_PER_UNIT["Meter"] / 100.0, dm: OpenLayers.INCHES_PER_UNIT["Meter"] * 100.0, km: OpenLayers.INCHES_PER_UNIT["Meter"] * 1000.0, kmi: OpenLayers.INCHES_PER_UNIT["nmi"], fath: OpenLayers.INCHES_PER_UNIT["Fathom"], ch: OpenLayers.INCHES_PER_UNIT["IntnlChain"], link: OpenLayers.INCHES_PER_UNIT["IntnlLink"], "us-in": OpenLayers.INCHES_PER_UNIT["inches"], "us-ft": OpenLayers.INCHES_PER_UNIT["Foot"], "us-yd": OpenLayers.INCHES_PER_UNIT["Yard"], "us-ch": OpenLayers.INCHES_PER_UNIT["GunterChain"], "us-mi": OpenLayers.INCHES_PER_UNIT["Mile"], "ind-yd": OpenLayers.INCHES_PER_UNIT["IndianYd37"], "ind-ft": OpenLayers.INCHES_PER_UNIT["IndianFt37"], "ind-ch": 20.11669506 / OpenLayers.METERS_PER_INCH }); OpenLayers.DOTS_PER_INCH = 72; OpenLayers.Util.normalizeScale = function(scale) { var normScale = scale > 1.0 ? 1.0 / scale : scale; return normScale; }; 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; }; 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; }; OpenLayers.Util.pagePosition = function(forElement) { var pos = [0, 0]; var viewportElement = OpenLayers.Util.getViewportElement(); if (!forElement || forElement == window || forElement == viewportElement) { return pos; } 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) { box = forElement.getBoundingClientRect(); var scrollTop = viewportElement.scrollTop; var scrollLeft = viewportElement.scrollLeft; pos[0] = box.left + scrollLeft; pos[1] = box.top + scrollTop; } else if (document.getBoxObjectFor && !BUGGY_GECKO_BOX_OBJECT) { box = document.getBoxObjectFor(forElement); var vpBox = document.getBoxObjectFor(viewportElement); pos[0] = box.screenX - vpBox.screenX; pos[1] = box.screenY - vpBox.screenY; } else { 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; if ( browser == "opera" || (browser == "safari" && OpenLayers.Element.getStyle(forElement, "position") == "absolute") ) { pos[1] -= document.body.offsetTop; } parent = forElement.offsetParent; while (parent && parent != document.body) { pos[0] -= parent.scrollLeft; if (browser != "opera" || parent.tagName != "TR") { pos[1] -= parent.scrollTop; } parent = parent.offsetParent; } } return pos; }; 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; }; OpenLayers.Util.isEquivalentUrl = function(url1, url2, options) { options = options || {}; OpenLayers.Util.applyDefaults(options, { ignoreCase: true, ignorePort80: true, ignoreHash: true }); var urlObj1 = OpenLayers.Util.createUrlObject(url1, options); var urlObj2 = OpenLayers.Util.createUrlObject(url2, options); for (var key in urlObj1) { if (key !== "args") { if (urlObj1[key] != urlObj2[key]) { return false; } } } for (var key in urlObj1.args) { if (urlObj1.args[key] != urlObj2.args[key]) { return false; } delete urlObj2.args[key]; } for (var key in urlObj2.args) { return false; } return true; }; OpenLayers.Util.createUrlObject = function(url, options) { options = options || {}; 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) { url = fullUrl + url; } else { 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 = {}; urlObject.host = a.host.split(":").shift(); urlObject.protocol = a.protocol; if (options.ignorePort80) { urlObject.port = a.port == "80" || a.port == "0" ? "" : a.port; } else { urlObject.port = a.port == "" || a.port == "0" ? "80" : a.port; } urlObject.hash = options.ignoreHash || a.hash === "#" ? "" : a.hash; var queryString = a.search; if (!queryString) { var qMark = url.indexOf("?"); queryString = qMark != -1 ? url.substr(qMark) : ""; } urlObject.args = OpenLayers.Util.getParameters(queryString); urlObject.pathname = a.pathname.charAt(0) == "/" ? a.pathname : "/" + a.pathname; return urlObject; }; 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; }; OpenLayers.IS_GECKO = (function() { var ua = navigator.userAgent.toLowerCase(); return ua.indexOf("webkit") == -1 && ua.indexOf("gecko") != -1; })(); OpenLayers.CANVAS_SUPPORTED = (function() { var elem = document.createElement("canvas"); return !!(elem.getContext && elem.getContext("2d")); })(); 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; })(); OpenLayers.Util.getBrowserName = function() { return OpenLayers.BROWSER_NAME; }; OpenLayers.Util.getRenderedDimensions = function(contentHTML, size, options) { var w, h; var container = document.createElement("div"); container.style.visibility = "hidden"; var containerElement = options && options.containerElement ? options.containerElement : document.body; 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"; 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"; } } if (options && options.displayClass) { container.className = options.displayClass; } var content = document.createElement("div"); content.innerHTML = contentHTML; content.style.overflow = "visible"; if (content.childNodes) { for (var i = 0, l = content.childNodes.length; i < l; i++) { if (!content.childNodes[i].style) continue; content.childNodes[i].style.overflow = "visible"; } } container.appendChild(content); if (superContainer) { containerElement.appendChild(superContainer); } else { containerElement.appendChild(container); } if (!w) { w = parseInt(content.scrollWidth); container.style.width = w + "px"; } if (!h) { h = parseInt(content.scrollHeight); } container.removeChild(content); if (superContainer) { superContainer.removeChild(container); containerElement.removeChild(superContainer); } else { containerElement.removeChild(container); } return new OpenLayers.Size(w, h); }; OpenLayers.Util.getScrollbarWidth = function() { var scrollbarWidth = OpenLayers.Util._scrollbarWidth; if (scrollbarWidth == null) { var scr = null; var inn = null; var wNoScroll = 0; var wScroll = 0; scr = document.createElement("div"); scr.style.position = "absolute"; scr.style.top = "-1000px"; scr.style.left = "-1000px"; scr.style.width = "100px"; scr.style.height = "50px"; scr.style.overflow = "hidden"; inn = document.createElement("div"); inn.style.width = "100%"; inn.style.height = "200px"; scr.appendChild(inn); document.body.appendChild(scr); wNoScroll = inn.offsetWidth; scr.style.overflow = "scroll"; wScroll = inn.offsetWidth; document.body.removeChild(document.body.lastChild); OpenLayers.Util._scrollbarWidth = wNoScroll - wScroll; scrollbarWidth = OpenLayers.Util._scrollbarWidth; } return scrollbarWidth; }; OpenLayers.Util.getFormattedLonLat = function(coordinate, axis, dmsOption) { if (!dmsOption) { dmsOption = "dms"; } coordinate = ((coordinate + 540) % 360) - 180; var abscoordinate = Math.abs(coordinate); var coordinatedegrees = Math.floor(abscoordinate); var coordinateminutes = (abscoordinate - coordinatedegrees) / (1 / 60); var tempcoordinateminutes = coordinateminutes; coordinateminutes = Math.floor(coordinateminutes); var coordinateseconds = (tempcoordinateminutes - coordinateminutes) / (1 / 60); coordinateseconds = Math.round(coordinateseconds * 10); coordinateseconds /= 10; if (coordinateseconds >= 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.Event = { observers: false, KEY_SPACE: 32, KEY_BACKSPACE: 8, KEY_TAB: 9, KEY_RETURN: 13, KEY_ESC: 27, KEY_LEFT: 37, KEY_UP: 38, KEY_RIGHT: 39, KEY_DOWN: 40, KEY_DELETE: 46, element: function(event) { return event.target || event.srcElement; }, isSingleTouch: function(event) { return event.touches && event.touches.length == 1; }, isMultiTouch: function(event) { return event.touches && event.touches.length > 1; }, isLeftClick: function(event) { return ( (event.which && event.which == 1) || (event.button && event.button == 1) ); }, isRightClick: function(event) { return ( (event.which && event.which == 3) || (event.button && event.button == 2) ); }, stop: function(event, allowDefault) { if (!allowDefault) { if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } } if (event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } }, 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; }, 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 (!this.observers) { this.observers = {}; } if (!element._eventCacheID) { var idPrefix = "eventCacheID_"; if (element.id) { idPrefix = element.id + "_" + idPrefix; } element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix); } var cacheID = element._eventCacheID; if (!this.observers[cacheID]) { this.observers[cacheID] = []; } this.observers[cacheID].push({ element: element, name: name, observer: observer, useCapture: useCapture }); if (element.addEventListener) { element.addEventListener(name, observer, useCapture); } else if (element.attachEvent) { element.attachEvent("on" + name, observer); } }, stopObservingElement: function(elementParam) { var element = OpenLayers.Util.getElement(elementParam); var cacheID = element._eventCacheID; this._removeElementObservers(OpenLayers.Event.observers[cacheID]); }, _removeElementObservers: function(elementObservers) { if (elementObservers) { for (var i = elementObservers.length - 1; i >= 0; i--) { var entry = elementObservers[i]; var args = new Array( entry.element, entry.name, entry.observer, entry.useCapture ); var removed = OpenLayers.Event.stopObserving.apply(this, args); } } }, 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"; } } var foundEntry = false; var elementObservers = OpenLayers.Event.observers[cacheID]; if (elementObservers) { 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++; } } if (foundEntry) { if (element.removeEventListener) { element.removeEventListener(name, observer, useCapture); } else if (element && element.detachEvent) { element.detachEvent("on" + name, observer); } } return foundEntry; }, unloadCache: function() { 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" }; OpenLayers.Event.observe(window, "unload", OpenLayers.Event.unloadCache, false); OpenLayers.Events = OpenLayers.Class({ BROWSER_EVENTS: [ "mouseover", "mouseout", "mousedown", "mouseup", "mousemove", "click", "dblclick", "rightclick", "dblrightclick", "resize", "focus", "blur", "touchstart", "touchmove", "touchend", "keydown" ], listeners: null, object: null, element: null, eventHandler: null, fallThrough: null, includeXY: false, extensions: null, extensionCount: null, clearMouseListener: null, initialize: function(object, element, eventTypes, fallThrough, options) { OpenLayers.Util.extend(this, options); this.object = object; this.fallThrough = fallThrough; this.listeners = {}; this.extensions = {}; this.extensionCount = {}; if (element != null) { this.attachToElement(element); } }, 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; }, addEventType: function(eventName) {}, attachToElement: function(element) { if (this.element) { OpenLayers.Event.stopObservingElement(this.element); } else { this.eventHandler = OpenLayers.Function.bindAsEventListener( this.handleBrowserEvent, this ); this.clearMouseListener = OpenLayers.Function.bind( this.clearMouseCache, this ); } this.element = element; for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) { OpenLayers.Event.observe( element, this.BROWSER_EVENTS[i], this.eventHandler ); } OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop); }, on: function(object) { for (var type in object) { if (type != "scope" && object.hasOwnProperty(type)) { this.register(type, object.scope, object[type]); } } }, 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); } } }, registerPriority: function(type, obj, func) { this.register(type, obj, func, true); }, un: function(object) { for (var type in object) { if (type != "scope" && object.hasOwnProperty(type)) { this.unregister(type, object.scope, object[type]); } } }, unregister: function(type, obj, func) { if (obj == null) { obj = this.object; } var listeners = this.listeners[type]; if (listeners != null) { for (var i = 0, len = listeners.length; i < len; i++) { if (listeners[i].obj == obj && listeners[i].func == func) { listeners.splice(i, 1); break; } } } }, remove: function(type) { if (this.listeners[type] != null) { this.listeners[type] = []; } }, triggerEvent: function(type, evt) { var listeners = this.listeners[type]; if (!listeners || listeners.length == 0) { return undefined; } if (evt == null) { evt = {}; } evt.object = this.object; evt.element = this.element; if (!evt.type) { evt.type = type; } listeners = listeners.slice(); var continueChain; for (var i = 0, len = listeners.length; i < len; i++) { var callback = listeners[i]; continueChain = callback.func.apply(callback.obj, [evt]); if (continueChain != undefined && continueChain == false) { break; } } if (!this.fallThrough) { OpenLayers.Event.stop(evt, true); } return continueChain; }, handleBrowserEvent: function(evt) { var type = evt.type, listeners = this.listeners[type]; if (!listeners || listeners.length == 0) { return; } var touches = evt.touches; if (touches && touches[0]) { var x = 0; var y = 0; var num = touches.length; var touch; for (var i = 0; i < num; ++i) { touch = touches[i]; x += touch.clientX; y += touch.clientY; } evt.clientX = x / num; evt.clientY = y / num; } if (this.includeXY) { evt.xy = this.getMousePosition(evt); } this.triggerEvent(type, evt); }, clearMouseCache: function() { this.element.scrolls = null; this.element.lefttop = null; var body = document.body; if ( body && !( (body.scrollTop != 0 || body.scrollLeft != 0) && navigator.userAgent.match(/iPhone/i) ) ) { this.element.offsets = null; } }, 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 = [ viewportElement.scrollLeft, 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] ); }, CLASS_NAME: "OpenLayers.Events" }); OpenLayers.Events.buttonclick = OpenLayers.Class({ target: null, events: [ "mousedown", "mouseup", "click", "dblclick", "touchstart", "touchmove", "touchend", "keydown" ], startRegEx: /^mousedown|touchstart$/, cancelRegEx: /^touchmove$/, completeRegEx: /^mouseup|touchend$/, 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 }); } }, destroy: function() { for (var i = this.events.length - 1; i >= 0; --i) { this.target.unregister(this.events[i], this, this.buttonClick); } delete this.target; }, getPressedButton: function(element) { var depth = 3, button; do { if (OpenLayers.Element.hasClass(element, "olButton")) { button = element; break; } element = element.parentNode; } while (--depth > 0 && element); return button; }, buttonClick: function(evt) { var propagate = true, element = OpenLayers.Event.element(evt); if ( element && (OpenLayers.Event.isLeftClick(evt) || !~evt.type.indexOf("mouse")) ) { 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); 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 { delete this.startEvt; } } return propagate; } }); OpenLayers.Animation = (function(window) { var isNative = !!( window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ); var requestFrame = (function() { var request = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback, element) { window.setTimeout(callback, 16); }; return function(callback, element) { request.apply(window, [callback, element]); }; })(); var counter = 0; var loops = {}; 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(id) { delete loops[id]; } return { isNative: isNative, requestFrame: requestFrame, start: start, stop: stop }; })(window); OpenLayers.Tween = OpenLayers.Class({ easing: null, begin: null, finish: null, duration: null, callbacks: null, time: null, animationId: null, playing: false, initialize: function(easing) { this.easing = easing ? easing : OpenLayers.Easing.Expo.easeOut; }, start: function(begin, finish, duration, options) { this.playing = true; this.begin = begin; this.finish = finish; this.duration = duration; this.callbacks = options.callbacks; this.time = 0; 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) ); }, 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; }, 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) { this.callbacks.eachStep.call(this, value); } if (this.time > this.duration) { this.stop(); } }, CLASS_NAME: "OpenLayers.Tween" }); OpenLayers.Easing = { CLASS_NAME: "OpenLayers.Easing" }; OpenLayers.Easing.Linear = { easeIn: function(t, b, c, d) { return (c * t) / d + b; }, easeOut: function(t, b, c, d) { return (c * t) / d + b; }, easeInOut: function(t, b, c, d) { return (c * t) / d + b; }, CLASS_NAME: "OpenLayers.Easing.Linear" }; OpenLayers.Easing.Expo = { easeIn: function(t, b, c, d) { return t == 0 ? b : c * Math.pow(2, 10 * (t / d - 1)) + b; }, easeOut: function(t, b, c, d) { return t == d ? b + c : c * (-Math.pow(2, (-10 * t) / d) + 1) + b; }, 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" }; OpenLayers.Easing.Quad = { easeIn: function(t, b, c, d) { return c * (t /= d) * t + b; }, easeOut: function(t, b, c, d) { return -c * (t /= d) * (t - 2) + b; }, 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 = OpenLayers.Class({ proj: null, projCode: null, titleRegEx: /\+title=[^\+]*/, initialize: function(projCode, options) { OpenLayers.Util.extend(this, options); this.projCode = projCode; if (window.Proj4js) { this.proj = new Proj4js.Proj(projCode); } }, getCode: function() { return this.proj ? this.proj.srsCode : this.projCode; }, getUnits: function() { return this.proj ? this.proj.units : null; }, toString: function() { return this.getCode(); }, equals: function(projection) { var p = projection, equals = false; if (p) { if (!(p instanceof OpenLayers.Projection)) { p = new OpenLayers.Projection(p); } if (window.Proj4js && 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; }, destroy: function() { delete this.proj; delete this.projCode; }, CLASS_NAME: "OpenLayers.Projection" }); OpenLayers.Projection.transforms = {}; 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] } }; 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; }; 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; }; OpenLayers.Projection.nullTransform = function(point) { return point; }; (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; xy.y = (Math.log(Math.tan(((90 + xy.y) * Math.PI) / 360)) / Math.PI) * pole; return xy; } function map(base, codes) { var add = OpenLayers.Projection.addTransform; var same = OpenLayers.Projection.nullTransform; var i, len, code, other, j; for (i = 0, len = codes.length; i < len; ++i) { code = codes[i]; add(base, code, forwardMercator); add(code, base, inverseMercator); for (j = i + 1; j < len; ++j) { other = codes[j]; add(code, other, same); add(other, code, same); } } } var mercator = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"], geographic = ["CRS:84", "urn:ogc:def:crs:EPSG:6.6:4326", "EPSG:4326"], i; for (i = mercator.length - 1; i >= 0; --i) { map(mercator[i], geographic); } for (i = geographic.length - 1; i >= 0; --i) { map(geographic[i], mercator); } })(); OpenLayers.Map = OpenLayers.Class({ Z_INDEX_BASE: { BaseLayer: 100, Overlay: 325, Feature: 725, Popup: 750, Control: 1000 }, id: null, fractionalZoom: false, events: null, allOverlays: false, div: null, dragging: false, size: null, viewPortDiv: null, layerContainerOrigin: null, layerContainerDiv: null, layers: null, controls: null, popups: null, baseLayer: null, center: null, resolution: null, zoom: 0, panRatio: 1.5, options: null, tileSize: null, projection: "EPSG:4326", units: null, resolutions: null, maxResolution: null, minResolution: null, maxScale: null, minScale: null, maxExtent: null, minExtent: null, restrictedExtent: null, numZoomLevels: 16, theme: null, displayProjection: null, fallThrough: true, panTween: null, eventListeners: null, panMethod: OpenLayers.Easing.Expo.easeOut, panDuration: 50, paddingForPopups: null, minPx: null, maxPx: null, initialize: function(div, options) { if (arguments.length === 1 && typeof div === "object") { options = div; div = options && options.div; } this.tileSize = new OpenLayers.Size( OpenLayers.Map.TILE_WIDTH, OpenLayers.Map.TILE_HEIGHT ); this.paddingForPopups = new OpenLayers.Bounds(15, 15, 15, 15); this.options = OpenLayers.Util.extend({}, 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] ); 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); } 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"); 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 } ); id = this.id + "_OpenLayers_Container"; this.layerContainerDiv = OpenLayers.Util.createDiv(id); this.layerContainerDiv.style.width = "100px"; this.layerContainerDiv.style.height = "100px"; this.layerContainerDiv.style.zIndex = this.Z_INDEX_BASE["Popup"] - 1; this.viewPortDiv.appendChild(this.layerContainerDiv); this.updateSize(); if (this.eventListeners instanceof Object) { this.events.on(this.eventListeners); } if (parseFloat(navigator.appVersion.split("MSIE")[1]) < 9) { this.events.register("resize", this, this.updateSize); } else { this.updateSizeDestroy = OpenLayers.Function.bind(this.updateSize, this); OpenLayers.Event.observe(window, "resize", this.updateSizeDestroy); } if (this.theme) { var addNode = true; var nodes = document.getElementsByTagName("link"); for (var i = 0, len = nodes.length; i < len; ++i) { if (OpenLayers.Util.isEquivalentUrl(nodes.item(i).href, this.theme)) { addNode = false; break; } } if (addNode) { var cssNode = document.createElement("link"); cssNode.setAttribute("rel", "stylesheet"); cssNode.setAttribute("type", "text/css"); cssNode.setAttribute("href", this.theme); document.getElementsByTagName("head")[0].appendChild(cssNode); } } if (this.controls == null) { this.controls = []; if (OpenLayers.Control != null) { if (OpenLayers.Control.Navigation) { this.controls.push(new OpenLayers.Control.Navigation()); } else if (OpenLayers.Control.TouchNavigation) { this.controls.push(new OpenLayers.Control.TouchNavigation()); } if (OpenLayers.Control.Zoom) { this.controls.push(new OpenLayers.Control.Zoom()); } else if (OpenLayers.Control.PanZoom) { this.controls.push(new OpenLayers.Control.PanZoom()); } if (OpenLayers.Control.ArgParser) { this.controls.push(new OpenLayers.Control.ArgParser()); } if (OpenLayers.Control.Attribution) { this.controls.push(new OpenLayers.Control.Attribution()); } } } for (var i = 0, len = this.controls.length; i < len; i++) { this.addControlToMap(this.controls[i]); } this.popups = []; this.unloadDestroy = OpenLayers.Function.bind(this.destroy, this); OpenLayers.Event.observe(window, "unload", this.unloadDestroy); if (options && options.layers) { delete this.center; this.addLayers(options.layers); if (options.center && !this.getCenter()) { this.setCenter(options.center, options.zoom); } } }, getViewport: function() { return this.viewPortDiv; }, render: function(div) { this.div = OpenLayers.Util.getElement(div); OpenLayers.Element.addClass(this.div, "olMap"); this.viewPortDiv.parentNode.removeChild(this.viewPortDiv); this.div.appendChild(this.viewPortDiv); this.updateSize(); }, unloadDestroy: null, updateSizeDestroy: null, destroy: function() { if (!this.unloadDestroy) { return false; } if (this.panTween) { this.panTween.stop(); this.panTween = null; } OpenLayers.Event.stopObserving(window, "unload", this.unloadDestroy); this.unloadDestroy = null; if (this.updateSizeDestroy) { OpenLayers.Event.stopObserving(window, "resize", this.updateSizeDestroy); } else { this.events.unregister("resize", this, this.updateSize); } this.paddingForPopups = null; if (this.controls != null) { for (var i = this.controls.length - 1; i >= 0; --i) { this.controls[i].destroy(); } this.controls = null; } if (this.layers != null) { for (var i = this.layers.length - 1; i >= 0; --i) { this.layers[i].destroy(false); } this.layers = null; } if (this.viewPortDiv) { this.div.removeChild(this.viewPortDiv); } this.viewPortDiv = null; if (this.eventListeners) { this.events.un(this.eventListeners); this.eventListeners = null; } this.events.destroy(); this.events = null; this.options = null; }, setOptions: function(options) { var updatePxExtent = this.minPx && options.restrictedExtent != this.restrictedExtent; OpenLayers.Util.extend(this, options); updatePxExtent && this.moveTo(this.getCachedCenter(), this.zoom, { forceZoomChange: true }); }, getTileSize: function() { return this.tileSize; }, 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; }, getLayersBy: function(property, match) { return this.getBy("layers", property, match); }, getLayersByName: function(match) { return this.getLayersBy("name", match); }, getLayersByClass: function(match) { return this.getLayersBy("CLASS_NAME", match); }, getControlsBy: function(property, match) { return this.getBy("controls", property, match); }, getControlsByClass: function(match) { return this.getControlsBy("CLASS_NAME", match); }, getLayer: function(id) { var foundLayer = null; for (var i = 0, len = this.layers.length; i < len; i++) { var layer = this.layers[i]; if (layer.id == id) { foundLayer = layer; break; } } return foundLayer; }, setLayerZIndex: function(layer, zIdx) { layer.setZIndex( this.Z_INDEX_BASE[layer.isBaseLayer ? "BaseLayer" : "Overlay"] + zIdx * 5 ); }, resetLayersZIndex: function() { for (var i = 0, len = this.layers.length; i < len; i++) { var layer = this.layers[i]; this.setLayerZIndex(layer, i); } }, 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) { 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; }, addLayers: function(layers) { for (var i = 0, len = layers.length; i < len; i++) { this.addLayer(layers[i]); } }, 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 (this.baseLayer == layer) { this.baseLayer = null; if (setNewBaseLayer) { for (var i = 0, len = this.layers.length; i < len; i++) { var iLayer = this.layers[i]; if (iLayer.isBaseLayer || this.allOverlays) { this.setBaseLayer(iLayer); break; } } } } this.resetLayersZIndex(); this.events.triggerEvent("removelayer", { layer: layer }); layer.events.triggerEvent("removed", { map: this, layer: layer }); }, getNumLayers: function() { return this.layers.length; }, getLayerIndex: function(layer) { return OpenLayers.Util.indexOf(this.layers, layer); }, 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 < len; i++) { this.setLayerZIndex(this.layers[i], i); } this.events.triggerEvent("changelayer", { layer: layer, property: "order" }); if (this.allOverlays) { if (idx === 0) { this.setBaseLayer(layer); } else if (this.baseLayer !== this.layers[0]) { this.setBaseLayer(this.layers[0]); } } } }, raiseLayer: function(layer, delta) { var idx = this.getLayerIndex(layer) + delta; this.setLayerIndex(layer, idx); }, setBaseLayer: function(newBaseLayer) { if (newBaseLayer != this.baseLayer) { if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) { var center = this.getCachedCenter(); var newResolution = OpenLayers.Util.getResolutionFromScale( this.getScale(), newBaseLayer.units ); if (this.baseLayer != null && !this.allOverlays) { this.baseLayer.setVisibility(false); } this.baseLayer = newBaseLayer; if (!this.allOverlays || this.baseLayer.visibility) { this.baseLayer.setVisibility(true); if (this.baseLayer.inRange === false) { this.baseLayer.redraw(); } } if (center != null) { var newZoom = this.getZoomForResolution( newResolution || this.resolution, true ); this.setCenter(center, newZoom, false, true); } this.events.triggerEvent("changebaselayer", { layer: this.baseLayer }); } } }, addControl: function(control, px) { this.controls.push(control); this.addControlToMap(control, px); }, addControls: function(controls, pixels) { var pxs = arguments.length === 1 ? [] : pixels; for (var i = 0, len = controls.length; i < len; i++) { var ctrl = controls[i]; var px = pxs[i] ? pxs[i] : null; this.addControl(ctrl, px); } }, addControlToMap: function(control, px) { control.outsideViewport = control.div != null; 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(); } }, getControl: function(id) { var returnControl = null; for (var i = 0, len = this.controls.length; i < len; i++) { var control = this.controls[i]; if (control.id == id) { returnControl = control; break; } } return returnControl; }, removeControl: function(control) { 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); } }, addPopup: function(popup, exclusive) { if (exclusive) { 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); } }, removePopup: function(popup) { OpenLayers.Util.removeItem(this.popups, popup); if (popup.div) { try { this.layerContainerDiv.removeChild(popup.div); } catch (e) {} } popup.map = null; }, getSize: function() { var size = null; if (this.size != null) { size = this.size.clone(); } return size; }, updateSize: function() { 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)) { this.size = newSize; for (var i = 0, len = this.layers.length; i < len; i++) { this.layers[i].onMapResize(); } var center = this.getCachedCenter(); if (this.baseLayer != null && center != null) { var zoom = this.getZoom(); this.zoom = null; this.setCenter(center, zoom); } } } }, 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; }, 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; }, getCenter: function() { var center = null; var cachedCenter = this.getCachedCenter(); if (cachedCenter) { center = cachedCenter.clone(); } return center; }, getCachedCenter: function() { if (!this.center && this.size) { this.center = this.getLonLatFromViewPortPx({ x: this.size.w / 2, y: this.size.h / 2 }); } return this.center; }, getZoom: function() { return this.zoom; }, 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 { var centerPx = this.getViewPortPxFromLonLat(this.getCachedCenter()); 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"); } } } } }, panTo: function(lonlat) { if ( this.panMethod && this.getExtent() .scale(this.panRatio) .containsLonLat(lonlat) ) { if (!this.panTween) { this.panTween = new OpenLayers.Tween(this.panMethod); } var center = this.getCachedCenter(); 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); } }, setCenter: function(lonlat, zoom, dragging, forceZoomChange) { this.panTween && this.panTween.stop(); this.moveTo(lonlat, zoom, { dragging: dragging, forceZoomChange: forceZoomChange }); }, 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; 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.layerContainerDiv.style.left = parseInt(this.layerContainerDiv.style.left) - dx + "px"; this.minPx.x -= dx; this.maxPx.x -= dx; } if (dy) { this.layerContainerDiv.style.top = parseInt(this.layerContainerDiv.style.top) - dy + "px"; this.minPx.y -= dy; this.maxPx.y -= dy; } var layer, i, len; for (i = 0, len = this.layers.length; i < len; ++i) { layer = this.layers[i]; if (layer.visibility && (layer === this.baseLayer || layer.inRange)) { layer.moveByPx(dx, dy); layer.events.triggerEvent("move"); } } this.events.triggerEvent("move"); } }, adjustZoom: function(zoom) { var resolution, resolutions = this.baseLayer.resolutions, maxResolution = this.getMaxExtent().getWidth() / this.size.w; if (this.getResolutionForZoom(zoom) > maxResolution) { for (var i = zoom | 0, ii = resolutions.length; i < ii; ++i) { if (resolutions[i] <= maxResolution) { zoom = i; break; } } } return zoom; }, 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); } } if (this.baseLayer.wrapDateLine) { var requestedZoom = zoom; zoom = this.adjustZoom(zoom); if (zoom !== requestedZoom) { lonlat = this.getCenter(); } } var dragging = options.dragging || this.dragging; var forceZoomChange = options.forceZoomChange; if (!this.getCachedCenter() && !this.isValidLonLat(lonlat)) { lonlat = this.maxExtent.getCenterLonLat(); this.center = lonlat.clone(); } if (this.restrictedExtent != null) { 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 (zoomChanged || centerChanged || dragging) { dragging || this.events.triggerEvent("movestart"); if (centerChanged) { if (!zoomChanged && this.center) { this.centerLayerContainer(lonlat); } this.center = lonlat.clone(); } var res = zoomChanged ? this.getResolutionForZoom(zoom) : this.getResolution(); if (zoomChanged || this.layerContainerOrigin == null) { this.layerContainerOrigin = this.getCachedCenter(); this.layerContainerDiv.style.left = "0px"; this.layerContainerDiv.style.top = "0px"; 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(); 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) { 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) { for (var i = 0, len = this.popups.length; i < len; i++) { this.popups[i].updatePosition(); } this.events.triggerEvent("zoomend"); } } }, centerLayerContainer: function(lonlat) { var originPx = this.getViewPortPxFromLonLat(this.layerContainerOrigin); var newPx = this.getViewPortPxFromLonLat(lonlat); if (originPx != null && newPx != null) { var oldLeft = parseInt(this.layerContainerDiv.style.left); var oldTop = parseInt(this.layerContainerDiv.style.top); var newLeft = Math.round(originPx.x - newPx.x); var newTop = Math.round(originPx.y - newPx.y); this.layerContainerDiv.style.left = newLeft + "px"; this.layerContainerDiv.style.top = newTop + "px"; var dx = oldLeft - newLeft; var dy = oldTop - newTop; this.minPx.x -= dx; this.maxPx.x -= dx; this.minPx.y -= dy; this.maxPx.y -= dy; } }, isValidZoomLevel: function(zoomLevel) { return ( zoomLevel != null && zoomLevel >= 0 && zoomLevel < this.getNumZoomLevels() ); }, 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; }, getProjection: function() { var projection = this.getProjectionObject(); return projection ? projection.getCode() : null; }, getProjectionObject: function() { var projection = null; if (this.baseLayer != null) { projection = this.baseLayer.projection; } return projection; }, getMaxResolution: function() { var maxResolution = null; if (this.baseLayer != null) { maxResolution = this.baseLayer.maxResolution; } return maxResolution; }, 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; }, getNumZoomLevels: function() { var numZoomLevels = null; if (this.baseLayer != null) { numZoomLevels = this.baseLayer.numZoomLevels; } return numZoomLevels; }, getExtent: function() { var extent = null; if (this.baseLayer != null) { extent = this.baseLayer.getExtent(); } return extent; }, getResolution: function() { var resolution = null; if (this.baseLayer != null) { resolution = this.baseLayer.getResolution(); } else if (this.allOverlays === true && this.layers.length > 0) { resolution = this.layers[0].getResolution(); } return resolution; }, getUnits: function() { var units = null; if (this.baseLayer != null) { units = this.baseLayer.units; } return units; }, 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; }, getZoomForExtent: function(bounds, closest) { var zoom = null; if (this.baseLayer != null) { zoom = this.baseLayer.getZoomForExtent(bounds, closest); } return zoom; }, getResolutionForZoom: function(zoom) { var resolution = null; if (this.baseLayer) { resolution = this.baseLayer.getResolutionForZoom(zoom); } return resolution; }, getZoomForResolution: function(resolution, closest) { var zoom = null; if (this.baseLayer != null) { zoom = this.baseLayer.getZoomForResolution(resolution, closest); } return zoom; }, zoomTo: function(zoom) { if (this.isValidZoomLevel(zoom)) { this.setCenter(null, zoom); } }, zoomIn: function() { this.zoomTo(this.getZoom() + 1); }, zoomOut: function() { this.zoomTo(this.getZoom() - 1); }, 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(); bounds = bounds.clone(); while (bounds.right < bounds.left) { bounds.right += maxExtent.getWidth(); } center = bounds.getCenterLonLat().wrapDateLine(maxExtent); } this.setCenter(center, this.getZoomForExtent(bounds, closest)); }, zoomToMaxExtent: function(options) { var restricted = options ? options.restricted : true; var maxExtent = this.getMaxExtent({ restricted: restricted }); this.zoomToExtent(maxExtent); }, 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); }, getLonLatFromViewPortPx: function(viewPortPx) { var lonlat = null; if (this.baseLayer != null) { lonlat = this.baseLayer.getLonLatFromViewPortPx(viewPortPx); } return lonlat; }, getViewPortPxFromLonLat: function(lonlat) { var px = null; if (this.baseLayer != null) { px = this.baseLayer.getViewPortPxFromLonLat(lonlat); } return px; }, getLonLatFromPixel: function(px) { return this.getLonLatFromViewPortPx(px); }, getPixelFromLonLat: function(lonlat) { var px = this.getViewPortPxFromLonLat(lonlat); px.x = Math.round(px.x); px.y = Math.round(px.y); return px; }, 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) ); }, getViewPortPxFromLayerPx: function(layerPx) { var viewPortPx = null; if (layerPx != null) { var dX = parseInt(this.layerContainerDiv.style.left); var dY = parseInt(this.layerContainerDiv.style.top); viewPortPx = layerPx.add(dX, dY); } return viewPortPx; }, getLayerPxFromViewPortPx: function(viewPortPx) { var layerPx = null; if (viewPortPx != null) { var dX = -parseInt(this.layerContainerDiv.style.left); var dY = -parseInt(this.layerContainerDiv.style.top); layerPx = viewPortPx.add(dX, dY); if (isNaN(layerPx.x) || isNaN(layerPx.y)) { layerPx = null; } } return layerPx; }, getLonLatFromLayerPx: function(px) { px = this.getViewPortPxFromLayerPx(px); return this.getLonLatFromViewPortPx(px); }, getLayerPxFromLonLat: function(lonlat) { var px = this.getPixelFromLonLat(lonlat); return this.getLayerPxFromViewPortPx(px); }, CLASS_NAME: "OpenLayers.Map" }); OpenLayers.Map.TILE_WIDTH = 256; OpenLayers.Map.TILE_HEIGHT = 256; OpenLayers.Layer = OpenLayers.Class({ id: null, name: null, div: null, opacity: 1, alwaysInRange: null, RESOLUTION_PROPERTIES: [ "scales", "resolutions", "maxScale", "minScale", "maxResolution", "minResolution", "numZoomLevels", "maxZoomLevel" ], events: null, map: null, isBaseLayer: false, alpha: false, displayInLayerSwitcher: true, visibility: true, attribution: null, inRange: false, imageSize: null, options: null, eventListeners: null, gutter: 0, projection: null, units: null, scales: null, resolutions: null, maxExtent: null, minExtent: null, maxResolution: null, minResolution: null, numZoomLevels: null, minScale: null, maxScale: null, displayOutsideMaxExtent: false, wrapDateLine: false, metadata: null, initialize: function(name, options) { this.metadata = {}; 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); } } }, 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; }, clone: function(obj) { if (obj == null) { obj = new OpenLayers.Layer(this.name, this.getOptions()); } OpenLayers.Util.applyDefaults(obj, this); obj.map = null; return obj; }, getOptions: function() { var options = {}; for (var o in this.options) { options[o] = this[o]; } return options; }, setName: function(newName) { if (newName != this.name) { this.name = newName; if (this.map != null) { this.map.events.triggerEvent("changelayer", { layer: this, property: "name" }); } } }, addOptions: function(newOptions, reinitialize) { if (this.options == null) { this.options = {}; } if (newOptions) { if (typeof newOptions.projection == "string") { newOptions.projection = new OpenLayers.Projection( newOptions.projection ); } if (newOptions.projection) { OpenLayers.Util.applyDefaults( newOptions, OpenLayers.Projection.defaults[newOptions.projection.getCode()] ); } 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); } } OpenLayers.Util.extend(this.options, newOptions); OpenLayers.Util.extend(this, newOptions); if (this.projection && this.projection.getUnits()) { this.units = this.projection.getUnits(); } if (this.map) { 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) { this.map.setCenter( this.map.getCenter(), this.map.getZoomForResolution(resolution), false, true ); this.map.events.triggerEvent("changebaselayer", { layer: this }); } break; } } } }, onMapResize: function() {}, redraw: function() { var redrawn = false; if (this.map) { this.inRange = this.calculateInRange(); 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; }, moveTo: function(bounds, zoomChanged, dragging) { var display = this.visibility; if (!this.isBaseLayer) { display = display && this.inRange; } this.display(display); }, moveByPx: function(dx, dy) {}, setMap: function(map) { if (this.map == null) { this.map = map; 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); } 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"; } this.setTileSize(); } }, afterAdd: function() {}, removeMap: function(map) {}, getImageSize: function(bounds) { return this.imageSize || this.tileSize; }, setTileSize: function(size) { var tileSize = size ? size : this.tileSize ? this.tileSize : this.map.getTileSize(); this.tileSize = tileSize; if (this.gutter) { this.imageSize = new OpenLayers.Size( tileSize.w + 2 * this.gutter, tileSize.h + 2 * this.gutter ); } }, getVisibility: function() { return this.visibility; }, 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"); } }, display: function(display) { if (display != (this.div.style.display != "none")) { this.div.style.display = display && this.calculateInRange() ? "block" : "none"; } }, 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; }, setIsBaseLayer: function(isBaseLayer) { if (isBaseLayer != this.isBaseLayer) { this.isBaseLayer = isBaseLayer; if (this.map != null) { this.map.events.triggerEvent("changebaselayer", { layer: this }); } } }, initResolutions: function() { var i, len, p; var props = {}, alwaysInRange = true; for (i = 0, len = this.RESOLUTION_PROPERTIES.length; i < len; i++) { p = this.RESOLUTION_PROPERTIES[i]; props[p] = this.options[p]; if (alwaysInRange && this.options[p]) { alwaysInRange = false; } } if (this.alwaysInRange == null) { this.alwaysInRange = alwaysInRange; } if (props.resolutions == null) { props.resolutions = this.resolutionsFromScales(props.scales); } if (props.resolutions == null) { props.resolutions = this.calculateResolutions(props); } if (props.resolutions == null) { for (i = 0, len = this.RESOLUTION_PROPERTIES.length; i < len; i++) { p = this.RESOLUTION_PROPERTIES[i]; props[p] = this.options[p] != null ? this.options[p] : this.map[p]; } if (props.resolutions == null) { props.resolutions = this.resolutionsFromScales(props.scales); } if (props.resolutions == null) { props.resolutions = this.calculateResolutions(props); } } var maxResolution; if (this.options.maxResolution && this.options.maxResolution !== "auto") { maxResolution = this.options.maxResolution; } if (this.options.minScale) { maxResolution = OpenLayers.Util.getResolutionFromScale( this.options.minScale, this.units ); } var minResolution; if (this.options.minResolution && this.options.minResolution !== "auto") { minResolution = this.options.minResolution; } if (this.options.maxScale) { minResolution = OpenLayers.Util.getResolutionFromScale( this.options.maxScale, this.units ); } if (props.resolutions) { props.resolutions.sort(function(a, b) { return b - a; }); if (!maxResolution) { maxResolution = props.resolutions[0]; } if (!minResolution) { var lastIdx = props.resolutions.length - 1; minResolution = props.resolutions[lastIdx]; } } this.resolutions = props.resolutions; if (this.resolutions) { len = this.resolutions.length; this.scales = new Array(len); for (i = 0; i < len; i++) { this.scales[i] = OpenLayers.Util.getScaleFromResolution( this.resolutions[i], this.units ); } this.numZoomLevels = len; } this.minResolution = minResolution; if (minResolution) { this.maxScale = OpenLayers.Util.getScaleFromResolution( minResolution, this.units ); } this.maxResolution = maxResolution; if (maxResolution) { this.minScale = OpenLayers.Util.getScaleFromResolution( maxResolution, this.units ); } }, resolutionsFromScales: function(scales) { if (scales == null) { return; } var resolutions, i, len; len = scales.length; resolutions = new Array(len); for (i = 0; i < len; i++) { resolutions[i] = OpenLayers.Util.getResolutionFromScale( scales[i], this.units ); } return resolutions; }, calculateResolutions: function(props) { var viewSize, wRes, hRes; var maxResolution = props.maxResolution; if (props.minScale != null) { maxResolution = OpenLayers.Util.getResolutionFromScale( props.minScale, this.units ); } else if (maxResolution == "auto" && this.maxExtent != null) { viewSize = this.map.getSize(); wRes = this.maxExtent.getWidth() / viewSize.w; hRes = this.maxExtent.getHeight() / viewSize.h; maxResolution = Math.max(wRes, hRes); } var minResolution = props.minResolution; if (props.maxScale != null) { minResolution = OpenLayers.Util.getResolutionFromScale( props.maxScale, this.units ); } else if (props.minResolution == "auto" && this.minExtent != null) { viewSize = this.map.getSize(); wRes = this.minExtent.getWidth() / viewSize.w; hRes = this.minExtent.getHeight() / viewSize.h; minResolution = Math.max(wRes, hRes); } if ( typeof maxResolution !== "number" && typeof minResolution !== "number" && this.maxExtent != null ) { var tileSize = this.map.getTileSize(); maxResolution = Math.max( this.maxExtent.getWidth() / tileSize.w, this.maxExtent.getHeight() / tileSize.h ); } var maxZoomLevel = props.maxZoomLevel; var numZoomLevels = props.numZoomLevels; if ( typeof minResolution === "number" && typeof maxResolution === "number" && numZoomLevels === undefined ) { var ratio = maxResolution / minResolution; numZoomLevels = Math.floor(Math.log(ratio) / Math.log(2)) + 1; } else if (numZoomLevels === undefined && maxZoomLevel != null) { numZoomLevels = maxZoomLevel + 1; } if ( typeof numZoomLevels !== "number" || numZoomLevels <= 0 || (typeof maxResolution !== "number" && typeof minResolution !== "number") ) { return; } var resolutions = new Array(numZoomLevels); var base = 2; if (typeof minResolution == "number" && typeof maxResolution == "number") { base = Math.pow(maxResolution / minResolution, 1 / (numZoomLevels - 1)); } var i; if (typeof maxResolution === "number") { for (i = 0; i < numZoomLevels; i++) { resolutions[i] = maxResolution / Math.pow(base, i); } } else { for (i = 0; i < numZoomLevels; i++) { resolutions[numZoomLevels - 1 - i] = minResolution * Math.pow(base, i); } } return resolutions; }, getResolution: function() { var zoom = this.map.getZoom(); return this.getResolutionForZoom(zoom); }, getExtent: function() { return this.map.calculateBounds(); }, 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); }, getDataExtent: function() {}, 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; }, 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 < len; ++i) { res = this.resolutions[i]; if (res >= 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 < len; i++) { if (closest) { diff = Math.abs(this.resolutions[i] - resolution); if (diff > minDiff) { break; } minDiff = diff; } else { if (this.resolutions[i] < resolution) { break; } } } zoom = Math.max(0, i - 1); } return zoom; }, 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; }, 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; }, 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; 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" }); } } }, getZIndex: function() { return this.div.style.zIndex; }, setZIndex: function(zIndex) { this.div.style.zIndex = zIndex; }, adjustBounds: function(bounds) { if (this.gutter) { 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) { var wrappingOptions = { rightTolerance: this.getResolution(), leftTolerance: this.getResolution() }; bounds = bounds.wrapDateLine(this.maxExtent, wrappingOptions); } return bounds; }, CLASS_NAME: "OpenLayers.Layer" }); OpenLayers.Layer.SphericalMercator = { getExtent: function() { var extent = null; if (this.sphericalMercator) { extent = this.map.calculateBounds(); } else { extent = OpenLayers.Layer.FixedZoomLevels.prototype.getExtent.apply(this); } return extent; }, getLonLatFromViewPortPx: function(viewPortPx) { return OpenLayers.Layer.prototype.getLonLatFromViewPortPx.apply( this, arguments ); }, getViewPortPxFromLonLat: function(lonlat) { return OpenLayers.Layer.prototype.getViewPortPxFromLonLat.apply( this, arguments ); }, initMercatorParameters: function() { this.RESOLUTIONS = []; var maxResolution = 156543.03390625; for (var zoom = 0; zoom <= this.MAX_ZOOM_LEVEL; ++zoom) { this.RESOLUTIONS[zoom] = maxResolution / Math.pow(2, zoom); } this.units = "m"; this.projection = this.projection || "EPSG:900913"; }, forwardMercator: (function() { var gg = new OpenLayers.Projection("EPSG:4326"); var sm = new OpenLayers.Projection("EPSG:900913"); return function(lon, lat) { var point = OpenLayers.Projection.transform({ x: lon, y: lat }, gg, sm); return new OpenLayers.LonLat(point.x, point.y); }; })(), inverseMercator: (function() { var gg = new OpenLayers.Projection("EPSG:4326"); var sm = new OpenLayers.Projection("EPSG:900913"); return function(x, y) { var point = OpenLayers.Projection.transform({ x: x, y: y }, sm, gg); return new OpenLayers.LonLat(point.x, point.y); }; })() }; OpenLayers.Layer.EventPane = OpenLayers.Class(OpenLayers.Layer, { smoothDragPan: true, isBaseLayer: true, isFixed: true, pane: null, mapObject: null, initialize: function(name, options) { OpenLayers.Layer.prototype.initialize.apply(this, arguments); if (this.pane == null) { this.pane = OpenLayers.Util.createDiv(this.div.id + "_EventPane"); } }, destroy: function() { this.mapObject = null; this.pane = null; OpenLayers.Layer.prototype.destroy.apply(this, arguments); }, setMap: function(map) { OpenLayers.Layer.prototype.setMap.apply(this, arguments); this.pane.style.zIndex = parseInt(this.div.style.zIndex) + 1; this.pane.style.display = this.div.style.display; this.pane.style.width = "100%"; this.pane.style.height = "100%"; if (OpenLayers.BROWSER_NAME == "msie") { this.pane.style.background = "url(" + OpenLayers.Util.getImageLocation("blank.gif") + ")"; } if (this.isFixed) { this.map.viewPortDiv.appendChild(this.pane); } else { this.map.layerContainerDiv.appendChild(this.pane); } this.loadMapObject(); if (this.mapObject == null) { this.loadWarningMessage(); } }, removeMap: function(map) { if (this.pane && this.pane.parentNode) { this.pane.parentNode.removeChild(this.pane); } OpenLayers.Layer.prototype.removeMap.apply(this, arguments); }, loadWarningMessage: function() { this.div.style.backgroundColor = "darkblue"; var viewSize = this.map.getSize(); var msgW = Math.min(viewSize.w, 300); var msgH = Math.min(viewSize.h, 200); var size = new OpenLayers.Size(msgW, msgH); var centerPx = new OpenLayers.Pixel(viewSize.w / 2, viewSize.h / 2); var topLeft = centerPx.add(-size.w / 2, -size.h / 2); var div = OpenLayers.Util.createDiv( this.name + "_warning", topLeft, size, null, null, null, "auto" ); div.style.padding = "7px"; div.style.backgroundColor = "yellow"; div.innerHTML = this.getWarningHTML(); this.div.appendChild(div); }, getWarningHTML: function() { return ""; }, display: function(display) { OpenLayers.Layer.prototype.display.apply(this, arguments); this.pane.style.display = this.div.style.display; }, setZIndex: function(zIndex) { OpenLayers.Layer.prototype.setZIndex.apply(this, arguments); this.pane.style.zIndex = parseInt(this.div.style.zIndex) + 1; }, moveByPx: function(dx, dy) { OpenLayers.Layer.prototype.moveByPx.apply(this, arguments); if (this.dragPanMapObject) { this.dragPanMapObject(dx, -dy); } else { this.moveTo(this.map.getCachedCenter()); } }, moveTo: function(bounds, zoomChanged, dragging) { OpenLayers.Layer.prototype.moveTo.apply(this, arguments); if (this.mapObject != null) { var newCenter = this.map.getCenter(); var newZoom = this.map.getZoom(); if (newCenter != null) { var moOldCenter = this.getMapObjectCenter(); var oldCenter = this.getOLLonLatFromMapObjectLonLat(moOldCenter); var moOldZoom = this.getMapObjectZoom(); var oldZoom = this.getOLZoomFromMapObjectZoom(moOldZoom); if (!newCenter.equals(oldCenter) || newZoom != oldZoom) { if ( !zoomChanged && oldCenter && this.dragPanMapObject && this.smoothDragPan ) { var oldPx = this.map.getViewPortPxFromLonLat(oldCenter); var newPx = this.map.getViewPortPxFromLonLat(newCenter); this.dragPanMapObject(newPx.x - oldPx.x, oldPx.y - newPx.y); } else { var center = this.getMapObjectLonLatFromOLLonLat(newCenter); var zoom = this.getMapObjectZoomFromOLZoom(newZoom); this.setMapObjectCenter(center, zoom, dragging); } } } } }, getLonLatFromViewPortPx: function(viewPortPx) { var lonlat = null; if (this.mapObject != null && this.getMapObjectCenter() != null) { var moPixel = this.getMapObjectPixelFromOLPixel(viewPortPx); var moLonLat = this.getMapObjectLonLatFromMapObjectPixel(moPixel); lonlat = this.getOLLonLatFromMapObjectLonLat(moLonLat); } return lonlat; }, getViewPortPxFromLonLat: function(lonlat) { var viewPortPx = null; if (this.mapObject != null && this.getMapObjectCenter() != null) { var moLonLat = this.getMapObjectLonLatFromOLLonLat(lonlat); var moPixel = this.getMapObjectPixelFromMapObjectLonLat(moLonLat); viewPortPx = this.getOLPixelFromMapObjectPixel(moPixel); } return viewPortPx; }, getOLLonLatFromMapObjectLonLat: function(moLonLat) { var olLonLat = null; if (moLonLat != null) { var lon = this.getLongitudeFromMapObjectLonLat(moLonLat); var lat = this.getLatitudeFromMapObjectLonLat(moLonLat); olLonLat = new OpenLayers.LonLat(lon, lat); } return olLonLat; }, getMapObjectLonLatFromOLLonLat: function(olLonLat) { var moLatLng = null; if (olLonLat != null) { moLatLng = this.getMapObjectLonLatFromLonLat(olLonLat.lon, olLonLat.lat); } return moLatLng; }, getOLPixelFromMapObjectPixel: function(moPixel) { var olPixel = null; if (moPixel != null) { var x = this.getXFromMapObjectPixel(moPixel); var y = this.getYFromMapObjectPixel(moPixel); olPixel = new OpenLayers.Pixel(x, y); } return olPixel; }, getMapObjectPixelFromOLPixel: function(olPixel) { var moPixel = null; if (olPixel != null) { moPixel = this.getMapObjectPixelFromXY(olPixel.x, olPixel.y); } return moPixel; }, CLASS_NAME: "OpenLayers.Layer.EventPane" }); OpenLayers.Layer.FixedZoomLevels = OpenLayers.Class({ initialize: function() {}, initResolutions: function() { var props = ["minZoomLevel", "maxZoomLevel", "numZoomLevels"]; for (var i = 0, len = props.length; i < len; i++) { var property = props[i]; this[property] = this.options[property] != null ? this.options[property] : this.map[property]; } if (this.minZoomLevel == null || this.minZoomLevel < this.MIN_ZOOM_LEVEL) { this.minZoomLevel = this.MIN_ZOOM_LEVEL; } var desiredZoomLevels; var limitZoomLevels = this.MAX_ZOOM_LEVEL - this.minZoomLevel + 1; if ( (this.options.numZoomLevels == null && this.options.maxZoomLevel != null) || (this.numZoomLevels == null && this.maxZoomLevel != null) ) { desiredZoomLevels = this.maxZoomLevel - this.minZoomLevel + 1; } else { desiredZoomLevels = this.numZoomLevels; } if (desiredZoomLevels != null) { this.numZoomLevels = Math.min(desiredZoomLevels, limitZoomLevels); } else { this.numZoomLevels = limitZoomLevels; } this.maxZoomLevel = this.minZoomLevel + this.numZoomLevels - 1; if (this.RESOLUTIONS != null) { var resolutionsIndex = 0; this.resolutions = []; for (var i = this.minZoomLevel; i <= this.maxZoomLevel; i++) { this.resolutions[resolutionsIndex++] = this.RESOLUTIONS[i]; } this.maxResolution = this.resolutions[0]; this.minResolution = this.resolutions[this.resolutions.length - 1]; } }, getResolution: function() { if (this.resolutions != null) { return OpenLayers.Layer.prototype.getResolution.apply(this, arguments); } else { var resolution = null; var viewSize = this.map.getSize(); var extent = this.getExtent(); if (viewSize != null && extent != null) { resolution = Math.max( extent.getWidth() / viewSize.w, extent.getHeight() / viewSize.h ); } return resolution; } }, getExtent: function() { var size = this.map.getSize(); var tl = this.getLonLatFromViewPortPx({ x: 0, y: 0 }); var br = this.getLonLatFromViewPortPx({ x: size.w, y: size.h }); if (tl != null && br != null) { return new OpenLayers.Bounds(tl.lon, br.lat, br.lon, tl.lat); } else { return null; } }, getZoomForResolution: function(resolution) { if (this.resolutions != null) { return OpenLayers.Layer.prototype.getZoomForResolution.apply( this, arguments ); } else { var extent = OpenLayers.Layer.prototype.getExtent.apply(this, []); return this.getZoomForExtent(extent); } }, getOLZoomFromMapObjectZoom: function(moZoom) { var zoom = null; if (moZoom != null) { zoom = moZoom - this.minZoomLevel; if (this.map.baseLayer !== this) { zoom = this.map.baseLayer.getZoomForResolution( this.getResolutionForZoom(zoom) ); } } return zoom; }, getMapObjectZoomFromOLZoom: function(olZoom) { var zoom = null; if (olZoom != null) { zoom = olZoom + this.minZoomLevel; if (this.map.baseLayer !== this) { zoom = this.getZoomForResolution( this.map.baseLayer.getResolutionForZoom(zoom) ); } } return zoom; }, CLASS_NAME: "OpenLayers.Layer.FixedZoomLevels" }); OpenLayers.Layer.Google = OpenLayers.Class( OpenLayers.Layer.EventPane, OpenLayers.Layer.FixedZoomLevels, { MIN_ZOOM_LEVEL: 0, MAX_ZOOM_LEVEL: 21, RESOLUTIONS: [ 1.40625, 0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625, 0.010986328125, 0.0054931640625, 0.00274658203125, 0.001373291015625, 0.0006866455078125, 0.00034332275390625, 0.000171661376953125, 0.0000858306884765625, 0.00004291534423828125, 0.00002145767211914062, 0.00001072883605957031, 0.00000536441802978515, 0.00000268220901489257, 0.0000013411045074462891, 0.00000067055225372314453 ], type: null, wrapDateLine: true, sphericalMercator: false, version: null, initialize: function(name, options) { options = options || {}; if (!options.version) { options.version = typeof GMap2 === "function" ? "2" : "3"; } var mixin = OpenLayers.Layer.Google["v" + options.version.replace(/\./g, "_")]; if (mixin) { OpenLayers.Util.applyDefaults(options, mixin); } else { throw "Unsupported Google Maps API version: " + options.version; } OpenLayers.Util.applyDefaults(options, mixin.DEFAULTS); if (options.maxExtent) { options.maxExtent = options.maxExtent.clone(); } OpenLayers.Layer.EventPane.prototype.initialize.apply(this, [ name, options ]); OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this, [ name, options ]); if (this.sphericalMercator) { OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator); this.initMercatorParameters(); } }, clone: function() { return new OpenLayers.Layer.Google(this.name, this.getOptions()); }, setVisibility: function(visible) { var opacity = this.opacity == null ? 1 : this.opacity; OpenLayers.Layer.EventPane.prototype.setVisibility.apply(this, arguments); this.setOpacity(opacity); }, display: function(visible) { if (!this._dragging) { this.setGMapVisibility(visible); } OpenLayers.Layer.EventPane.prototype.display.apply(this, arguments); }, moveTo: function(bounds, zoomChanged, dragging) { this._dragging = dragging; OpenLayers.Layer.EventPane.prototype.moveTo.apply(this, arguments); delete this._dragging; }, setOpacity: function(opacity) { if (opacity !== this.opacity) { if (this.map != null) { this.map.events.triggerEvent("changelayer", { layer: this, property: "opacity" }); } this.opacity = opacity; } if (this.getVisibility()) { var container = this.getMapContainer(); OpenLayers.Util.modifyDOMElement( container, null, null, null, null, null, null, opacity ); } }, destroy: function() { if (this.map) { this.setGMapVisibility(false); var cache = OpenLayers.Layer.Google.cache[this.map.id]; if (cache && cache.count <= 1) { this.removeGMapElements(); } } OpenLayers.Layer.EventPane.prototype.destroy.apply(this, arguments); }, removeGMapElements: function() { var cache = OpenLayers.Layer.Google.cache[this.map.id]; if (cache) { var container = this.mapObject && this.getMapContainer(); if (container && container.parentNode) { container.parentNode.removeChild(container); } var termsOfUse = cache.termsOfUse; if (termsOfUse && termsOfUse.parentNode) { termsOfUse.parentNode.removeChild(termsOfUse); } var poweredBy = cache.poweredBy; if (poweredBy && poweredBy.parentNode) { poweredBy.parentNode.removeChild(poweredBy); } } }, removeMap: function(map) { if (this.visibility && this.mapObject) { this.setGMapVisibility(false); } var cache = OpenLayers.Layer.Google.cache[map.id]; if (cache) { if (cache.count <= 1) { this.removeGMapElements(); delete OpenLayers.Layer.Google.cache[map.id]; } else { --cache.count; } } delete this.termsOfUse; delete this.poweredBy; delete this.mapObject; delete this.dragObject; OpenLayers.Layer.EventPane.prototype.removeMap.apply(this, arguments); }, getOLBoundsFromMapObjectBounds: function(moBounds) { var olBounds = null; if (moBounds != null) { var sw = moBounds.getSouthWest(); var ne = moBounds.getNorthEast(); if (this.sphericalMercator) { sw = this.forwardMercator(sw.lng(), sw.lat()); ne = this.forwardMercator(ne.lng(), ne.lat()); } else { sw = new OpenLayers.LonLat(sw.lng(), sw.lat()); ne = new OpenLayers.LonLat(ne.lng(), ne.lat()); } olBounds = new OpenLayers.Bounds(sw.lon, sw.lat, ne.lon, ne.lat); } return olBounds; }, getWarningHTML: function() { return OpenLayers.i18n("googleWarning"); }, getMapObjectCenter: function() { return this.mapObject.getCenter(); }, getMapObjectZoom: function() { return this.mapObject.getZoom(); }, getLongitudeFromMapObjectLonLat: function(moLonLat) { return this.sphericalMercator ? this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lon : moLonLat.lng(); }, getLatitudeFromMapObjectLonLat: function(moLonLat) { var lat = this.sphericalMercator ? this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lat : moLonLat.lat(); return lat; }, getXFromMapObjectPixel: function(moPixel) { return moPixel.x; }, getYFromMapObjectPixel: function(moPixel) { return moPixel.y; }, CLASS_NAME: "OpenLayers.Layer.Google" } ); OpenLayers.Layer.Google.cache = {}; OpenLayers.Layer.Google.v2 = { termsOfUse: null, poweredBy: null, dragObject: null, loadMapObject: function() { if (!this.type) { this.type = G_NORMAL_MAP; } var mapObject, termsOfUse, poweredBy; var cache = OpenLayers.Layer.Google.cache[this.map.id]; if (cache) { mapObject = cache.mapObject; termsOfUse = cache.termsOfUse; poweredBy = cache.poweredBy; ++cache.count; } else { var container = this.map.viewPortDiv; var div = document.createElement("div"); div.id = this.map.id + "_GMap2Container"; div.style.position = "absolute"; div.style.width = "100%"; div.style.height = "100%"; container.appendChild(div); try { mapObject = new GMap2(div); termsOfUse = div.lastChild; container.appendChild(termsOfUse); termsOfUse.style.zIndex = "1100"; termsOfUse.style.right = ""; termsOfUse.style.bottom = ""; termsOfUse.className = "olLayerGoogleCopyright"; poweredBy = div.lastChild; container.appendChild(poweredBy); poweredBy.style.zIndex = "1100"; poweredBy.style.right = ""; poweredBy.style.bottom = ""; poweredBy.className = "olLayerGooglePoweredBy gmnoprint"; } catch (e) { throw e; } OpenLayers.Layer.Google.cache[this.map.id] = { mapObject: mapObject, termsOfUse: termsOfUse, poweredBy: poweredBy, count: 1 }; } this.mapObject = mapObject; this.termsOfUse = termsOfUse; this.poweredBy = poweredBy; if ( OpenLayers.Util.indexOf(this.mapObject.getMapTypes(), this.type) === -1 ) { this.mapObject.addMapType(this.type); } if (typeof mapObject.getDragObject == "function") { this.dragObject = mapObject.getDragObject(); } else { this.dragPanMapObject = null; } if (this.isBaseLayer === false) { this.setGMapVisibility(this.div.style.display !== "none"); } }, onMapResize: function() { if (this.visibility && this.mapObject.isLoaded()) { this.mapObject.checkResize(); } else { if (!this._resized) { var layer = this; var handle = GEvent.addListener(this.mapObject, "load", function() { GEvent.removeListener(handle); delete layer._resized; layer.mapObject.checkResize(); layer.moveTo(layer.map.getCenter(), layer.map.getZoom()); }); } this._resized = true; } }, setGMapVisibility: function(visible) { var cache = OpenLayers.Layer.Google.cache[this.map.id]; if (cache) { var container = this.mapObject.getContainer(); if (visible === true) { this.mapObject.setMapType(this.type); container.style.display = ""; this.termsOfUse.style.left = ""; this.termsOfUse.style.display = ""; this.poweredBy.style.display = ""; cache.displayed = this.id; } else { if (cache.displayed === this.id) { delete cache.displayed; } if (!cache.displayed) { container.style.display = "none"; this.termsOfUse.style.display = "none"; this.termsOfUse.style.left = "-9999px"; this.poweredBy.style.display = "none"; } } } }, getMapContainer: function() { return this.mapObject.getContainer(); }, getMapObjectBoundsFromOLBounds: function(olBounds) { var moBounds = null; if (olBounds != null) { var sw = this.sphericalMercator ? this.inverseMercator(olBounds.bottom, olBounds.left) : new OpenLayers.LonLat(olBounds.bottom, olBounds.left); var ne = this.sphericalMercator ? this.inverseMercator(olBounds.top, olBounds.right) : new OpenLayers.LonLat(olBounds.top, olBounds.right); moBounds = new GLatLngBounds( new GLatLng(sw.lat, sw.lon), new GLatLng(ne.lat, ne.lon) ); } return moBounds; }, setMapObjectCenter: function(center, zoom) { this.mapObject.setCenter(center, zoom); }, dragPanMapObject: function(dX, dY) { this.dragObject.moveBy(new GSize(-dX, dY)); }, getMapObjectLonLatFromMapObjectPixel: function(moPixel) { return this.mapObject.fromContainerPixelToLatLng(moPixel); }, getMapObjectPixelFromMapObjectLonLat: function(moLonLat) { return this.mapObject.fromLatLngToContainerPixel(moLonLat); }, getMapObjectZoomFromMapObjectBounds: function(moBounds) { return this.mapObject.getBoundsZoomLevel(moBounds); }, getMapObjectLonLatFromLonLat: function(lon, lat) { var gLatLng; if (this.sphericalMercator) { var lonlat = this.inverseMercator(lon, lat); gLatLng = new GLatLng(lonlat.lat, lonlat.lon); } else { gLatLng = new GLatLng(lat, lon); } return gLatLng; }, getMapObjectPixelFromXY: function(x, y) { return new GPoint(x, y); } }; OpenLayers.Geometry = OpenLayers.Class({ id: null, parent: null, bounds: null, initialize: function() { this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); }, destroy: function() { this.id = null; this.bounds = null; }, clone: function() { return new OpenLayers.Geometry(); }, setBounds: function(bounds) { if (bounds) { this.bounds = bounds.clone(); } }, clearBounds: function() { this.bounds = null; if (this.parent) { this.parent.clearBounds(); } }, extendBounds: function(newBounds) { var bounds = this.getBounds(); if (!bounds) { this.setBounds(newBounds); } else { this.bounds.extend(newBounds); } }, getBounds: function() { if (this.bounds == null) { this.calculateBounds(); } return this.bounds; }, calculateBounds: function() {}, distanceTo: function(geometry, options) {}, getVertices: function(nodes) {}, 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; }, getLength: function() { return 0.0; }, getArea: function() { return 0.0; }, getCentroid: function() { return null; }, 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" }); OpenLayers.Geometry.fromWKT = function(wkt) { var geom; if (OpenLayers.Format && OpenLayers.Format.WKT) { var format = OpenLayers.Geometry.fromWKT.format; if (!format) { format = new OpenLayers.Format.WKT(); OpenLayers.Geometry.fromWKT.format = format; } var result = format.read(wkt); if (result instanceof OpenLayers.Feature.Vector) { geom = result.geometry; } else if (OpenLayers.Util.isArray(result)) { var len = result.length; var components = new Array(len); for (var i = 0; i < len; ++i) { components[i] = result[i].geometry; } geom = new OpenLayers.Geometry.Collection(components); } } return geom; }; 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) { if (n1 == 0 && n2 == 0) { intersection = true; } } else { var along1 = n1 / d; var along2 = n2 / d; if (along1 >= 0 && along1 <= 1 && along2 >= 0 && along2 <= 1) { if (!point) { intersection = true; } else { 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; 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 { var segs = [seg1, seg2]; var source, target, x, y, p, result; 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; }; OpenLayers.Geometry.distanceToSegment = 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.sqrt(Math.pow(x - x0, 2) + Math.pow(y - y0, 2)), x: x, y: y }; }; OpenLayers.Geometry.Collection = OpenLayers.Class(OpenLayers.Geometry, { components: null, componentTypes: null, initialize: function(components) { OpenLayers.Geometry.prototype.initialize.apply(this, arguments); this.components = []; if (components != null) { this.addComponents(components); } }, destroy: function() { this.components.length = 0; this.components = null; OpenLayers.Geometry.prototype.destroy.apply(this, arguments); }, clone: function() { var geometry = eval("new " + this.CLASS_NAME + "()"); for (var i = 0, len = this.components.length; i < len; i++) { geometry.addComponent(this.components[i].clone()); } OpenLayers.Util.applyDefaults(geometry, this); return geometry; }, getComponentsString: function() { var strings = []; for (var i = 0, len = this.components.length; i < len; i++) { strings.push(this.components[i].toShortString()); } return strings.join(","); }, calculateBounds: function() { this.bounds = null; var bounds = new OpenLayers.Bounds(); var components = this.components; if (components) { for (var i = 0, len = components.length; i < len; i++) { bounds.extend(components[i].getBounds()); } } if ( bounds.left != null && bounds.bottom != null && bounds.right != null && bounds.top != null ) { this.setBounds(bounds); } }, addComponents: function(components) { if (!OpenLayers.Util.isArray(components)) { components = [components]; } for (var i = 0, len = components.length; i < len; i++) { this.addComponent(components[i]); } }, 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; }, 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; }, removeComponent: function(component) { OpenLayers.Util.removeItem(this.components, component); this.clearBounds(); return true; }, getLength: function() { var length = 0.0; for (var i = 0, len = this.components.length; i < len; i++) { length += this.components[i].getLength(); } return length; }, getArea: function() { var area = 0.0; for (var i = 0, len = this.components.length; i < len; i++) { area += this.components[i].getArea(); } return area; }, getGeodesicArea: function(projection) { var area = 0.0; for (var i = 0, len = this.components.length; i < len; i++) { area += this.components[i].getGeodesicArea(projection); } return area; }, getCentroid: function(weighted) { if (!weighted) { return this.components.length && this.components[0].getCentroid(); } var len = this.components.length; if (!len) { return false; } var areas = []; var centroids = []; var areaSum = 0; var minArea = Number.MAX_VALUE; var component; for (var i = 0; i < len; ++i) { component = this.components[i]; var area = component.getArea(); var centroid = component.getCentroid(true); if (isNaN(area) || isNaN(centroid.x) || isNaN(centroid.y)) { continue; } areas.push(area); areaSum += area; minArea = area < minArea && area > 0 ? area : minArea; centroids.push(centroid); } len = areas.length; if (areaSum === 0) { for (var i = 0; i < len; ++i) { areas[i] = 1; } areaSum = areas.length; } else { for (var i = 0; i < len; ++i) { areas[i] /= minArea; } areaSum /= minArea; } var xSum = 0, ySum = 0, centroid, area; for (var i = 0; i < len; ++i) { centroid = centroids[i]; area = areas[i]; xSum += centroid.x * area; ySum += centroid.y * area; } return new OpenLayers.Geometry.Point(xSum / areaSum, ySum / areaSum); }, getGeodesicLength: function(projection) { var length = 0.0; for (var i = 0, len = this.components.length; i < len; i++) { length += this.components[i].getGeodesicLength(projection); } return length; }, move: function(x, y) { for (var i = 0, len = this.components.length; i < len; i++) { this.components[i].move(x, y); } }, rotate: function(angle, origin) { for (var i = 0, len = this.components.length; i < len; ++i) { this.components[i].rotate(angle, origin); } }, resize: function(scale, origin, ratio) { for (var i = 0; i < this.components.length; ++i) { this.components[i].resize(scale, origin, ratio); } return this; }, distanceTo: function(geometry, options) { var edge = !(options && options.edge === false); var details = edge && options && options.details; var result, best, distance; var min = Number.POSITIVE_INFINITY; for (var i = 0, len = this.components.length; i < len; ++i) { result = this.components[i].distanceTo(geometry, options); distance = details ? result.distance : result; if (distance < min) { min = distance; best = result; if (min == 0) { break; } } } return best; }, equals: function(geometry) { var equivalent = true; if ( !geometry || !geometry.CLASS_NAME || this.CLASS_NAME != geometry.CLASS_NAME ) { equivalent = false; } else if ( !OpenLayers.Util.isArray(geometry.components) || geometry.components.length != this.components.length ) { equivalent = false; } else { for (var i = 0, len = this.components.length; i < len; ++i) { if (!this.components[i].equals(geometry.components[i])) { equivalent = false; break; } } } return equivalent; }, transform: function(source, dest) { if (source && dest) { for (var i = 0, len = this.components.length; i < len; i++) { var component = this.components[i]; component.transform(source, dest); } this.bounds = null; } return this; }, intersects: function(geometry) { var intersect = false; for (var i = 0, len = this.components.length; i < len; ++i) { intersect = geometry.intersects(this.components[i]); if (intersect) { break; } } return intersect; }, getVertices: function(nodes) { var vertices = []; for (var i = 0, len = this.components.length; i < len; ++i) { Array.prototype.push.apply( vertices, this.components[i].getVertices(nodes) ); } return vertices; }, CLASS_NAME: "OpenLayers.Geometry.Collection" }); OpenLayers.Geometry.Point = OpenLayers.Class(OpenLayers.Geometry, { x: null, y: null, initialize: function(x, y) { OpenLayers.Geometry.prototype.initialize.apply(this, arguments); this.x = parseFloat(x); this.y = parseFloat(y); }, clone: function(obj) { if (obj == null) { obj = new OpenLayers.Geometry.Point(this.x, this.y); } OpenLayers.Util.applyDefaults(obj, this); return obj; }, calculateBounds: function() { this.bounds = new OpenLayers.Bounds(this.x, this.y, this.x, this.y); }, 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) { result = { x0: result.x1, y0: result.y1, x1: result.x0, y1: result.y0, distance: result.distance }; } } return result; }, 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; }, toShortString: function() { return this.x + ", " + this.y; }, move: function(x, y) { this.x = this.x + x; this.y = this.y + y; this.clearBounds(); }, 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(); }, getCentroid: function() { return new OpenLayers.Geometry.Point(this.x, this.y); }, 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; }, intersects: function(geometry) { var intersect = false; if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { intersect = this.equals(geometry); } else { intersect = geometry.intersects(this); } return intersect; }, transform: function(source, dest) { if (source && dest) { OpenLayers.Projection.transform(this, source, dest); this.bounds = null; } return this; }, getVertices: function(nodes) { return [this]; }, CLASS_NAME: "OpenLayers.Geometry.Point" }); OpenLayers.Geometry.MultiPoint = OpenLayers.Class( OpenLayers.Geometry.Collection, { componentTypes: ["OpenLayers.Geometry.Point"], addPoint: function(point, index) { this.addComponent(point, index); }, removePoint: function(point) { this.removeComponent(point); }, CLASS_NAME: "OpenLayers.Geometry.MultiPoint" } ); OpenLayers.Geometry.Curve = OpenLayers.Class(OpenLayers.Geometry.MultiPoint, { componentTypes: ["OpenLayers.Geometry.Point"], getLength: function() { var length = 0.0; if (this.components && this.components.length > 1) { for (var i = 1, len = this.components.length; i < len; i++) { length += this.components[i - 1].distanceTo(this.components[i]); } } return length; }, getGeodesicLength: function(projection) { var geom = this; if (projection) { var gg = new OpenLayers.Projection("EPSG:4326"); if (!gg.equals(projection)) { geom = this.clone().transform(projection, gg); } } var length = 0.0; if (geom.components && geom.components.length > 1) { var p1, p2; for (var i = 1, len = geom.components.length; i < len; i++) { p1 = geom.components[i - 1]; p2 = geom.components[i]; length += OpenLayers.Util.distVincenty( { lon: p1.x, lat: p1.y }, { lon: p2.x, lat: p2.y } ); } } return length * 1000; }, CLASS_NAME: "OpenLayers.Geometry.Curve" }); OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, { removeComponent: function(point) { var removed = this.components && this.components.length > 2; if (removed) { OpenLayers.Geometry.Collection.prototype.removeComponent.apply( this, arguments ); } return removed; }, 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; outer: for (var i = 0, len = segs1.length; i < len; ++i) { seg1 = segs1[i]; seg1x1 = seg1.x1; seg1x2 = seg1.x2; seg1y1 = seg1.y1; seg1y2 = seg1.y2; inner: for (var j = 0, jlen = segs2.length; j < jlen; ++j) { seg2 = segs2[j]; if (seg2.x1 > seg1x2) { break; } if (seg2.x2 < seg1x1) { continue; } seg2y1 = seg2.y1; seg2y2 = seg2.y2; if (Math.min(seg2y1, seg2y2) > Math.max(seg1y1, seg1y2)) { continue; } if (Math.max(seg2y1, seg2y2) < Math.min(seg1y1, seg1y2)) { continue; } if (OpenLayers.Geometry.segmentsIntersect(seg1, seg2)) { intersect = true; break outer; } } } } else { intersect = geometry.intersects(this); } return intersect; }, getSortedSegments: function() { var numSeg = this.components.length - 1; var segments = new Array(numSeg), point1, point2; for (var i = 0; i < numSeg; ++i) { point1 = this.components[i]; point2 = this.components[i + 1]; if (point1.x < point2.x) { segments[i] = { x1: point1.x, y1: point1.y, x2: point2.x, y2: point2.y }; } else { segments[i] = { x1: point2.x, y1: point2.y, x2: point1.x, y2: point1.y }; } } function byX1(seg1, seg2) { return seg1.x1 - seg2.x1; } return segments.sort(byX1); }, splitWithSegment: function(seg, options) { var edge = !(options && options.edge === false); var tolerance = options && options.tolerance; var lines = []; var verts = this.getVertices(); var points = []; var intersections = []; var split = false; var vert1, vert2, point; var node, vertex, target; var interOptions = { point: true, tolerance: tolerance }; var result = null; for (var i = 0, stop = verts.length - 2; i <= stop; ++i) { vert1 = verts[i]; points.push(vert1.clone()); vert2 = verts[i + 1]; target = { x1: vert1.x, y1: vert1.y, x2: vert2.x, y2: vert2.y }; point = OpenLayers.Geometry.segmentsIntersect(seg, target, interOptions); if (point instanceof OpenLayers.Geometry.Point) { if ( (point.x === seg.x1 && point.y === seg.y1) || (point.x === seg.x2 && point.y === seg.y2) || point.equals(vert1) || point.equals(vert2) ) { vertex = true; } else { vertex = false; } if (vertex || edge) { if (!point.equals(intersections[intersections.length - 1])) { intersections.push(point.clone()); } if (i === 0) { if (point.equals(vert1)) { continue; } } if (point.equals(vert2)) { continue; } split = true; if (!point.equals(vert1)) { points.push(point); } lines.push(new OpenLayers.Geometry.LineString(points)); points = [point.clone()]; } } } if (split) { points.push(vert2.clone()); lines.push(new OpenLayers.Geometry.LineString(points)); } if (intersections.length > 0) { 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; }, 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 < targetParts.length; ++j) { splits = targetParts[j].splitWithSegment(seg, options); if (splits) { lines = splits.lines; if (lines.length > 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 < len; ++k) { point = splits.points[k]; if (!point.equals(vert1)) { points.push(point); sourceParts.push(new OpenLayers.Geometry.LineString(points)); if (point.equals(vert2)) { points = []; } else { points = [point.clone()]; } } } } } } } if (mutual && sourceParts.length > 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; }, splitWith: function(geometry, options) { return geometry.split(this, options); }, 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; }, 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 < len; ++i) { seg = segs[i]; result = OpenLayers.Geometry.distanceToSegment(geometry, seg); if (result.distance < min) { min = result.distance; best = result; if (min === 0) { break; } } else { if ( seg.x2 > 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 < len; ++i) { seg0 = segs0[i]; x0 = seg0.x1; y0 = seg0.y1; for (var j = 0; j < len1; ++j) { seg1 = segs1[j]; intersection = OpenLayers.Geometry.segmentsIntersect( seg0, seg1, interOptions ); if (intersection) { min = 0; best = { distance: 0, x0: intersection.x, y0: intersection.y, x1: intersection.x, y1: intersection.y }; break outer; } else { result = OpenLayers.Geometry.distanceToSegment( { x: x0, y: y0 }, seg1 ); if (result.distance < min) { min = result.distance; best = { distance: min, x0: x0, y0: y0, x1: result.x, y1: result.y }; } } } } if (!details) { best = best.distance; } if (min !== 0) { if (seg0) { result = geometry.distanceTo( new OpenLayers.Geometry.Point(seg0.x2, seg0.y2), options ); var dist = details ? result.distance : result; if (dist < min) { if (details) { best = { distance: min, x0: result.x1, y0: result.y1, x1: result.x0, y1: result.y0 }; } else { best = dist; } } } } } else { best = geometry.distanceTo(this, options); if (details) { best = { distance: best.distance, x0: best.x1, y0: best.y1, x1: best.x0, y1: best.y0 }; } } return best; }, simplify: function(tolerance) { if (this && this !== null) { var points = this.getVertices(); if (points.length < 3) { return this; } var compareNumbers = function(a, b) { return a - b; }; var douglasPeuckerReduction = function( points, firstPoint, lastPoint, tolerance ) { var maxDistance = 0; var indexFarthest = 0; for (var index = firstPoint, distance; index < lastPoint; index++) { distance = perpendicularDistance( points[firstPoint], points[lastPoint], points[index] ); if (distance > maxDistance) { maxDistance = distance; indexFarthest = index; } } if (maxDistance > tolerance && indexFarthest != firstPoint) { pointIndexsToKeep.push(indexFarthest); douglasPeuckerReduction(points, firstPoint, indexFarthest, tolerance); douglasPeuckerReduction(points, indexFarthest, lastPoint, tolerance); } }; var perpendicularDistance = function(point1, point2, point) { 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 = []; pointIndexsToKeep.push(firstPoint); pointIndexsToKeep.push(lastPoint); while (points[firstPoint].equals(points[lastPoint])) { lastPoint--; 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 = OpenLayers.Class( OpenLayers.Geometry.LineString, { componentTypes: ["OpenLayers.Geometry.Point"], addComponent: function(point, index) { var added = false; var lastPoint = this.components.pop(); if (index != null || !point.equals(lastPoint)) { added = OpenLayers.Geometry.Collection.prototype.addComponent.apply( this, arguments ); } var firstPoint = this.components[0]; OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, [ firstPoint ]); return added; }, removeComponent: function(point) { var removed = this.components && this.components.length > 3; if (removed) { this.components.pop(); OpenLayers.Geometry.Collection.prototype.removeComponent.apply( this, arguments ); var firstPoint = this.components[0]; OpenLayers.Geometry.Collection.prototype.addComponent.apply(this, [ firstPoint ]); } return removed; }, move: function(x, y) { for (var i = 0, len = this.components.length; i < len - 1; i++) { this.components[i].move(x, y); } }, rotate: function(angle, origin) { for (var i = 0, len = this.components.length; i < len - 1; ++i) { this.components[i].rotate(angle, origin); } }, resize: function(scale, origin, ratio) { for (var i = 0, len = this.components.length; i < len - 1; ++i) { this.components[i].resize(scale, origin, ratio); } return this; }, transform: function(source, dest) { if (source && dest) { for (var i = 0, len = this.components.length; i < len - 1; i++) { var component = this.components[i]; component.transform(source, dest); } this.bounds = null; } return this; }, getCentroid: function() { if (this.components && this.components.length > 2) { var sumX = 0.0; var sumY = 0.0; for (var i = 0; i < this.components.length - 1; i++) { var b = this.components[i]; var c = this.components[i + 1]; sumX += (b.x + c.x) * (b.x * c.y - c.x * b.y); sumY += (b.y + c.y) * (b.x * c.y - c.x * b.y); } var area = -1 * this.getArea(); var x = sumX / (6 * area); var y = sumY / (6 * area); return new OpenLayers.Geometry.Point(x, y); } else { return null; } }, 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 < len - 1; i++) { var b = this.components[i]; var c = this.components[i + 1]; sum += (b.x + c.x) * (c.y - b.y); } area = -sum / 2.0; } return area; }, getGeodesicArea: function(projection) { var ring = this; 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 < len - 1; i++) { p1 = ring.components[i]; p2 = ring.components[i + 1]; area += OpenLayers.Util.rad(p2.x - p1.x) * (2 + Math.sin(OpenLayers.Util.rad(p1.y)) + Math.sin(OpenLayers.Util.rad(p2.y))); } area = (area * 6378137.0 * 6378137.0) / 2.0; } return area; }, 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 < numSeg; ++i) { start = this.components[i]; x1 = approx(start.x, digs); y1 = approx(start.y, digs); end = this.components[i + 1]; x2 = approx(end.x, digs); y2 = approx(end.y, digs); if (y1 == y2) { if (py == y1) { if ( (x1 <= x2 && (px >= x1 && px <= x2)) || (x1 >= x2 && (px <= x1 && px >= x2)) ) { crosses = -1; break; } } continue; } cx = approx(getX(py, x1, y1, x2, y2), digs); if (cx == px) { if ( (y1 < y2 && (py >= y1 && py <= y2)) || (y1 > y2 && (py <= y1 && py >= y2)) ) { crosses = -1; break; } } if (cx <= px) { continue; } if (x1 != x2 && (cx < Math.min(x1, x2) || cx > Math.max(x1, x2))) { continue; } if ( (y1 < y2 && (py >= y1 && py < y2)) || (y1 > y2 && (py < y1 && py >= y2)) ) { ++crosses; } } var contained = crosses == -1 ? 1 : !!(crosses & 1); return contained; }, 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 { for (var i = 0, len = geometry.components.length; i < len; ++i) { intersect = geometry.components[i].intersects(this); if (intersect) { break; } } } return intersect; }, getVertices: function(nodes) { return nodes === true ? [] : this.components.slice(0, this.components.length - 1); }, CLASS_NAME: "OpenLayers.Geometry.LinearRing" } ); OpenLayers.Layer.HTTPRequest = OpenLayers.Class(OpenLayers.Layer, { URL_HASH_FACTOR: (Math.sqrt(5) - 1) / 2, url: null, params: null, reproject: false, 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); } }, destroy: function() { this.url = null; this.params = null; OpenLayers.Layer.prototype.destroy.apply(this, arguments); }, clone: function(obj) { if (obj == null) { obj = new OpenLayers.Layer.HTTPRequest( this.name, this.url, this.params, this.getOptions() ); } obj = OpenLayers.Layer.prototype.clone.apply(this, [obj]); return obj; }, setUrl: function(newUrl) { this.url = newUrl; }, 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; }, redraw: function(force) { if (force) { return this.mergeNewParams({ _olSalt: Math.random() }); } else { return OpenLayers.Layer.prototype.redraw.apply(this, []); } }, selectUrl: function(paramString, urls) { var product = 1; for (var i = 0, len = paramString.length; i < len; i++) { product *= paramString.charCodeAt(i) * this.URL_HASH_FACTOR; product -= Math.floor(product); } return urls[Math.floor(product * urls.length)]; }, getFullRequestString: function(newParams, altUrl) { var url = altUrl || this.url; var allParams = OpenLayers.Util.extend({}, this.params); allParams = OpenLayers.Util.extend(allParams, newParams); var paramsString = OpenLayers.Util.getParameterString(allParams); if (OpenLayers.Util.isArray(url)) { url = this.selectUrl(paramsString, url); } var urlParams = OpenLayers.Util.upperCaseObject( OpenLayers.Util.getParameters(url) ); for (var key in allParams) { if (key.toUpperCase() in urlParams) { delete allParams[key]; } } paramsString = OpenLayers.Util.getParameterString(allParams); return OpenLayers.Util.urlAppend(url, paramsString); }, CLASS_NAME: "OpenLayers.Layer.HTTPRequest" }); OpenLayers.Tile = OpenLayers.Class({ events: null, eventListeners: null, id: null, layer: null, url: null, bounds: null, size: null, position: null, isLoading: false, 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(); } 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); } }, unload: function() { if (this.isLoading) { this.isLoading = false; this.events.triggerEvent("unload"); } }, 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; }, draw: function(deferred) { if (!deferred) { this.clear(); } var draw = this.shouldDraw(); if (draw && !deferred) { draw = this.events.triggerEvent("beforedraw") !== false; } return draw; }, 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; }, 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; }, moveTo: function(bounds, position, redraw) { if (redraw == null) { redraw = true; } this.setBounds(bounds); this.position = position.clone(); if (redraw) { this.draw(); } }, clear: function(draw) {}, CLASS_NAME: "OpenLayers.Tile" }); OpenLayers.Tile.Image = OpenLayers.Class(OpenLayers.Tile, { url: null, imgDiv: null, frame: null, imageReloadAttempts: null, layerAlphaHack: null, asyncRequestId: null, blankImageUrl: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAQAIBRAA7", maxGetUrlLength: null, canvasContext: null, crossOriginKeyword: null, initialize: function(layer, position, bounds, url, size, options) { OpenLayers.Tile.prototype.initialize.apply(this, arguments); this.url = url; this.layerAlphaHack = this.layer.alpha && OpenLayers.Util.alphaHack(); if ( this.maxGetUrlLength != null || this.layer.gutter || this.layerAlphaHack ) { 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); } }, destroy: function() { if (this.imgDiv) { this.clear(); this.imgDiv = null; this.frame = null; } this.asyncRequestId = null; OpenLayers.Tile.prototype.destroy.apply(this, arguments); }, draw: function() { var drawn = OpenLayers.Tile.prototype.draw.apply(this, arguments); if (drawn) { if (this.layer != this.layer.map.baseLayer && this.layer.reproject) { this.bounds = this.getBoundsFromBaseLayer(this.position); } if (this.isLoading) { this._loadEvent = "reload"; } else { this.isLoading = true; this._loadEvent = "loadstart"; } this.positionTile(); this.renderTile(); } else { this.unload(); } return drawn; }, renderTile: function() { this.layer.div.appendChild(this.getTile()); if (this.layer.async) { 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 { this.url = this.layer.getURL(this.bounds); this.initImage(); } }, positionTile: function() { var style = this.getTile().style, size = this.frame ? this.size : this.layer.getImageSize(this.bounds); style.left = this.position.x + "%"; style.top = this.position.y + "%"; style.width = size.w + "%"; style.height = size.h + "%"; }, clear: function() { OpenLayers.Tile.prototype.clear.apply(this, arguments); var img = this.imgDiv; if (img) { OpenLayers.Event.stopObservingElement(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; }, getImage: function() { if (!this.imgDiv) { this.imgDiv = document.createElement("img"); this.imgDiv.className = "olTileImage"; this.imgDiv.galleryImg = "no"; 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) { style.paddingTop = style.height; style.height = "0"; style.width = "100%"; } if (this.frame) { this.frame.appendChild(this.imgDiv); } } return this.imgDiv; }, initImage: function() { this.events.triggerEvent(this._loadEvent); var img = this.getImage(); if (this.url && img.getAttribute("src") == this.url) { this.onImageLoad(); } else { var load = OpenLayers.Function.bind(function() { OpenLayers.Event.stopObservingElement(img); 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); }, this); if (img.getAttribute("src") == this.blankImageUrl) { load(); } else { OpenLayers.Event.observe(img, "load", load); OpenLayers.Event.observe(img, "error", load); if (this.crossOriginKeyword) { img.removeAttribute("crossorigin"); } img.src = this.blankImageUrl; } } }, setImgSrc: function(url) { var img = this.imgDiv; img.style.visibility = "hidden"; img.style.opacity = 0; if (url) { if (this.crossOriginKeyword) { if (url.substr(0, 5) !== "data:") { img.setAttribute("crossorigin", this.crossOriginKeyword); } else { img.removeAttribute("crossorigin"); } } img.src = url; } }, getTile: function() { return this.frame ? this.frame : this.getImage(); }, 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; }, onImageLoad: function() { var img = this.imgDiv; OpenLayers.Event.stopObservingElement(img); img.style.visibility = "inherit"; img.style.opacity = this.layer.opacity; this.isLoading = false; this.canvasContext = null; this.events.triggerEvent("loadend"); if ( parseFloat(navigator.appVersion.split("MSIE")[1]) < 7 && this.layer && this.layer.div ) { var span = document.createElement("span"); span.style.display = "none"; var layerDiv = this.layer.div; layerDiv.appendChild(span); window.setTimeout(function() { span.parentNode === layerDiv && span.parentNode.removeChild(span); }, 0); } if (this.layerAlphaHack === true) { img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + img.src + "', sizingMethod='scale')"; } }, 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(); } } }, 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" }); OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, { tileSize: null, tileOriginCorner: "bl", tileOrigin: null, tileOptions: null, tileClass: OpenLayers.Tile.Image, grid: null, singleTile: false, ratio: 1.5, buffer: 0, transitionEffect: null, numLoadingTiles: 0, tileLoadingDelay: 85, serverResolutions: null, moveTimerId: null, deferMoveGriddedTiles: null, tileQueueId: null, tileQueue: null, loading: false, backBuffer: null, gridResolution: null, backBufferResolution: null, backBufferLonLat: null, backBufferTimerId: null, removeBackBufferDelay: null, className: null, initialize: function(name, url, params, options) { OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this, arguments); this.grid = []; this.tileQueue = []; if (this.removeBackBufferDelay === null) { this.removeBackBufferDelay = this.singleTile ? 0 : 2500; } if (this.className === null) { this.className = this.singleTile ? "olLayerGridSingleTile" : "olLayerGrid"; } if (!OpenLayers.Animation.isNative) { this.deferMoveGriddedTiles = OpenLayers.Function.bind(function() { this.moveGriddedTiles(true); this.moveTimerId = null; }, this); } }, setMap: function(map) { OpenLayers.Layer.HTTPRequest.prototype.setMap.call(this, map); OpenLayers.Element.addClass(this.div, this.className); }, removeMap: function(map) { if (this.moveTimerId !== null) { window.clearTimeout(this.moveTimerId); this.moveTimerId = null; } this.clearTileQueue(); if (this.backBufferTimerId !== null) { window.clearTimeout(this.backBufferTimerId); this.backBufferTimerId = null; } }, destroy: function() { this.removeBackBuffer(); this.clearGrid(); this.grid = null; this.tileSize = null; OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this, arguments); }, clearGrid: function() { this.clearTileQueue(); if (this.grid) { for (var iRow = 0, len = this.grid.length; iRow < len; iRow++) { var row = this.grid[iRow]; for (var iCol = 0, clen = row.length; iCol < clen; iCol++) { var tile = row[iCol]; this.destroyTile(tile); } } this.grid = []; this.gridResolution = null; } }, clone: function(obj) { if (obj == null) { obj = new OpenLayers.Layer.Grid( this.name, this.url, this.params, this.getOptions() ); } obj = OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this, [obj]); if (this.tileSize != null) { obj.tileSize = this.tileSize.clone(); } obj.grid = []; obj.gridResolution = null; obj.backBuffer = null; obj.backBufferTimerId = null; obj.tileQueue = []; obj.tileQueueId = null; obj.loading = false; obj.moveTimerId = null; return obj; }, moveTo: function(bounds, zoomChanged, dragging) { OpenLayers.Layer.HTTPRequest.prototype.moveTo.apply(this, arguments); bounds = bounds || this.map.getExtent(); if (bounds != null) { var forceReTile = !this.grid.length || zoomChanged; var tilesBounds = this.getTilesBounds(); var resolution = this.map.getResolution(); var serverResolution = this.getServerResolution(resolution); if (this.singleTile) { if (forceReTile || (!dragging && !tilesBounds.containsBounds(bounds))) { if (zoomChanged && this.transitionEffect !== "resize") { this.removeBackBuffer(); } if (!zoomChanged || this.transitionEffect === "resize") { this.applyBackBuffer(serverResolution); } this.initSingleTile(bounds); } } else { forceReTile = forceReTile || !tilesBounds.intersectsBounds(bounds, { worldBounds: this.map.baseLayer.wrapDateLine && this.map.getMaxExtent() }); if (resolution !== serverResolution) { bounds = this.map.calculateBounds(null, serverResolution); if (forceReTile) { var scale = serverResolution / resolution; this.transformDiv(scale); } } else { this.div.style.width = "100%"; this.div.style.height = "100%"; this.div.style.left = "0%"; this.div.style.top = "0%"; } if (forceReTile) { if (zoomChanged && this.transitionEffect === "resize") { this.applyBackBuffer(serverResolution); } this.initGriddedTiles(bounds); } else { this.moveGriddedTiles(); } } } }, 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) { if (this.map.baseLayer.wrapDateLine) { var worldWidth = this.map.getMaxExtent().getWidth(); var worldsAway = Math.ceil((left - x) / worldWidth); x += worldWidth * worldsAway; } } var dtx = (x - left) / (res * tileWidth); var dty = (top - y) / (res * tileHeight); 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, i: Math.floor((dtx - col) * tileWidth), j: Math.floor((dty - row) * tileHeight) }; } } } return data; }, queueTileDraw: function(evt) { var tile = evt.object; if (!~OpenLayers.Util.indexOf(this.tileQueue, tile)) { this.tileQueue.push(tile); } if (!this.tileQueueId) { this.tileQueueId = OpenLayers.Animation.start( OpenLayers.Function.bind(this.drawTileFromQueue, this), null, this.div ); } return false; }, drawTileFromQueue: function() { if (this.tileQueue.length === 0) { this.clearTileQueue(); } else { this.tileQueue.shift().draw(true); } }, clearTileQueue: function() { OpenLayers.Animation.stop(this.tileQueueId); this.tileQueueId = null; this.tileQueue = []; }, destroyTile: function(tile) { this.removeTileMonitoringHooks(tile); tile.destroy(); }, getServerResolution: function(resolution) { resolution = resolution || this.map.getResolution(); if ( this.serverResolutions && OpenLayers.Util.indexOf(this.serverResolutions, resolution) === -1 ) { var i, serverResolution; for (i = this.serverResolutions.length - 1; i >= 0; i--) { serverResolution = this.serverResolutions[i]; if (serverResolution > resolution) { resolution = serverResolution; break; } } if (i === -1) { throw "no appropriate resolution in serverResolutions"; } } return resolution; }, getServerZoom: function() { var resolution = this.getServerResolution(); return this.serverResolutions ? OpenLayers.Util.indexOf(this.serverResolutions, resolution) : this.map.getZoomForResolution(resolution) + (this.zoomOffset || 0); }, transformDiv: function(scale) { this.div.style.width = 100 * scale + "%"; this.div.style.height = 100 * scale + "%"; var size = this.map.getSize(); var lcX = parseInt(this.map.layerContainerDiv.style.left, 10); var lcY = parseInt(this.map.layerContainerDiv.style.top, 10); var x = (lcX - size.w / 2.0) * (scale - 1); var y = (lcY - size.h / 2.0) * (scale - 1); this.div.style.left = x + "%"; this.div.style.top = y + "%"; }, getResolutionScale: function() { return parseInt(this.div.style.width, 10) / 100; }, applyBackBuffer: function(resolution) { if (this.backBufferTimerId !== null) { this.removeBackBuffer(); } var backBuffer = this.backBuffer; if (!backBuffer) { backBuffer = this.createBackBuffer(); if (!backBuffer) { return; } this.div.insertBefore(backBuffer, this.div.firstChild); this.backBuffer = backBuffer; var topLeftTileBounds = this.grid[0][0].bounds; this.backBufferLonLat = { lon: topLeftTileBounds.left, lat: topLeftTileBounds.top }; this.backBufferResolution = this.gridResolution; } var style = backBuffer.style; var ratio = this.backBufferResolution / resolution; style.width = 100 * ratio + "%"; style.height = 100 * ratio + "%"; var position = this.getViewPortPxFromLonLat( this.backBufferLonLat, resolution ); var leftOffset = parseInt(this.map.layerContainerDiv.style.left, 10); var topOffset = parseInt(this.map.layerContainerDiv.style.top, 10); backBuffer.style.left = Math.round(position.x - leftOffset) + "%"; backBuffer.style.top = Math.round(position.y - topOffset) + "%"; }, 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"; backBuffer.style.width = "100%"; backBuffer.style.height = "100%"; for (var i = 0, lenI = this.grid.length; i < lenI; i++) { for (var j = 0, lenJ = this.grid[i].length; j < lenJ; j++) { var tile = this.grid[i][j].createBackBuffer(); if (!tile) { continue; } tile.style.top = i * this.tileSize.h + "%"; tile.style.left = j * this.tileSize.w + "%"; backBuffer.appendChild(tile); } } } return backBuffer; }, removeBackBuffer: function() { if (this.backBuffer) { this.div.removeChild(this.backBuffer); this.backBuffer = null; this.backBufferResolution = null; if (this.backBufferTimerId !== null) { window.clearTimeout(this.backBufferTimerId); this.backBufferTimerId = null; } } }, moveByPx: function(dx, dy) { if (!this.singleTile) { this.moveGriddedTiles(); } }, setTileSize: function(size) { if (this.singleTile) { size = this.map.getSize(); size.h = parseInt(size.h * this.ratio); size.w = parseInt(size.w * this.ratio); } OpenLayers.Layer.HTTPRequest.prototype.setTileSize.apply(this, [size]); }, 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; }, initSingleTile: function(bounds) { this.clearTileQueue(); 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); } this.removeExcessTiles(1, 1); this.gridResolution = this.getServerResolution(); }, 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 tilecolremain = offsetlon / tilelon - tilecol; var tileoffsetx = -tilecolremain * this.tileSize.w; var tileoffsetlon = origin.lon + tilecol * tilelon; var offsetlat = bounds.top - (origin.lat + tilelat); var tilerow = Math.ceil(offsetlat / tilelat) + this.buffer; var tilerowremain = tilerow - offsetlat / tilelat; var tileoffsety = -tilerowremain * this.tileSize.h; var tileoffsetlat = origin.lat + tilerow * tilelat; return { tilelon: tilelon, tilelat: tilelat, tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat, tileoffsetx: tileoffsetx, tileoffsety: tileoffsety }; }, 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; }, initGriddedTiles: function(bounds) { this.clearTileQueue(); var viewSize = this.map.getSize(); var minRows = Math.ceil(viewSize.h / this.tileSize.h) + Math.max(1, 2 * this.buffer); var minCols = Math.ceil(viewSize.w / this.tileSize.w) + Math.max(1, 2 * this.buffer); var origin = this.getTileOrigin(); var resolution = this.getServerResolution(); var tileLayout = this.calculateGridLayout(bounds, origin, resolution); var tileoffsetx = Math.round(tileLayout.tileoffsetx); var tileoffsety = Math.round(tileLayout.tileoffsety); var tileoffsetlon = tileLayout.tileoffsetlon; var tileoffsetlat = tileLayout.tileoffsetlat; var tilelon = tileLayout.tilelon; var tilelat = tileLayout.tilelat; var startX = tileoffsetx; var startLon = tileoffsetlon; var rowidx = 0; var layerContainerDivLeft = parseInt(this.map.layerContainerDiv.style.left); var layerContainerDivTop = parseInt(this.map.layerContainerDiv.style.top); var tileData = [], center = this.map.getCenter(); do { var row = this.grid[rowidx++]; if (!row) { row = []; this.grid.push(row); } tileoffsetlon = startLon; tileoffsetx = startX; var colidx = 0; do { var tileBounds = new OpenLayers.Bounds( tileoffsetlon, tileoffsetlat, tileoffsetlon + tilelon, tileoffsetlat + tilelat ); var x = tileoffsetx; x -= layerContainerDivLeft; var y = tileoffsety; y -= layerContainerDivTop; var px = new OpenLayers.Pixel(x, y); 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) }); tileoffsetlon += tilelon; tileoffsetx += this.tileSize.w; } while ( tileoffsetlon <= bounds.right + tilelon * this.buffer || colidx < minCols ); tileoffsetlat -= tilelat; tileoffsety += this.tileSize.h; } while ( tileoffsetlat >= bounds.bottom - tilelat * this.buffer || rowidx < minRows ); this.removeExcessTiles(rowidx, colidx); this.gridResolution = this.getServerResolution(); tileData.sort(function(a, b) { return a.distance - b.distance; }); for (var i = 0, ii = tileData.length; i < ii; ++i) { tileData[i].tile.draw(); } }, getMaxExtent: function() { return this.maxExtent; }, addTile: function(bounds, position) { var tile = new this.tileClass( this, position, bounds, null, this.tileSize, this.tileOptions ); tile.events.register("beforedraw", this, this.queueTileDraw); return tile; }, addTileMonitoringHooks: function(tile) { tile.onLoadStart = function() { if (this.loading === false) { this.loading = true; this.events.triggerEvent("loadstart"); } this.events.triggerEvent("tileloadstart", { tile: tile }); this.numLoadingTiles++; }; tile.onLoadEnd = function() { this.numLoadingTiles--; this.events.triggerEvent("tileloaded", { tile: tile }); if (this.tileQueue.length === 0 && this.numLoadingTiles === 0) { this.loading = false; this.events.triggerEvent("loadend"); if (this.backBuffer) { this.backBufferTimerId = window.setTimeout( OpenLayers.Function.bind(this.removeBackBuffer, this), this.removeBackBufferDelay ); } } }; 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 }); }, removeTileMonitoringHooks: function(tile) { tile.unload(); tile.events.un({ loadstart: tile.onLoadStart, loadend: tile.onLoadEnd, unload: tile.onLoadEnd, loaderror: tile.onLoadError, scope: this }); }, moveGriddedTiles: function(deferred) { if (!deferred && !OpenLayers.Animation.isNative) { if (this.moveTimerId != null) { window.clearTimeout(this.moveTimerId); } this.moveTimerId = window.setTimeout( this.deferMoveGriddedTiles, this.tileLoadingDelay ); return; } var buffer = this.buffer || 1; var scale = this.getResolutionScale(); while (true) { var tlViewPort = { x: this.grid[0][0].position.x * scale + parseInt(this.div.style.left, 10) + parseInt(this.map.layerContainerDiv.style.left), y: this.grid[0][0].position.y * scale + parseInt(this.div.style.top, 10) + parseInt(this.map.layerContainerDiv.style.top) }; var tileSize = { w: this.tileSize.w * scale, h: this.tileSize.h * scale }; if (tlViewPort.x > -tileSize.w * (buffer - 1)) { this.shiftColumn(true); } else if (tlViewPort.x < -tileSize.w * buffer) { this.shiftColumn(false); } else if (tlViewPort.y > -tileSize.h * (buffer - 1)) { this.shiftRow(true); } else if (tlViewPort.y < -tileSize.h * buffer) { this.shiftRow(false); } else { break; } } }, shiftRow: function(prepend) { var modelRowIndex = prepend ? 0 : this.grid.length - 1; var grid = this.grid; var modelRow = grid[modelRowIndex]; var resolution = this.getServerResolution(); var deltaY = prepend ? -this.tileSize.h : this.tileSize.h; var deltaLat = resolution * -deltaY; var row = prepend ? grid.pop() : grid.shift(); for (var i = 0, len = modelRow.length; i < len; i++) { var modelTile = modelRow[i]; var bounds = modelTile.bounds.clone(); var position = modelTile.position.clone(); bounds.bottom = bounds.bottom + deltaLat; bounds.top = bounds.top + deltaLat; position.y = position.y + deltaY; row[i].moveTo(bounds, position); } if (prepend) { grid.unshift(row); } else { grid.push(row); } }, shiftColumn: function(prepend) { var deltaX = prepend ? -this.tileSize.w : this.tileSize.w; var resolution = this.getServerResolution(); var deltaLon = resolution * deltaX; for (var i = 0, len = this.grid.length; i < len; i++) { var row = this.grid[i]; var modelTileIndex = prepend ? 0 : row.length - 1; var modelTile = row[modelTileIndex]; var bounds = modelTile.bounds.clone(); var position = modelTile.position.clone(); bounds.left = bounds.left + deltaLon; bounds.right = bounds.right + deltaLon; position.x = position.x + deltaX; var tile = prepend ? this.grid[i].pop() : this.grid[i].shift(); tile.moveTo(bounds, position); if (prepend) { row.unshift(tile); } else { row.push(tile); } } }, removeExcessTiles: function(rows, columns) { var i, l; while (this.grid.length > rows) { var row = this.grid.pop(); for (i = 0, l = row.length; i < l; i++) { var tile = row[i]; this.destroyTile(tile); } } for (i = 0, l = this.grid.length; i < l; i++) { while (this.grid[i].length > columns) { var row = this.grid[i]; var tile = row.pop(); this.destroyTile(tile); } } }, onMapResize: function() { if (this.singleTile) { this.clearGrid(); this.setTileSize(); } }, 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 = OpenLayers.Class(OpenLayers.Layer.Grid, { isBaseLayer: true, sphericalMercator: false, zoomOffset: 0, serverResolutions: null, 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 ]); }, clone: function(obj) { if (obj == null) { obj = new OpenLayers.Layer.XYZ(this.name, this.url, this.getOptions()); } obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]); return obj; }, 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); }, 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 }; }, 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 = OpenLayers.Class(OpenLayers.Layer.XYZ, { name: "OpenStreetMap", 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" ], attribution: "Data CC-By-SA by OpenStreetMap", sphericalMercator: true, wrapDateLine: true, tileOptions: null, 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 ); }, 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.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, { key: null, 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 ], attributionTemplate: '' + '
' + '
${copyrights}' + '' + "Terms of Use
", metadata: null, type: "Road", culture: "en-US", metadataParams: null, tileOptions: null, 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(); }, loadMetadata: function() { this._callbackId = "_callback_" + this.id.replace(/\./g, "_"); 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 = "http://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); }, initLayer: function() { var res = this.metadata.resourceSets[0].resources[0]; var url = res.imageUrl.replace("{quadkey}", "${quadkey}"); url = url.replace("{culture}", this.culture); this.url = []; for (var i = 0; i < res.imageUrlSubdomains.length; ++i) { this.url.push(url.replace("{subdomain}", res.imageUrlSubdomains[i])); } this.addOptions( { maxResolution: Math.min( this.serverResolutions[res.zoomMin], this.maxResolution || Number.POSITIVE_INFINITY ), numZoomLevels: Math.min( res.zoomMax + 1 - res.zoomMin, this.numZoomLevels ) }, true ); }, 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 }); }, 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 < ii; ++i) { provider = providers[i]; for (j = 0, jj = provider.coverageAreas.length; j < jj; ++j) { coverage = provider.coverageAreas[j]; bbox = OpenLayers.Bounds.fromArray(coverage.bbox, true); if ( extent.intersectsBounds(bbox) && zoom <= coverage.zoomMax && zoom >= coverage.zoomMin ) { copyrights += provider.attribution + " "; } } } this.attribution = OpenLayers.String.format(this.attributionTemplate, { type: this.type.toLowerCase(), logo: metadata.brandLogoUri, copyrights: copyrights }); this.map && this.map.events.triggerEvent("changelayer", { layer: this, property: "attribution" }); }, setMap: function() { OpenLayers.Layer.XYZ.prototype.setMap.apply(this, arguments); this.updateAttribution(); this.map.events.register("moveend", this, this.updateAttribution); }, clone: function(obj) { if (obj == null) { obj = new OpenLayers.Layer.Bing(this.options); } obj = OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]); return obj; }, 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" }); 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; delete this._callbackId; }; OpenLayers.Handler = OpenLayers.Class({ id: null, control: null, map: null, keyMask: null, active: false, evt: null, 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 + "_"); }, setMap: function(map) { this.map = map; }, checkModifiers: function(evt) { if (this.keyMask == null) { return true; } var keyModifiers = (evt.shiftKey ? OpenLayers.Handler.MOD_SHIFT : 0) | (evt.ctrlKey ? OpenLayers.Handler.MOD_CTRL : 0) | (evt.altKey ? OpenLayers.Handler.MOD_ALT : 0); return keyModifiers == this.keyMask; }, activate: function() { if (this.active) { return false; } var events = OpenLayers.Events.prototype.BROWSER_EVENTS; for (var i = 0, len = events.length; i < len; i++) { if (this[events[i]]) { this.register(events[i], this[events[i]]); } } this.active = true; return true; }, deactivate: function() { if (!this.active) { return false; } var events = OpenLayers.Events.prototype.BROWSER_EVENTS; for (var i = 0, len = events.length; i < len; i++) { if (this[events[i]]) { this.unregister(events[i], this[events[i]]); } } this.active = false; return true; }, callback: function(name, args) { if (name && this.callbacks[name]) { this.callbacks[name].apply(this.control, args); } }, register: function(name, method) { this.map.events.registerPriority(name, this, method); this.map.events.registerPriority(name, this, this.setEvent); }, unregister: function(name, method) { this.map.events.unregister(name, this, method); this.map.events.unregister(name, this, this.setEvent); }, setEvent: function(evt) { this.evt = evt; return true; }, destroy: function() { this.deactivate(); this.control = this.map = null; }, CLASS_NAME: "OpenLayers.Handler" }); OpenLayers.Handler.MOD_NONE = 0; OpenLayers.Handler.MOD_SHIFT = 1; OpenLayers.Handler.MOD_CTRL = 2; OpenLayers.Handler.MOD_ALT = 4; OpenLayers.Handler.MouseWheel = OpenLayers.Class(OpenLayers.Handler, { wheelListener: null, mousePosition: null, interval: 0, delta: 0, cumulative: true, initialize: function(control, callbacks, options) { OpenLayers.Handler.prototype.initialize.apply(this, arguments); this.wheelListener = OpenLayers.Function.bindAsEventListener( this.onWheelEvent, this ); }, destroy: function() { OpenLayers.Handler.prototype.destroy.apply(this, arguments); this.wheelListener = null; }, onWheelEvent: function(e) { if (!this.map || !this.checkModifiers(e)) { return; } var overScrollableDiv = false; var overLayerDiv = false; var overMapDiv = false; var elem = OpenLayers.Event.element(e); while (elem != null && !overMapDiv && !overScrollableDiv) { if (!overScrollableDiv) { try { if (elem.currentStyle) { overflow = elem.currentStyle["overflow"]; } else { var style = document.defaultView.getComputedStyle(elem, null); var overflow = style.getPropertyValue("overflow"); } overScrollableDiv = (overflow && overflow == "auto") || overflow == "scroll"; } catch (err) {} } if (!overLayerDiv) { for (var i = 0, len = this.map.layers.length; i < len; i++) { if ( elem == this.map.layers[i].div || elem == this.map.layers[i].pane ) { overLayerDiv = true; break; } } } overMapDiv = elem == this.map.div; elem = elem.parentNode; } if (!overScrollableDiv && overMapDiv) { if (overLayerDiv) { var delta = 0; if (!e) { e = window.event; } if (e.wheelDelta) { delta = e.wheelDelta / 120; if (window.opera && window.opera.version() < 9.2) { delta = -delta; } } else if (e.detail) { delta = -e.detail / 3; } this.delta = this.delta + delta; if (this.interval) { window.clearTimeout(this._timeoutId); this._timeoutId = window.setTimeout( OpenLayers.Function.bind(function() { this.wheelZoom(e); }, this), this.interval ); } else { this.wheelZoom(e); } } OpenLayers.Event.stop(e); } }, wheelZoom: function(e) { var delta = this.delta; this.delta = 0; if (delta) { if (this.mousePosition) { e.xy = this.mousePosition; } if (!e.xy) { e.xy = this.map.getPixelFromLonLat(this.map.getCenter()); } if (delta < 0) { this.callback("down", [e, this.cumulative ? delta : -1]); } else { this.callback("up", [e, this.cumulative ? delta : 1]); } } }, mousemove: function(evt) { this.mousePosition = evt.xy; }, activate: function(evt) { if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) { var wheelListener = this.wheelListener; OpenLayers.Event.observe(window, "DOMMouseScroll", wheelListener); OpenLayers.Event.observe(window, "mousewheel", wheelListener); OpenLayers.Event.observe(document, "mousewheel", wheelListener); return true; } else { return false; } }, deactivate: function(evt) { if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { var wheelListener = this.wheelListener; OpenLayers.Event.stopObserving(window, "DOMMouseScroll", wheelListener); OpenLayers.Event.stopObserving(window, "mousewheel", wheelListener); OpenLayers.Event.stopObserving(document, "mousewheel", wheelListener); return true; } else { return false; } }, CLASS_NAME: "OpenLayers.Handler.MouseWheel" }); OpenLayers.Geometry.MultiLineString = OpenLayers.Class( OpenLayers.Geometry.Collection, { componentTypes: ["OpenLayers.Geometry.LineString"], 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 < len; ++i) { sourceLine = this.components[i]; sourceSplit = false; for (var j = 0; j < targetParts.length; ++j) { splits = sourceLine.split(targetParts[j], options); if (splits) { if (mutual) { sourceLines = splits[0]; for (var k = 0, klen = sourceLines.length; k < klen; ++k) { if (k === 0 && sourceParts.length) { sourceParts[sourceParts.length - 1].addComponent( sourceLines[k] ); } else { sourceParts.push( new OpenLayers.Geometry.MultiLineString([sourceLines[k]]) ); } } sourceSplit = true; splits = splits[1]; } if (splits.length) { splits.unshift(j, 1); Array.prototype.splice.apply(targetParts, splits); break; } } } if (!sourceSplit) { if (sourceParts.length) { sourceParts[sourceParts.length - 1].addComponent( sourceLine.clone() ); } else { sourceParts = [ new OpenLayers.Geometry.MultiLineString(sourceLine.clone()) ]; } } } if (sourceParts && sourceParts.length > 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; }, 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 < len; ++i) { targetSplit = false; targetLine = this.components[i]; for (var j = 0; j < sourceParts.length; ++j) { splits = sourceParts[j].split(targetLine, options); if (splits) { if (mutual) { sourceLines = splits[0]; if (sourceLines.length) { sourceLines.unshift(j, 1); Array.prototype.splice.apply(sourceParts, sourceLines); j += sourceLines.length - 2; } splits = splits[1]; if (splits.length === 0) { splits = [targetLine.clone()]; } } for (var k = 0, klen = splits.length; k < klen; ++k) { if (k === 0 && targetParts.length) { targetParts[targetParts.length - 1].addComponent(splits[k]); } else { targetParts.push( new OpenLayers.Geometry.MultiLineString([splits[k]]) ); } } targetSplit = true; } } if (!targetSplit) { if (targetParts.length) { targetParts[targetParts.length - 1].addComponent( targetLine.clone() ); } else { targetParts = [ new OpenLayers.Geometry.MultiLineString([targetLine.clone()]) ]; } } } } else { results = geometry.split(this); } if (sourceParts && sourceParts.length > 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.Renderer = OpenLayers.Class({ container: null, root: null, extent: null, locked: false, size: null, resolution: null, map: null, featureDx: 0, initialize: function(containerID, options) { this.container = OpenLayers.Util.getElement(containerID); OpenLayers.Util.extend(this, options); }, destroy: function() { this.container = null; this.extent = null; this.size = null; this.resolution = null; this.map = null; }, supported: function() { return false; }, 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; }, setSize: function(size) { this.size = size.clone(); this.resolution = null; }, getResolution: function() { this.resolution = this.resolution || this.map.getResolution(); return this.resolution; }, 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; } } }, 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; } }, drawGeometry: function(geometry, style, featureId) {}, drawText: function(featureId, style, location) {}, removeText: function(featureId) {}, clear: function() {}, getFeatureIdFromEvent: function(evt) {}, eraseFeatures: function(features) { if (!OpenLayers.Util.isArray(features)) { features = [features]; } for (var i = 0, len = features.length; i < len; ++i) { var feature = features[i]; this.eraseGeometry(feature.geometry, feature.id); this.removeText(feature.id); } }, eraseGeometry: function(geometry, featureId) {}, moveRoot: function(renderer) {}, getRenderLayerId: function() { return this.container.id; }, 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" }); OpenLayers.Renderer.defaultSymbolizer = { fillColor: "#000000", strokeColor: "#000000", strokeWidth: 2, fillOpacity: 1, strokeOpacity: 1, pointRadius: 0, labelAlign: "cm" }; 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.ElementsIndexer = OpenLayers.Class({ maxZIndex: null, order: null, indices: null, compare: null, initialize: function(yOrdering) { this.compare = yOrdering ? OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER : OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER; this.clear(); }, insert: function(newNode) { 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); return this.getNextElement(rightIndex); }, remove: function(node) { var nodeId = node.id; var arrayIndex = OpenLayers.Util.indexOf(this.order, nodeId); if (arrayIndex >= 0) { this.order.splice(arrayIndex, 1); delete this.indices[nodeId]; if (this.order.length > 0) { var lastId = this.order[this.order.length - 1]; this.maxZIndex = this.indices[lastId]; } else { this.maxZIndex = 0; } } }, clear: function() { this.order = []; this.indices = {}; this.maxZIndex = 0; }, exists: function(node) { return this.indices[node.id] != null; }, getZIndex: function(node) { return node._style.graphicZIndex; }, determineZIndex: function(node) { var zIndex = node._style.graphicZIndex; if (zIndex == null) { zIndex = this.maxZIndex; node._style.graphicZIndex = zIndex; } else if (zIndex > this.maxZIndex) { this.maxZIndex = zIndex; } }, 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" }); OpenLayers.ElementsIndexer.IndexingMethods = { 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; }, Z_ORDER_DRAWING_ORDER: function(indexer, newNode, nextNode) { var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER( indexer, newNode, nextNode ); if (nextNode && returnVal == 0) { returnVal = 1; } return returnVal; }, 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; } }; OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, { rendererRoot: null, root: null, vectorRoot: null, textRoot: null, xmlns: null, xOffset: 0, indexer: null, BACKGROUND_ID_SUFFIX: "_background", LABEL_ID_SUFFIX: "_label", LABEL_OUTLINE_SUFFIX: "_outline", 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); } }, destroy: function() { this.clear(); this.rendererRoot = null; this.root = null; this.xmlns = null; OpenLayers.Renderer.prototype.destroy.apply(this, arguments); }, 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(); } }, 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; }, getNodeType: function(geometry, style) {}, 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 < len; i++) { rendered = this.drawGeometry(geometry.components[i], style, featureId) && rendered; } return rendered; } rendered = false; var removeBackground = false; if (style.display != "none") { if (style.backgroundGraphic) { this.redrawBackgroundNode(geometry.id, geometry, style, featureId); } else { removeBackground = true; } rendered = this.redrawNode(geometry.id, geometry, style, featureId); } if (rendered == false) { var node = document.getElementById(geometry.id); if (node) { if (node._style.backgroundGraphic) { removeBackground = true; } node.parentNode.removeChild(node); } } if (removeBackground) { var node = document.getElementById( geometry.id + this.BACKGROUND_ID_SUFFIX ); if (node) { node.parentNode.removeChild(node); } } return rendered; }, redrawNode: function(id, geometry, style, featureId) { style = this.applyDefaultSymbolizer(style); var node = this.nodeFactory(id, this.getNodeType(geometry, style)); 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; if (this.indexer) { var insert = this.indexer.insert(node); if (insert) { this.vectorRoot.insertBefore(node, insert); } else { this.vectorRoot.appendChild(node); } } else { if (node.parentNode !== this.vectorRoot) { this.vectorRoot.appendChild(node); } } this.postDraw(node); return drawResult.complete; }, redrawBackgroundNode: function(id, geometry, style, featureId) { var backgroundStyle = OpenLayers.Util.extend({}, style); 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; backgroundStyle.backgroundGraphic = null; backgroundStyle.backgroundXOffset = null; backgroundStyle.backgroundYOffset = null; backgroundStyle.backgroundGraphicZIndex = null; return this.redrawNode( id + this.BACKGROUND_ID_SUFFIX, geometry, backgroundStyle, null ); }, 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; if (drawn != false) { return { node: this.setStyle(node, style, options, geometry), complete: drawn }; } else { return false; } }, postDraw: function(node) {}, drawPoint: function(node, geometry) {}, drawLineString: function(node, geometry) {}, drawLinearRing: function(node, geometry) {}, drawPolygon: function(node, geometry) {}, drawRectangle: function(node, geometry) {}, drawCircle: function(node, geometry) {}, 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); } }, getFeatureIdFromEvent: function(evt) { var target = evt.target; var useElement = target && target.correspondingUseElement; var node = useElement ? useElement : target || evt.srcElement; return node._featureId; }, 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 < len; i++) { this.eraseGeometry(geometry.components[i], featureId); } } else { var element = OpenLayers.Util.getElement(geometry.id); if (element && element.parentNode) { if (element.geometry) { element.geometry.destroy(); element.geometry = null; } element.parentNode.removeChild(element); if (this.indexer) { this.indexer.remove(element); } if (element._style.backgroundGraphic) { var backgroundId = geometry.id + this.BACKGROUND_ID_SUFFIX; var bElem = OpenLayers.Util.getElement(backgroundId); if (bElem && bElem.parentNode) { bElem.parentNode.removeChild(bElem); } } } } }, nodeFactory: function(id, type) { var node = OpenLayers.Util.getElement(id); if (node) { if (!this.nodeTypeCompare(node, type)) { node.parentNode.removeChild(node); node = this.nodeFactory(id, type); } } else { node = this.createNode(type, id); } return node; }, nodeTypeCompare: function(node, type) {}, createNode: function(type, id) {}, moveRoot: function(renderer) { var root = this.root; if (renderer.root.parentNode == this.rendererRoot) { root = renderer.root; } root.parentNode.removeChild(root); renderer.rendererRoot.appendChild(root); }, getRenderLayerId: function() { return this.root.parentNode.parentNode.id; }, isComplexSymbol: function(graphicName) { return graphicName != "circle" && !!graphicName; }, CLASS_NAME: "OpenLayers.Renderer.Elements" }); OpenLayers.Control = OpenLayers.Class({ id: null, map: null, div: null, type: null, allowSelection: false, displayClass: "", title: "", autoActivate: false, active: null, handler: null, eventListeners: null, events: null, initialize: function(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 + "_"); } }, destroy: function() { if (this.events) { if (this.eventListeners) { this.events.un(this.eventListeners); } this.events.destroy(); this.events = null; } this.eventListeners = null; 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; }, setMap: function(map) { this.map = map; if (this.handler) { this.handler.setMap(map); } }, 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; }, moveTo: function(px) { if (px != null && this.div != null) { this.div.style.left = px.x + "px"; this.div.style.top = px.y + "px"; } }, 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; }, 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" }); OpenLayers.Control.TYPE_BUTTON = 1; OpenLayers.Control.TYPE_TOGGLE = 2; OpenLayers.Control.TYPE_TOOL = 3; OpenLayers.Control.Panel = OpenLayers.Class(OpenLayers.Control, { controls: null, autoActivate: true, defaultControl: null, saveState: false, allowDepress: false, activeState: null, initialize: function(options) { OpenLayers.Control.prototype.initialize.apply(this, [options]); this.controls = []; this.activeState = {}; }, 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; }, activate: function() { if (OpenLayers.Control.prototype.activate.apply(this, arguments)) { var control; for (var i = 0, len = this.controls.length; i < len; i++) { control = this.controls[i]; if ( control === this.defaultControl || (this.saveState && this.activeState[control.id]) ) { control.activate(); } } if (this.saveState === true) { this.defaultControl = null; } this.redraw(); return true; } else { return false; } }, deactivate: function() { if (OpenLayers.Control.prototype.deactivate.apply(this, arguments)) { var control; for (var i = 0, len = this.controls.length; i < len; i++) { control = this.controls[i]; this.activeState[control.id] = control.deactivate(); } this.redraw(); return true; } else { return false; } }, draw: function() { OpenLayers.Control.prototype.draw.apply(this, arguments); if (this.outsideViewport) { this.events.attachToElement(this.div); this.events.register("buttonclick", this, this.onButtonClick); } else { this.map.events.register("buttonclick", this, this.onButtonClick); } this.addControlsToMap(this.controls); return this.div; }, redraw: function() { for (var l = this.div.childNodes.length, i = l - 1; 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 < len; i++) { this.div.appendChild(this.controls[i].panel_div); } } }, 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 < len; i++) { c = this.controls[i]; if ( c != control && (c.type === OpenLayers.Control.TYPE_TOOL || c.type == null) ) { c.deactivate(); } } control.activate(); } }, addControls: function(controls) { if (!OpenLayers.Util.isArray(controls)) { controls = [controls]; } this.controls = this.controls.concat(controls); for (var i = 0, len = controls.length; i < len; i++) { var control = controls[i], element = this.createControlMarkup(control); OpenLayers.Element.addClass( element, control.displayClass + "ItemInactive" ); OpenLayers.Element.addClass(element, "olButton"); if (control.title != "" && !element.title) { element.title = control.title; } control.panel_div = element; } if (this.map) { this.addControlsToMap(controls); this.redraw(); } }, createControlMarkup: function(control) { return document.createElement("div"); }, addControlsToMap: function(controls) { var control; for (var i = 0, len = controls.length; i < len; i++) { control = controls[i]; if (control.autoActivate === true) { control.autoActivate = false; this.map.addControl(control); control.autoActivate = true; } else { this.map.addControl(control); control.deactivate(); } control.events.on({ activate: this.iconOn, deactivate: this.iconOff }); } }, iconOn: function() { var d = this.panel_div; var re = new RegExp("\\b(" + this.displayClass + "Item)Inactive\\b"); d.className = d.className.replace(re, "$1Active"); }, iconOff: function() { var d = this.panel_div; var re = new RegExp("\\b(" + this.displayClass + "Item)Active\\b"); d.className = d.className.replace(re, "$1Inactive"); }, onButtonClick: function(evt) { var controls = this.controls, button = evt.buttonElement; for (var i = controls.length - 1; i >= 0; --i) { if (controls[i].panel_div === button) { this.activateControl(controls[i]); break; } } }, 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; }, getControlsByName: function(match) { return this.getControlsBy("name", match); }, getControlsByClass: function(match) { return this.getControlsBy("CLASS_NAME", match); }, CLASS_NAME: "OpenLayers.Control.Panel" }); OpenLayers.Strategy = OpenLayers.Class({ layer: null, options: null, active: null, autoActivate: true, autoDestroy: true, initialize: function(options) { OpenLayers.Util.extend(this, options); this.options = options; this.active = false; }, destroy: function() { this.deactivate(); this.layer = null; this.options = null; }, setLayer: function(layer) { this.layer = layer; }, activate: function() { if (!this.active) { this.active = true; return true; } return false; }, deactivate: function() { if (this.active) { this.active = false; return true; } return false; }, CLASS_NAME: "OpenLayers.Strategy" }); OpenLayers.Strategy.Fixed = OpenLayers.Class(OpenLayers.Strategy, { preload: false, activate: function() { if (OpenLayers.Strategy.prototype.activate.apply(this, arguments)) { 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 true; } return false; }, 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; }, load: function(options) { var layer = this.layer; layer.events.triggerEvent("loadstart"); layer.protocol.read( OpenLayers.Util.applyDefaults( { callback: OpenLayers.Function.bind( this.merge, this, layer.map.getProjectionObject() ), filter: layer.filter }, options ) ); layer.events.un({ visibilitychanged: this.load, scope: this }); }, merge: function(mapProjection, resp) { var layer = this.layer; layer.destroyFeatures(); var features = resp.features; if (features && features.length > 0) { if (!mapProjection.equals(layer.projection)) { var geom; for (var i = 0, len = features.length; i < len; ++i) { geom = features[i].geometry; if (geom) { geom.transform(layer.projection, mapProjection); } } } layer.addFeatures(features); } layer.events.triggerEvent("loadend"); }, CLASS_NAME: "OpenLayers.Strategy.Fixed" }); OpenLayers.Control.Zoom = OpenLayers.Class(OpenLayers.Control, { zoomInText: "+", zoomInId: "olZoomInLink", zoomOutText: "-", zoomOutId: "olZoomOutLink", 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; }, 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 }; }, onZoomClick: function(evt) { var button = evt.buttonElement; if (button === this.zoomInLink) { this.map.zoomIn(); } else if (button === this.zoomOutLink) { this.map.zoomOut(); } }, 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.Geometry.Polygon = OpenLayers.Class(OpenLayers.Geometry.Collection, { componentTypes: ["OpenLayers.Geometry.LinearRing"], 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 < len; i++) { area -= Math.abs(this.components[i].getArea()); } } return area; }, 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 < len; i++) { area -= Math.abs(this.components[i].getGeodesicArea(projection)); } } return area; }, containsPoint: function(point) { var numRings = this.components.length; var contained = false; if (numRings > 0) { contained = this.components[0].containsPoint(point); if (contained !== 1) { if (contained && numRings > 1) { var hole; for (var i = 1; i < numRings; ++i) { hole = this.components[i].containsPoint(point); if (hole) { if (hole === 1) { contained = 1; } else { contained = false; } break; } } } } } return contained; }, 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" ) { for (i = 0, len = this.components.length; i < len; ++i) { intersect = geometry.intersects(this.components[i]); if (intersect) { break; } } if (!intersect) { for (i = 0, len = geometry.components.length; i < len; ++i) { intersect = this.containsPoint(geometry.components[i]); if (intersect) { break; } } } } else { for (i = 0, len = geometry.components.length; i < len; ++i) { intersect = this.intersects(geometry.components[i]); if (intersect) { break; } } } if (!intersect && geometry.CLASS_NAME == "OpenLayers.Geometry.Polygon") { var ring = this.components[0]; for (i = 0, len = ring.components.length; i < len; ++i) { intersect = geometry.containsPoint(ring.components[i]); if (intersect) { break; } } } return intersect; }, distanceTo: function(geometry, options) { var edge = !(options && options.edge === false); var result; 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" }); 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 < sides; ++i) { rotatedAngle = angle + (i * 2 * Math.PI) / sides; x = origin.x + radius * Math.cos(rotatedAngle); y = origin.y + radius * Math.sin(rotatedAngle); points.push(new OpenLayers.Geometry.Point(x, y)); } var ring = new OpenLayers.Geometry.LinearRing(points); return new OpenLayers.Geometry.Polygon([ring]); }; OpenLayers.Geometry.MultiPolygon = OpenLayers.Class( OpenLayers.Geometry.Collection, { componentTypes: ["OpenLayers.Geometry.Polygon"], CLASS_NAME: "OpenLayers.Geometry.MultiPolygon" } ); OpenLayers.Feature = OpenLayers.Class({ layer: null, id: null, lonlat: null, data: null, marker: null, popupClass: null, popup: null, initialize: function(layer, lonlat, data) { this.layer = layer; this.lonlat = lonlat; this.data = data != null ? data : {}; this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); }, destroy: function() { if (this.layer != null && this.layer.map != null) { if (this.popup != null) { this.layer.map.removePopup(this.popup); } } 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; } }, 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; }, createMarker: function() { if (this.lonlat != null) { this.marker = new OpenLayers.Marker(this.lonlat, this.data.icon); } return this.marker; }, destroyMarker: function() { this.marker.destroy(); }, 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; }, destroyPopup: function() { if (this.popup) { this.popup.feature = null; this.popup.destroy(); this.popup = null; } }, CLASS_NAME: "OpenLayers.Feature" }); OpenLayers.State = { UNKNOWN: "Unknown", INSERT: "Insert", UPDATE: "Update", DELETE: "Delete" }; OpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, { fid: null, geometry: null, attributes: null, bounds: null, state: null, style: null, url: null, renderIntent: "default", modified: null, 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; }, 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); }, clone: function() { return new OpenLayers.Feature.Vector( this.geometry ? this.geometry.clone() : null, this.attributes, this.style ); }, 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; }, 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()) ); }, createMarker: function() { return null; }, destroyMarker: function() {}, createPopup: function() { return null; }, atPoint: function(lonlat, toleranceLon, toleranceLat) { var atPoint = false; if (this.geometry) { atPoint = this.geometry.atPoint(lonlat, toleranceLon, toleranceLat); } return atPoint; }, destroyPopup: function() {}, move: function(location) { if (!this.layer || !this.geometry.move) { 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; }, 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: 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" }); 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 = OpenLayers.Class({ id: null, name: null, title: null, description: null, layerName: null, isDefault: false, rules: null, context: null, defaultStyle: null, defaultsPerSymbolizer: false, propertyStyles: null, initialize: function(style, options) { OpenLayers.Util.extend(this, options); this.rules = []; if (options && options.rules) { this.addRules(options.rules); } this.setDefaultStyle(style || OpenLayers.Feature.Vector.style["default"]); this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); }, destroy: function() { for (var i = 0, len = this.rules.length; i < len; i++) { this.rules[i].destroy(); this.rules[i] = null; } this.rules = null; this.defaultStyle = null; }, createSymbolizer: function(feature) { var style = this.defaultsPerSymbolizer ? {} : this.createLiterals( OpenLayers.Util.extend({}, this.defaultStyle), feature ); var rules = this.rules; var rule, context; var elseRules = []; var appliedRules = false; for (var i = 0, len = rules.length; i < len; i++) { rule = rules[i]; var applies = rule.evaluate(feature); if (applies) { if (rule instanceof OpenLayers.Rule && rule.elseFilter) { elseRules.push(rule); } else { appliedRules = true; this.applySymbolizer(rule, style, feature); } } } if (appliedRules == false && elseRules.length > 0) { appliedRules = true; for (var i = 0, len = elseRules.length; i < len; i++) { this.applySymbolizer(elseRules[i], style, feature); } } if (rules.length > 0 && appliedRules == false) { style.display = "none"; } if (style.label != null && typeof style.label !== "string") { style.label = String(style.label); } return style; }, 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 }); } } return this.createLiterals( OpenLayers.Util.extend(style, symbolizer), feature ); }, 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; }, findPropertyStyles: function() { var propertyStyles = {}; var style = this.defaultStyle; this.addPropertyStyles(propertyStyles, style); var rules = this.rules; var symbolizer, value; for (var i = 0, len = rules.length; i < len; i++) { symbolizer = rules[i].symbolizer; for (var key in symbolizer) { value = symbolizer[key]; if (typeof value == "object") { this.addPropertyStyles(propertyStyles, value); } else { this.addPropertyStyles(propertyStyles, symbolizer); break; } } } return propertyStyles; }, addPropertyStyles: function(propertyStyles, symbolizer) { var property; for (var key in symbolizer) { property = symbolizer[key]; if (typeof property == "string" && property.match(/\$\{\w+\}/)) { propertyStyles[key] = true; } } return propertyStyles; }, addRules: function(rules) { Array.prototype.push.apply(this.rules, rules); this.propertyStyles = this.findPropertyStyles(); }, setDefaultStyle: function(style) { this.defaultStyle = style; this.propertyStyles = this.findPropertyStyles(); }, getSymbolizerPrefix: function(geometry) { var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES; for (var i = 0, len = prefixes.length; i < len; i++) { if (geometry.CLASS_NAME.indexOf(prefixes[i]) != -1) { return prefixes[i]; } } }, clone: function() { var options = OpenLayers.Util.extend({}, this); if (this.rules) { options.rules = []; for (var i = 0, len = this.rules.length; i < len; ++i) { options.rules.push(this.rules[i].clone()); } } options.context = this.context && OpenLayers.Util.extend({}, this.context); var defaultStyle = OpenLayers.Util.extend({}, this.defaultStyle); return new OpenLayers.Style(defaultStyle, options); }, CLASS_NAME: "OpenLayers.Style" }); 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; }; OpenLayers.Style.SYMBOLIZER_PREFIXES = [ "Point", "Line", "Polygon", "Text", "Raster" ]; OpenLayers.Filter = OpenLayers.Class({ initialize: function(options) { OpenLayers.Util.extend(this, options); }, destroy: function() {}, evaluate: function(context) { return true; }, clone: function() { return null; }, 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.Spatial = OpenLayers.Class(OpenLayers.Filter, { type: null, property: null, value: null, distance: null, distanceUnits: null, 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; }, 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.Strategy.BBOX = OpenLayers.Class(OpenLayers.Strategy, { bounds: null, resolution: null, ratio: 2, resFactor: null, response: null, activate: function() { var activated = OpenLayers.Strategy.prototype.activate.call(this); if (activated) { this.layer.events.on({ moveend: this.update, refresh: this.update, visibilitychanged: this.update, scope: this }); this.update(); } return activated; }, deactivate: function() { var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this); if (deactivated) { this.layer.events.un({ moveend: this.update, refresh: this.update, visibilitychanged: this.update, scope: this }); } return deactivated; }, update: function(options) { var mapBounds = this.getMapBounds(); if ( mapBounds !== null && ((options && options.force) || (this.layer.visibility && this.layer.calculateInRange() && this.invalidBounds(mapBounds))) ) { this.calculateBounds(mapBounds); this.resolution = this.layer.map.getResolution(); this.triggerRead(options); } }, getMapBounds: function() { if (this.layer.map === null) { return null; } var bounds = this.layer.map.getExtent(); if ( bounds && !this.layer.projection.equals(this.layer.map.getProjectionObject()) ) { bounds = bounds .clone() .transform(this.layer.map.getProjectionObject(), this.layer.projection); } return bounds; }, invalidBounds: function(mapBounds) { if (!mapBounds) { mapBounds = this.getMapBounds(); } var invalid = !this.bounds || !this.bounds.containsBounds(mapBounds); if (!invalid && this.resFactor) { var ratio = this.resolution / this.layer.map.getResolution(); invalid = ratio >= this.resFactor || ratio <= 1 / this.resFactor; } return invalid; }, calculateBounds: function(mapBounds) { if (!mapBounds) { mapBounds = this.getMapBounds(); } var center = mapBounds.getCenterLonLat(); var dataWidth = mapBounds.getWidth() * this.ratio; var dataHeight = mapBounds.getHeight() * this.ratio; this.bounds = new OpenLayers.Bounds( center.lon - dataWidth / 2, center.lat - dataHeight / 2, center.lon + dataWidth / 2, center.lat + dataHeight / 2 ); }, triggerRead: function(options) { if (this.response && !(options && options.noAbort === true)) { this.layer.protocol.abort(this.response); this.layer.events.triggerEvent("loadend"); } this.layer.events.triggerEvent("loadstart"); this.response = this.layer.protocol.read( OpenLayers.Util.applyDefaults( { filter: this.createFilter(), callback: this.merge, scope: this }, options ) ); }, createFilter: function() { var filter = new OpenLayers.Filter.Spatial({ type: OpenLayers.Filter.Spatial.BBOX, value: this.bounds, projection: this.layer.projection }); if (this.layer.filter) { filter = new OpenLayers.Filter.Logical({ type: OpenLayers.Filter.Logical.AND, filters: [this.layer.filter, filter] }); } return filter; }, merge: function(resp) { this.layer.destroyFeatures(); var features = resp.features; if (features && features.length > 0) { var remote = this.layer.projection; var local = this.layer.map.getProjectionObject(); if (!local.equals(remote)) { var geom; for (var i = 0, len = features.length; i < len; ++i) { geom = features[i].geometry; if (geom) { geom.transform(remote, local); } } } this.layer.addFeatures(features); } this.response = null; this.layer.events.triggerEvent("loadend"); }, CLASS_NAME: "OpenLayers.Strategy.BBOX" }); OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, { EVENTMAP: { click: { in: "click", out: "clickout" }, mousemove: { in: "over", out: "out" }, dblclick: { in: "dblclick", out: null }, mousedown: { in: null, out: null }, mouseup: { in: null, out: null }, touchstart: { in: "click", out: "clickout" } }, feature: null, lastFeature: null, down: null, up: null, touch: false, clickTolerance: 4, geometryTypes: null, stopClick: true, stopDown: true, stopUp: false, initialize: function(control, layer, callbacks, options) { OpenLayers.Handler.prototype.initialize.apply(this, [ control, callbacks, options ]); this.layer = layer; }, touchstart: function(evt) { if (!this.touch) { this.touch = true; this.map.events.un({ mousedown: this.mousedown, mouseup: this.mouseup, mousemove: this.mousemove, click: this.click, dblclick: this.dblclick, scope: this }); } return OpenLayers.Event.isMultiTouch(evt) ? true : this.mousedown(evt); }, touchmove: function(evt) { OpenLayers.Event.stop(evt); }, mousedown: function(evt) { if ( OpenLayers.Event.isLeftClick(evt) || OpenLayers.Event.isSingleTouch(evt) ) { this.down = evt.xy; } return this.handle(evt) ? !this.stopDown : true; }, mouseup: function(evt) { this.up = evt.xy; return this.handle(evt) ? !this.stopUp : true; }, click: function(evt) { return this.handle(evt) ? !this.stopClick : true; }, mousemove: function(evt) { if (!this.callbacks["over"] && !this.callbacks["out"]) { return true; } this.handle(evt); return true; }, dblclick: function(evt) { return !this.handle(evt); }, geometryTypeMatches: function(feature) { return ( this.geometryTypes == null || OpenLayers.Util.indexOf(this.geometryTypes, feature.geometry.CLASS_NAME) > -1 ); }, handle: function(evt) { if (this.feature && !this.feature.layer) { this.feature = null; } var type = evt.type; var handled = false; var previouslyIn = !!this.feature; var click = type == "click" || type == "dblclick" || type == "touchstart"; this.feature = this.layer.getFeatureFromEvent(evt); if (this.feature && !this.feature.layer) { this.feature = null; } if (this.lastFeature && !this.lastFeature.layer) { this.lastFeature = null; } if (this.feature) { if (type === "touchstart") { OpenLayers.Event.stop(evt); } var inNew = this.feature != this.lastFeature; if (this.geometryTypeMatches(this.feature)) { if (previouslyIn && inNew) { if (this.lastFeature) { this.triggerCallback(type, "out", [this.lastFeature]); } this.triggerCallback(type, "in", [this.feature]); } else if (!previouslyIn || click) { this.triggerCallback(type, "in", [this.feature]); } this.lastFeature = this.feature; handled = true; } else { if (this.lastFeature && ((previouslyIn && inNew) || click)) { this.triggerCallback(type, "out", [this.lastFeature]); } this.feature = null; } } else { if (this.lastFeature && (previouslyIn || click)) { this.triggerCallback(type, "out", [this.lastFeature]); } } return handled; }, triggerCallback: function(type, mode, args) { var key = this.EVENTMAP[type][mode]; if (key) { if (type == "click" && this.up && this.down) { var dpx = Math.sqrt( Math.pow(this.up.x - this.down.x, 2) + Math.pow(this.up.y - this.down.y, 2) ); if (dpx <= this.clickTolerance) { this.callback(key, args); } } else { this.callback(key, args); } } }, activate: function() { var activated = false; if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) { this.moveLayerToTop(); this.map.events.on({ removelayer: this.handleMapEvents, changelayer: this.handleMapEvents, scope: this }); activated = true; } return activated; }, deactivate: function() { var deactivated = false; if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { this.moveLayerBack(); this.feature = null; this.lastFeature = null; this.down = null; this.up = null; this.touch = false; this.map.events.un({ removelayer: this.handleMapEvents, changelayer: this.handleMapEvents, scope: this }); deactivated = true; } return deactivated; }, handleMapEvents: function(evt) { if (evt.type == "removelayer" || evt.property == "order") { this.moveLayerToTop(); } }, moveLayerToTop: function() { var index = Math.max(this.map.Z_INDEX_BASE["Feature"] - 1, this.layer.getZIndex()) + 1; this.layer.setZIndex(index); }, 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.Handler.Feature" }); OpenLayers.StyleMap = OpenLayers.Class({ styles: null, extendDefault: true, initialize: function(style, options) { this.styles = { default: new OpenLayers.Style(OpenLayers.Feature.Vector.style["default"]), select: new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"]), temporary: new OpenLayers.Style( OpenLayers.Feature.Vector.style["temporary"] ), delete: new OpenLayers.Style(OpenLayers.Feature.Vector.style["delete"]) }; if (style instanceof OpenLayers.Style) { this.styles["default"] = style; this.styles["select"] = style; this.styles["temporary"] = style; this.styles["delete"] = style; } else if (typeof style == "object") { for (var key in style) { if (style[key] instanceof OpenLayers.Style) { this.styles[key] = style[key]; } else if (typeof style[key] == "object") { this.styles[key] = new OpenLayers.Style(style[key]); } else { this.styles["default"] = new OpenLayers.Style(style); this.styles["select"] = new OpenLayers.Style(style); this.styles["temporary"] = new OpenLayers.Style(style); this.styles["delete"] = new OpenLayers.Style(style); break; } } } OpenLayers.Util.extend(this, options); }, destroy: function() { for (var key in this.styles) { this.styles[key].destroy(); } this.styles = null; }, createSymbolizer: function(feature, intent) { if (!feature) { feature = new OpenLayers.Feature.Vector(); } if (!this.styles[intent]) { intent = "default"; } feature.renderIntent = intent; var defaultSymbolizer = {}; if (this.extendDefault && intent != "default") { defaultSymbolizer = this.styles["default"].createSymbolizer(feature); } return OpenLayers.Util.extend( defaultSymbolizer, this.styles[intent].createSymbolizer(feature) ); }, addUniqueValueRules: function(renderIntent, property, symbolizers, context) { var rules = []; for (var value in symbolizers) { rules.push( new OpenLayers.Rule({ symbolizer: symbolizers[value], context: context, filter: new OpenLayers.Filter.Comparison({ type: OpenLayers.Filter.Comparison.EQUAL_TO, property: property, value: value }) }) ); } this.styles[renderIntent].addRules(rules); }, CLASS_NAME: "OpenLayers.StyleMap" }); OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, { isBaseLayer: false, isFixed: false, features: null, filter: null, selectedFeatures: null, unrenderedFeatures: null, reportError: true, style: null, styleMap: null, strategies: null, protocol: null, renderers: ["SVG", "VML", "Canvas"], renderer: null, rendererOptions: null, geometryType: null, drawn: false, ratio: 1, initialize: function(name, options) { OpenLayers.Layer.prototype.initialize.apply(this, arguments); if (!this.renderer || !this.renderer.supported()) { this.assignRenderer(); } if (!this.renderer || !this.renderer.supported()) { this.renderer = null; this.displayError(); } if (!this.styleMap) { this.styleMap = new OpenLayers.StyleMap(); } this.features = []; this.selectedFeatures = []; this.unrenderedFeatures = {}; if (this.strategies) { for (var i = 0, len = this.strategies.length; i < len; i++) { this.strategies[i].setLayer(this); } } }, destroy: function() { if (this.strategies) { var strategy, i, len; for (i = 0, len = this.strategies.length; i < len; i++) { strategy = this.strategies[i]; if (strategy.autoDestroy) { strategy.destroy(); } } this.strategies = null; } if (this.protocol) { if (this.protocol.autoDestroy) { this.protocol.destroy(); } this.protocol = null; } this.destroyFeatures(); this.features = null; this.selectedFeatures = null; this.unrenderedFeatures = null; if (this.renderer) { this.renderer.destroy(); } this.renderer = null; this.geometryType = null; this.drawn = null; OpenLayers.Layer.prototype.destroy.apply(this, arguments); }, clone: function(obj) { if (obj == null) { obj = new OpenLayers.Layer.Vector(this.name, this.getOptions()); } obj = OpenLayers.Layer.prototype.clone.apply(this, [obj]); var features = this.features; var len = features.length; var clonedFeatures = new Array(len); for (var i = 0; i < len; ++i) { clonedFeatures[i] = features[i].clone(); } obj.features = clonedFeatures; return obj; }, refresh: function(obj) { if (this.calculateInRange() && this.visibility) { this.events.triggerEvent("refresh", obj); } }, assignRenderer: function() { for (var i = 0, len = this.renderers.length; i < len; i++) { var rendererClass = this.renderers[i]; var renderer = typeof rendererClass == "function" ? rendererClass : OpenLayers.Renderer[rendererClass]; if (renderer && renderer.prototype.supported()) { this.renderer = new renderer(this.div, this.rendererOptions); break; } } }, displayError: function() { if (this.reportError) { OpenLayers.Console.userError( OpenLayers.i18n("browserNotSupported", { renderers: this.renderers.join("\n") }) ); } }, setMap: function(map) { OpenLayers.Layer.prototype.setMap.apply(this, arguments); if (!this.renderer) { this.map.removeLayer(this); } else { this.renderer.map = this.map; var newSize = this.map.getSize(); newSize.w = newSize.w * this.ratio; newSize.h = newSize.h * this.ratio; this.renderer.setSize(newSize); } }, afterAdd: function() { if (this.strategies) { var strategy, i, len; for (i = 0, len = this.strategies.length; i < len; i++) { strategy = this.strategies[i]; if (strategy.autoActivate) { strategy.activate(); } } } }, removeMap: function(map) { this.drawn = false; if (this.strategies) { var strategy, i, len; for (i = 0, len = this.strategies.length; i < len; i++) { strategy = this.strategies[i]; if (strategy.autoActivate) { strategy.deactivate(); } } } }, onMapResize: function() { OpenLayers.Layer.prototype.onMapResize.apply(this, arguments); var newSize = this.map.getSize(); newSize.w = newSize.w * this.ratio; newSize.h = newSize.h * this.ratio; this.renderer.setSize(newSize); }, moveTo: function(bounds, zoomChanged, dragging) { OpenLayers.Layer.prototype.moveTo.apply(this, arguments); var coordSysUnchanged = true; if (!dragging) { this.renderer.root.style.visibility = "hidden"; var viewSize = this.map.getSize(), viewWidth = viewSize.w, viewHeight = viewSize.h, offsetLeft = (viewWidth / 2) * this.ratio - viewWidth / 2, offsetTop = (viewHeight / 2) * this.ratio - viewHeight / 2; offsetLeft += parseInt(this.map.layerContainerDiv.style.left, 10); offsetLeft = -Math.round(offsetLeft); offsetTop += parseInt(this.map.layerContainerDiv.style.top, 10); offsetTop = -Math.round(offsetTop); this.div.style.left = offsetLeft + "px"; this.div.style.top = offsetTop + "px"; var extent = this.map.getExtent().scale(this.ratio); coordSysUnchanged = this.renderer.setExtent(extent, zoomChanged); this.renderer.root.style.visibility = "visible"; if (OpenLayers.IS_GECKO === true) { this.div.scrollLeft = this.div.scrollLeft; } if (!zoomChanged && coordSysUnchanged) { for (var i in this.unrenderedFeatures) { var feature = this.unrenderedFeatures[i]; this.drawFeature(feature); } } } if (!this.drawn || zoomChanged || !coordSysUnchanged) { this.drawn = true; var feature; for (var i = 0, len = this.features.length; i < len; i++) { this.renderer.locked = i !== len - 1; feature = this.features[i]; this.drawFeature(feature); } } }, display: function(display) { OpenLayers.Layer.prototype.display.apply(this, arguments); var currentDisplay = this.div.style.display; if (currentDisplay != this.renderer.root.style.display) { this.renderer.root.style.display = currentDisplay; } }, addFeatures: function(features, options) { if (!OpenLayers.Util.isArray(features)) { features = [features]; } var notify = !options || !options.silent; if (notify) { var event = { features: features }; var ret = this.events.triggerEvent("beforefeaturesadded", event); if (ret === false) { return; } features = event.features; } var featuresAdded = []; for (var i = 0, len = features.length; i < len; i++) { if (i != features.length - 1) { this.renderer.locked = true; } else { this.renderer.locked = false; } var feature = features[i]; if ( this.geometryType && !(feature.geometry instanceof this.geometryType) ) { throw new TypeError( "addFeatures: component should be an " + this.geometryType.prototype.CLASS_NAME ); } feature.layer = this; if (!feature.style && this.style) { feature.style = OpenLayers.Util.extend({}, this.style); } if (notify) { if ( this.events.triggerEvent("beforefeatureadded", { feature: feature }) === false ) { continue; } this.preFeatureInsert(feature); } featuresAdded.push(feature); this.features.push(feature); this.drawFeature(feature); if (notify) { this.events.triggerEvent("featureadded", { feature: feature }); this.onFeatureInsert(feature); } } if (notify) { this.events.triggerEvent("featuresadded", { features: featuresAdded }); } }, removeFeatures: function(features, options) { if (!features || features.length === 0) { return; } if (features === this.features) { return this.removeAllFeatures(options); } if (!OpenLayers.Util.isArray(features)) { features = [features]; } if (features === this.selectedFeatures) { features = features.slice(); } var notify = !options || !options.silent; if (notify) { this.events.triggerEvent("beforefeaturesremoved", { features: features }); } for (var i = features.length - 1; i >= 0; i--) { if (i != 0 && features[i - 1].geometry) { this.renderer.locked = true; } else { this.renderer.locked = false; } var feature = features[i]; delete this.unrenderedFeatures[feature.id]; if (notify) { this.events.triggerEvent("beforefeatureremoved", { feature: feature }); } this.features = OpenLayers.Util.removeItem(this.features, feature); feature.layer = null; if (feature.geometry) { this.renderer.eraseFeatures(feature); } if (OpenLayers.Util.indexOf(this.selectedFeatures, feature) != -1) { OpenLayers.Util.removeItem(this.selectedFeatures, feature); } if (notify) { this.events.triggerEvent("featureremoved", { feature: feature }); } } if (notify) { this.events.triggerEvent("featuresremoved", { features: features }); } }, removeAllFeatures: function(options) { var notify = !options || !options.silent; var features = this.features; if (notify) { this.events.triggerEvent("beforefeaturesremoved", { features: features }); } var feature; for (var i = features.length - 1; i >= 0; i--) { feature = features[i]; if (notify) { this.events.triggerEvent("beforefeatureremoved", { feature: feature }); } feature.layer = null; if (notify) { this.events.triggerEvent("featureremoved", { feature: feature }); } } this.renderer.clear(); this.features = []; this.unrenderedFeatures = {}; this.selectedFeatures = []; if (notify) { this.events.triggerEvent("featuresremoved", { features: features }); } }, destroyFeatures: function(features, options) { var all = features == undefined; if (all) { features = this.features; } if (features) { this.removeFeatures(features, options); for (var i = features.length - 1; i >= 0; i--) { features[i].destroy(); } } }, drawFeature: function(feature, style) { if (!this.drawn) { return; } if (typeof style != "object") { if (!style && feature.state === OpenLayers.State.DELETE) { style = "delete"; } var renderIntent = style || feature.renderIntent; style = feature.style || this.style; if (!style) { style = this.styleMap.createSymbolizer(feature, renderIntent); } } var drawn = this.renderer.drawFeature(feature, style); if (drawn === false || drawn === null) { this.unrenderedFeatures[feature.id] = feature; } else { delete this.unrenderedFeatures[feature.id]; } }, eraseFeatures: function(features) { this.renderer.eraseFeatures(features); }, getFeatureFromEvent: function(evt) { if (!this.renderer) { throw new Error( "getFeatureFromEvent called on layer with no " + "renderer. This usually means you destroyed a " + "layer, but not some handler which is associated " + "with it." ); } var feature = null; var featureId = this.renderer.getFeatureIdFromEvent(evt); if (featureId) { if (typeof featureId === "string") { feature = this.getFeatureById(featureId); } else { feature = featureId; } } return feature; }, getFeatureBy: function(property, value) { var feature = null; for (var i = 0, len = this.features.length; i < len; ++i) { if (this.features[i][property] == value) { feature = this.features[i]; break; } } return feature; }, getFeatureById: function(featureId) { return this.getFeatureBy("id", featureId); }, getFeatureByFid: function(featureFid) { return this.getFeatureBy("fid", featureFid); }, getFeaturesByAttribute: function(attrName, attrValue) { var i, feature, len = this.features.length, foundFeatures = []; for (i = 0; i < len; i++) { feature = this.features[i]; if (feature && feature.attributes) { if (feature.attributes[attrName] === attrValue) { foundFeatures.push(feature); } } } return foundFeatures; }, onFeatureInsert: function(feature) {}, preFeatureInsert: function(feature) {}, getDataExtent: function() { var maxExtent = null; var features = this.features; if (features && features.length > 0) { var geometry = null; for (var i = 0, len = features.length; i < len; i++) { geometry = features[i].geometry; if (geometry) { if (maxExtent === null) { maxExtent = new OpenLayers.Bounds(); } maxExtent.extend(geometry.getBounds()); } } } return maxExtent; }, CLASS_NAME: "OpenLayers.Layer.Vector" }); OpenLayers.Layer.Vector.RootContainer = OpenLayers.Class( OpenLayers.Layer.Vector, { displayInLayerSwitcher: false, layers: null, display: function() {}, getFeatureFromEvent: function(evt) { var layers = this.layers; var feature; for (var i = 0; i < layers.length; i++) { feature = layers[i].getFeatureFromEvent(evt); if (feature) { return feature; } } }, setMap: function(map) { OpenLayers.Layer.Vector.prototype.setMap.apply(this, arguments); this.collectRoots(); map.events.register("changelayer", this, this.handleChangeLayer); }, removeMap: function(map) { map.events.unregister("changelayer", this, this.handleChangeLayer); this.resetRoots(); OpenLayers.Layer.Vector.prototype.removeMap.apply(this, arguments); }, collectRoots: function() { var layer; for (var i = 0; i < this.map.layers.length; ++i) { layer = this.map.layers[i]; if (OpenLayers.Util.indexOf(this.layers, layer) != -1) { layer.renderer.moveRoot(this.renderer); } } }, resetRoots: function() { var layer; for (var i = 0; i < this.layers.length; ++i) { layer = this.layers[i]; if (this.renderer && layer.renderer.getRenderLayerId() == this.id) { this.renderer.moveRoot(layer.renderer); } } }, handleChangeLayer: function(evt) { var layer = evt.layer; if ( evt.property == "order" && OpenLayers.Util.indexOf(this.layers, layer) != -1 ) { this.resetRoots(); this.collectRoots(); } }, CLASS_NAME: "OpenLayers.Layer.Vector.RootContainer" } ); OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, { multipleKey: null, toggleKey: null, multiple: false, clickout: true, toggle: false, hover: false, highlightOnly: false, box: false, onBeforeSelect: function() {}, onSelect: function() {}, onUnselect: function() {}, scope: null, geometryTypes: null, layer: null, layers: null, callbacks: null, selectStyle: null, renderIntent: "select", handlers: null, initialize: function(layers, options) { OpenLayers.Control.prototype.initialize.apply(this, [options]); if (this.scope === null) { this.scope = this; } this.initLayer(layers); var callbacks = { click: this.clickFeature, clickout: this.clickoutFeature }; if (this.hover) { callbacks.over = this.overFeature; callbacks.out = this.outFeature; } this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks); this.handlers = { feature: new OpenLayers.Handler.Feature( this, this.layer, this.callbacks, { geometryTypes: this.geometryTypes } ) }; if (this.box) { this.handlers.box = new OpenLayers.Handler.Box( this, { done: this.selectBox }, { boxDivClassName: "olHandlerBoxSelectFeature" } ); } }, initLayer: function(layers) { if (OpenLayers.Util.isArray(layers)) { this.layers = layers; this.layer = new OpenLayers.Layer.Vector.RootContainer( this.id + "_container", { layers: layers } ); } else { this.layer = layers; } }, destroy: function() { if (this.active && this.layers) { this.map.removeLayer(this.layer); } OpenLayers.Control.prototype.destroy.apply(this, arguments); if (this.layers) { this.layer.destroy(); } }, activate: function() { if (!this.active) { if (this.layers) { this.map.addLayer(this.layer); } this.handlers.feature.activate(); if (this.box && this.handlers.box) { this.handlers.box.activate(); } } return OpenLayers.Control.prototype.activate.apply(this, arguments); }, deactivate: function() { if (this.active) { this.handlers.feature.deactivate(); if (this.handlers.box) { this.handlers.box.deactivate(); } if (this.layers) { this.map.removeLayer(this.layer); } } return OpenLayers.Control.prototype.deactivate.apply(this, arguments); }, unselectAll: function(options) { var layers = this.layers || [this.layer]; var layer, feature; for (var l = 0; l < layers.length; ++l) { layer = layers[l]; for (var i = layer.selectedFeatures.length - 1; i >= 0; --i) { feature = layer.selectedFeatures[i]; if (!options || options.except != feature) { this.unselect(feature); } } } }, clickFeature: function(feature) { if (!this.hover) { var selected = OpenLayers.Util.indexOf(feature.layer.selectedFeatures, feature) > -1; if (selected) { if (this.toggleSelect()) { this.unselect(feature); } else if (!this.multipleSelect()) { this.unselectAll({ except: feature }); } } else { if (!this.multipleSelect()) { this.unselectAll({ except: feature }); } this.select(feature); } } }, multipleSelect: function() { return ( this.multiple || (this.handlers.feature.evt && this.handlers.feature.evt[this.multipleKey]) ); }, toggleSelect: function() { return ( this.toggle || (this.handlers.feature.evt && this.handlers.feature.evt[this.toggleKey]) ); }, clickoutFeature: function(feature) { if (!this.hover && this.clickout) { this.unselectAll(); } }, overFeature: function(feature) { var layer = feature.layer; if (this.hover) { if (this.highlightOnly) { this.highlight(feature); } else if ( OpenLayers.Util.indexOf(layer.selectedFeatures, feature) == -1 ) { this.select(feature); } } }, outFeature: function(feature) { if (this.hover) { if (this.highlightOnly) { if (feature._lastHighlighter == this.id) { if (feature._prevHighlighter && feature._prevHighlighter != this.id) { delete feature._lastHighlighter; var control = this.map.getControl(feature._prevHighlighter); if (control) { control.highlight(feature); } } else { this.unhighlight(feature); } } } else { this.unselect(feature); } } }, highlight: function(feature) { var layer = feature.layer; var cont = this.events.triggerEvent("beforefeaturehighlighted", { feature: feature }); if (cont !== false) { feature._prevHighlighter = feature._lastHighlighter; feature._lastHighlighter = this.id; var style = this.selectStyle || this.renderIntent; layer.drawFeature(feature, style); this.events.triggerEvent("featurehighlighted", { feature: feature }); } }, unhighlight: function(feature) { var layer = feature.layer; if (feature._prevHighlighter == undefined) { delete feature._lastHighlighter; } else if (feature._prevHighlighter == this.id) { delete feature._prevHighlighter; } else { feature._lastHighlighter = feature._prevHighlighter; delete feature._prevHighlighter; } layer.drawFeature( feature, feature.style || feature.layer.style || "default" ); this.events.triggerEvent("featureunhighlighted", { feature: feature }); }, select: function(feature) { var cont = this.onBeforeSelect.call(this.scope, feature); var layer = feature.layer; if (cont !== false) { cont = layer.events.triggerEvent("beforefeatureselected", { feature: feature }); if (cont !== false) { layer.selectedFeatures.push(feature); this.highlight(feature); if (!this.handlers.feature.lastFeature) { this.handlers.feature.lastFeature = layer.selectedFeatures[0]; } layer.events.triggerEvent("featureselected", { feature: feature }); this.onSelect.call(this.scope, feature); } } }, unselect: function(feature) { var layer = feature.layer; this.unhighlight(feature); OpenLayers.Util.removeItem(layer.selectedFeatures, feature); layer.events.triggerEvent("featureunselected", { feature: feature }); this.onUnselect.call(this.scope, feature); }, selectBox: function(position) { if (position instanceof OpenLayers.Bounds) { var minXY = this.map.getLonLatFromPixel({ x: position.left, y: position.bottom }); var maxXY = this.map.getLonLatFromPixel({ x: position.right, y: position.top }); var bounds = new OpenLayers.Bounds( minXY.lon, minXY.lat, maxXY.lon, maxXY.lat ); if (!this.multipleSelect()) { this.unselectAll(); } var prevMultiple = this.multiple; this.multiple = true; var layers = this.layers || [this.layer]; this.events.triggerEvent("boxselectionstart", { layers: layers }); var layer; for (var l = 0; l < layers.length; ++l) { layer = layers[l]; for (var i = 0, len = layer.features.length; i < len; ++i) { var feature = layer.features[i]; if (!feature.getVisibility()) { continue; } if ( this.geometryTypes == null || OpenLayers.Util.indexOf( this.geometryTypes, feature.geometry.CLASS_NAME ) > -1 ) { if (bounds.toGeometry().intersects(feature.geometry)) { if ( OpenLayers.Util.indexOf(layer.selectedFeatures, feature) == -1 ) { this.select(feature); } } } } } this.multiple = prevMultiple; this.events.triggerEvent("boxselectionend", { layers: layers }); } }, setMap: function(map) { this.handlers.feature.setMap(map); if (this.box) { this.handlers.box.setMap(map); } OpenLayers.Control.prototype.setMap.apply(this, arguments); }, setLayer: function(layers) { var isActive = this.active; this.unselectAll(); this.deactivate(); if (this.layers) { this.layer.destroy(); this.layers = null; } this.initLayer(layers); this.handlers.feature.layer = this.layer; if (isActive) { this.activate(); } }, CLASS_NAME: "OpenLayers.Control.SelectFeature" }); OpenLayers.Control.Attribution = OpenLayers.Class(OpenLayers.Control, { separator: ", ", template: "${layers}", destroy: function() { this.map.events.un({ removelayer: this.updateAttribution, addlayer: this.updateAttribution, changelayer: this.updateAttribution, changebaselayer: this.updateAttribution, scope: this }); OpenLayers.Control.prototype.destroy.apply(this, arguments); }, draw: function() { OpenLayers.Control.prototype.draw.apply(this, arguments); this.map.events.on({ changebaselayer: this.updateAttribution, changelayer: this.updateAttribution, addlayer: this.updateAttribution, removelayer: this.updateAttribution, scope: this }); this.updateAttribution(); return this.div; }, updateAttribution: function() { var attributions = []; if (this.map && this.map.layers) { for (var i = 0, len = this.map.layers.length; i < len; i++) { var layer = this.map.layers[i]; if (layer.attribution && layer.getVisibility()) { if (OpenLayers.Util.indexOf(attributions, layer.attribution) === -1) { attributions.push(layer.attribution); } } } this.div.innerHTML = OpenLayers.String.format(this.template, { layers: attributions.join(this.separator) }); } }, CLASS_NAME: "OpenLayers.Control.Attribution" }); OpenLayers.Kinetic = OpenLayers.Class({ threshold: 0, deceleration: 0.0035, nbPoints: 100, delay: 200, points: undefined, timerId: undefined, initialize: function(options) { OpenLayers.Util.extend(this, options); }, begin: function() { OpenLayers.Animation.stop(this.timerId); this.timerId = undefined; this.points = []; }, update: function(xy) { this.points.unshift({ xy: xy, tick: new Date().getTime() }); if (this.points.length > this.nbPoints) { this.points.pop(); } }, end: function(xy) { var last, now = new Date().getTime(); for (var i = 0, l = this.points.length, point; i < l; i++) { point = this.points[i]; if (now - point.tick > this.delay) { break; } last = point; } if (!last) { return; } var time = new Date().getTime() - last.tick; var dist = Math.sqrt( Math.pow(xy.x - last.xy.x, 2) + Math.pow(xy.y - last.xy.y, 2) ); var speed = dist / time; if (speed == 0 || speed < this.threshold) { return; } var theta = Math.asin((xy.y - last.xy.y) / dist); if (last.xy.x <= xy.x) { theta = Math.PI - theta; } return { speed: speed, theta: theta }; }, move: function(info, callback) { var v0 = info.speed; var fx = Math.cos(info.theta); var fy = -Math.sin(info.theta); var initialTime = new Date().getTime(); var lastX = 0; var lastY = 0; var timerCallback = function() { if (this.timerId == null) { return; } var t = new Date().getTime() - initialTime; var p = (-this.deceleration * Math.pow(t, 2)) / 2.0 + v0 * t; var x = p * fx; var y = p * fy; var args = {}; args.end = false; var v = -this.deceleration * t + v0; if (v <= 0) { OpenLayers.Animation.stop(this.timerId); this.timerId = null; args.end = true; } args.x = x - lastX; args.y = y - lastY; lastX = x; lastY = y; callback(args.x, args.y, args.end); }; this.timerId = OpenLayers.Animation.start( OpenLayers.Function.bind(timerCallback, this) ); }, CLASS_NAME: "OpenLayers.Kinetic" }); OpenLayers.Filter.Logical = OpenLayers.Class(OpenLayers.Filter, { filters: null, type: null, initialize: function(options) { this.filters = []; OpenLayers.Filter.prototype.initialize.apply(this, [options]); }, destroy: function() { this.filters = null; OpenLayers.Filter.prototype.destroy.apply(this); }, evaluate: function(context) { var i, len; switch (this.type) { case OpenLayers.Filter.Logical.AND: for (i = 0, len = this.filters.length; i < len; i++) { if (this.filters[i].evaluate(context) == false) { return false; } } return true; case OpenLayers.Filter.Logical.OR: for (i = 0, len = this.filters.length; i < len; i++) { if (this.filters[i].evaluate(context) == true) { return true; } } return false; case OpenLayers.Filter.Logical.NOT: return !this.filters[0].evaluate(context); } return undefined; }, clone: function() { var filters = []; for (var i = 0, len = this.filters.length; i < len; ++i) { filters.push(this.filters[i].clone()); } return new OpenLayers.Filter.Logical({ type: this.type, filters: filters }); }, CLASS_NAME: "OpenLayers.Filter.Logical" }); OpenLayers.Filter.Logical.AND = "&&"; OpenLayers.Filter.Logical.OR = "||"; OpenLayers.Filter.Logical.NOT = "!"; OpenLayers.Handler.Drag = OpenLayers.Class(OpenLayers.Handler, { started: false, stopDown: true, dragging: false, touch: false, last: null, start: null, lastMoveEvt: null, oldOnselectstart: null, interval: 0, timeoutId: null, documentDrag: false, documentEvents: null, 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 } }); }; } }, 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]); OpenLayers.Event.stop(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; }, 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); 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; }, 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; }, down: function(evt) {}, move: function(evt) {}, up: function(evt) {}, out: function(evt) {}, mousedown: function(evt) { return this.dragstart(evt); }, touchstart: function(evt) { if (!this.touch) { this.touch = true; this.map.events.un({ mousedown: this.mousedown, mouseup: this.mouseup, mousemove: this.mousemove, click: this.click, scope: this }); } return this.dragstart(evt); }, mousemove: function(evt) { return this.dragmove(evt); }, touchmove: function(evt) { return this.dragmove(evt); }, removeTimeout: function() { this.timeoutId = null; if (this.dragging) { this.mousemove(this.lastMoveEvt); } }, mouseup: function(evt) { return this.dragend(evt); }, touchend: function(evt) { evt.xy = this.last; return this.dragend(evt); }, 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; }, click: function(evt) { return this.start == this.last; }, activate: function() { var activated = false; if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) { this.dragging = false; activated = true; } return activated; }, deactivate: function() { var deactivated = false; if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { this.touch = false; this.started = false; this.dragging = false; this.start = null; this.last = null; deactivated = true; OpenLayers.Element.removeClass(this.map.viewPortDiv, "olDragDown"); } return deactivated; }, adjustXY: function(evt) { var pos = OpenLayers.Util.pagePosition(this.map.viewPortDiv); evt.xy.x -= pos[0]; evt.xy.y -= pos[1]; }, 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); }, removeDocumentEvents: function() { OpenLayers.Element.removeClass(document.body, "olDragDown"); this.documentEvents = false; OpenLayers.Event.stopObserving(document, "mousemove", this._docMove); OpenLayers.Event.stopObserving(document, "mouseup", this._docUp); }, CLASS_NAME: "OpenLayers.Handler.Drag" }); OpenLayers.Handler.Box = OpenLayers.Class(OpenLayers.Handler, { dragHandler: null, boxDivClassName: "olHandlerBoxZoomBox", boxOffsets: null, initialize: function(control, callbacks, options) { OpenLayers.Handler.prototype.initialize.apply(this, arguments); this.dragHandler = new OpenLayers.Handler.Drag( this, { down: this.startBox, move: this.moveBox, out: this.removeBox, up: this.endBox }, { keyMask: this.keyMask } ); }, destroy: function() { OpenLayers.Handler.prototype.destroy.apply(this, arguments); if (this.dragHandler) { this.dragHandler.destroy(); this.dragHandler = null; } }, setMap: function(map) { OpenLayers.Handler.prototype.setMap.apply(this, arguments); if (this.dragHandler) { this.dragHandler.setMap(map); } }, startBox: function(xy) { this.callback("start", []); this.zoomBox = OpenLayers.Util.createDiv("zoomBox", { x: -9999, y: -9999 }); this.zoomBox.className = this.boxDivClassName; this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; this.map.viewPortDiv.appendChild(this.zoomBox); OpenLayers.Element.addClass(this.map.viewPortDiv, "olDrawBox"); }, moveBox: function(xy) { var startX = this.dragHandler.start.x; var startY = this.dragHandler.start.y; var deltaX = Math.abs(startX - xy.x); var deltaY = Math.abs(startY - xy.y); var offset = this.getBoxOffsets(); this.zoomBox.style.width = deltaX + offset.width + 1 + "px"; this.zoomBox.style.height = deltaY + offset.height + 1 + "px"; this.zoomBox.style.left = (xy.x < startX ? startX - deltaX - offset.left : startX - offset.left) + "px"; this.zoomBox.style.top = (xy.y < startY ? startY - deltaY - offset.top : startY - offset.top) + "px"; }, endBox: function(end) { var result; if ( Math.abs(this.dragHandler.start.x - end.x) > 5 || Math.abs(this.dragHandler.start.y - end.y) > 5 ) { var start = this.dragHandler.start; var top = Math.min(start.y, end.y); var bottom = Math.max(start.y, end.y); var left = Math.min(start.x, end.x); var right = Math.max(start.x, end.x); result = new OpenLayers.Bounds(left, bottom, right, top); } else { result = this.dragHandler.start.clone(); } this.removeBox(); this.callback("done", [result]); }, removeBox: function() { this.map.viewPortDiv.removeChild(this.zoomBox); this.zoomBox = null; this.boxOffsets = null; OpenLayers.Element.removeClass(this.map.viewPortDiv, "olDrawBox"); }, activate: function() { if (OpenLayers.Handler.prototype.activate.apply(this, arguments)) { this.dragHandler.activate(); return true; } else { return false; } }, deactivate: function() { if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { if (this.dragHandler.deactivate()) { if (this.zoomBox) { this.removeBox(); } } return true; } else { return false; } }, getBoxOffsets: function() { if (!this.boxOffsets) { var testDiv = document.createElement("div"); testDiv.style.position = "absolute"; testDiv.style.border = "1px solid black"; testDiv.style.width = "3px"; document.body.appendChild(testDiv); var w3cBoxModel = testDiv.clientWidth == 3; document.body.removeChild(testDiv); var left = parseInt( OpenLayers.Element.getStyle(this.zoomBox, "border-left-width") ); var right = parseInt( OpenLayers.Element.getStyle(this.zoomBox, "border-right-width") ); var top = parseInt( OpenLayers.Element.getStyle(this.zoomBox, "border-top-width") ); var bottom = parseInt( OpenLayers.Element.getStyle(this.zoomBox, "border-bottom-width") ); this.boxOffsets = { left: left, right: right, top: top, bottom: bottom, width: w3cBoxModel === false ? left + right : 0, height: w3cBoxModel === false ? top + bottom : 0 }; } return this.boxOffsets; }, CLASS_NAME: "OpenLayers.Handler.Box" }); OpenLayers.Control.ZoomBox = OpenLayers.Class(OpenLayers.Control, { type: OpenLayers.Control.TYPE_TOOL, out: false, keyMask: null, alwaysZoom: false, draw: function() { this.handler = new OpenLayers.Handler.Box( this, { done: this.zoomBox }, { keyMask: this.keyMask } ); }, zoomBox: function(position) { if (position instanceof OpenLayers.Bounds) { var bounds; if (!this.out) { var minXY = this.map.getLonLatFromPixel({ x: position.left, y: position.bottom }); var maxXY = this.map.getLonLatFromPixel({ x: position.right, y: position.top }); bounds = new OpenLayers.Bounds( minXY.lon, minXY.lat, maxXY.lon, maxXY.lat ); } else { var pixWidth = Math.abs(position.right - position.left); var pixHeight = Math.abs(position.top - position.bottom); var zoomFactor = Math.min( this.map.size.h / pixHeight, this.map.size.w / pixWidth ); var extent = this.map.getExtent(); var center = this.map.getLonLatFromPixel(position.getCenterPixel()); var xmin = center.lon - (extent.getWidth() / 2) * zoomFactor; var xmax = center.lon + (extent.getWidth() / 2) * zoomFactor; var ymin = center.lat - (extent.getHeight() / 2) * zoomFactor; var ymax = center.lat + (extent.getHeight() / 2) * zoomFactor; bounds = new OpenLayers.Bounds(xmin, ymin, xmax, ymax); } var lastZoom = this.map.getZoom(); this.map.zoomToExtent(bounds); if (lastZoom == this.map.getZoom() && this.alwaysZoom == true) { this.map.zoomTo(lastZoom + (this.out ? -1 : 1)); } } else { if (!this.out) { this.map.setCenter( this.map.getLonLatFromPixel(position), this.map.getZoom() + 1 ); } else { this.map.setCenter( this.map.getLonLatFromPixel(position), this.map.getZoom() - 1 ); } } }, CLASS_NAME: "OpenLayers.Control.ZoomBox" }); OpenLayers.Control.DragPan = OpenLayers.Class(OpenLayers.Control, { type: OpenLayers.Control.TYPE_TOOL, panned: false, interval: 1, documentDrag: false, kinetic: null, enableKinetic: false, kineticInterval: 10, draw: function() { if (this.enableKinetic) { var config = { interval: this.kineticInterval }; if (typeof this.enableKinetic === "object") { config = OpenLayers.Util.extend(config, this.enableKinetic); } this.kinetic = new OpenLayers.Kinetic(config); } this.handler = new OpenLayers.Handler.Drag( this, { move: this.panMap, done: this.panMapDone, down: this.panMapStart }, { interval: this.interval, documentDrag: this.documentDrag } ); }, panMapStart: function() { if (this.kinetic) { this.kinetic.begin(); } }, panMap: function(xy) { if (this.kinetic) { this.kinetic.update(xy); } this.panned = true; this.map.pan(this.handler.last.x - xy.x, this.handler.last.y - xy.y, { dragging: true, animate: false }); }, panMapDone: function(xy) { if (this.panned) { var res = null; if (this.kinetic) { res = this.kinetic.end(xy); } this.map.pan(this.handler.last.x - xy.x, this.handler.last.y - xy.y, { dragging: !!res, animate: false }); if (res) { var self = this; this.kinetic.move(res, function(x, y, end) { self.map.pan(x, y, { dragging: !end, animate: false }); }); } this.panned = false; } }, CLASS_NAME: "OpenLayers.Control.DragPan" }); OpenLayers.Handler.Click = OpenLayers.Class(OpenLayers.Handler, { delay: 300, single: true, double: false, pixelTolerance: 0, dblclickTolerance: 13, stopSingle: false, stopDouble: false, timerId: null, touch: false, down: null, last: null, first: null, rightclickTimerId: null, touchstart: function(evt) { if (!this.touch) { this.unregisterMouseListeners(); this.touch = true; } this.down = this.getEventInfo(evt); this.last = this.getEventInfo(evt); return true; }, touchmove: function(evt) { this.last = this.getEventInfo(evt); return true; }, touchend: function(evt) { if (this.down) { evt.xy = this.last.xy; evt.lastTouches = this.last.touches; this.handleSingle(evt); this.down = null; } return true; }, unregisterMouseListeners: function() { this.map.events.un({ mousedown: this.mousedown, mouseup: this.mouseup, click: this.click, dblclick: this.dblclick, scope: this }); }, mousedown: function(evt) { this.down = this.getEventInfo(evt); this.last = this.getEventInfo(evt); return true; }, mouseup: function(evt) { var propagate = true; if ( this.checkModifiers(evt) && this.control.handleRightClicks && OpenLayers.Event.isRightClick(evt) ) { propagate = this.rightclick(evt); } return propagate; }, rightclick: function(evt) { if (this.passesTolerance(evt)) { if (this.rightclickTimerId != null) { this.clearTimer(); this.callback("dblrightclick", [evt]); return !this.stopDouble; } else { var clickEvent = this["double"] ? OpenLayers.Util.extend({}, evt) : this.callback("rightclick", [evt]); var delayedRightCall = OpenLayers.Function.bind( this.delayedRightCall, this, clickEvent ); this.rightclickTimerId = window.setTimeout( delayedRightCall, this.delay ); } } return !this.stopSingle; }, delayedRightCall: function(evt) { this.rightclickTimerId = null; if (evt) { this.callback("rightclick", [evt]); } }, click: function(evt) { if (!this.last) { this.last = this.getEventInfo(evt); } this.handleSingle(evt); return !this.stopSingle; }, dblclick: function(evt) { this.handleDouble(evt); return !this.stopDouble; }, handleDouble: function(evt) { if (this.passesDblclickTolerance(evt)) { if (this["double"]) { this.callback("dblclick", [evt]); } this.clearTimer(); } }, handleSingle: function(evt) { if (this.passesTolerance(evt)) { if (this.timerId != null) { if (this.last.touches && this.last.touches.length === 1) { if (this["double"]) { OpenLayers.Event.stop(evt); } this.handleDouble(evt); } if (!this.last.touches || this.last.touches.length !== 2) { this.clearTimer(); } } else { this.first = this.getEventInfo(evt); var clickEvent = this.single ? OpenLayers.Util.extend({}, evt) : null; this.queuePotentialClick(clickEvent); } } }, queuePotentialClick: function(evt) { this.timerId = window.setTimeout( OpenLayers.Function.bind(this.delayedCall, this, evt), this.delay ); }, passesTolerance: function(evt) { var passes = true; if (this.pixelTolerance != null && this.down && this.down.xy) { passes = this.pixelTolerance >= this.down.xy.distanceTo(evt.xy); if ( passes && this.touch && this.down.touches.length === this.last.touches.length ) { for (var i = 0, ii = this.down.touches.length; i < ii; ++i) { if ( this.getTouchDistance(this.down.touches[i], this.last.touches[i]) > this.pixelTolerance ) { passes = false; break; } } } } return passes; }, getTouchDistance: function(from, to) { return Math.sqrt( Math.pow(from.clientX - to.clientX, 2) + Math.pow(from.clientY - to.clientY, 2) ); }, passesDblclickTolerance: function(evt) { var passes = true; if (this.down && this.first) { passes = this.down.xy.distanceTo(this.first.xy) <= this.dblclickTolerance; } return passes; }, clearTimer: function() { if (this.timerId != null) { window.clearTimeout(this.timerId); this.timerId = null; } if (this.rightclickTimerId != null) { window.clearTimeout(this.rightclickTimerId); this.rightclickTimerId = null; } }, delayedCall: function(evt) { this.timerId = null; if (evt) { this.callback("click", [evt]); } }, getEventInfo: function(evt) { var touches; if (evt.touches) { var len = evt.touches.length; touches = new Array(len); var touch; for (var i = 0; i < len; i++) { touch = evt.touches[i]; touches[i] = { clientX: touch.clientX, clientY: touch.clientY }; } } return { xy: evt.xy, touches: touches }; }, deactivate: function() { var deactivated = false; if (OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) { this.clearTimer(); this.down = null; this.first = null; this.last = null; this.touch = false; deactivated = true; } return deactivated; }, CLASS_NAME: "OpenLayers.Handler.Click" }); OpenLayers.Control.Navigation = OpenLayers.Class(OpenLayers.Control, { dragPan: null, dragPanOptions: null, pinchZoom: null, pinchZoomOptions: null, documentDrag: false, zoomBox: null, zoomBoxEnabled: true, zoomWheelEnabled: true, mouseWheelOptions: null, handleRightClicks: false, zoomBoxKeyMask: OpenLayers.Handler.MOD_SHIFT, autoActivate: true, initialize: function(options) { this.handlers = {}; OpenLayers.Control.prototype.initialize.apply(this, arguments); }, destroy: function() { this.deactivate(); if (this.dragPan) { this.dragPan.destroy(); } this.dragPan = null; if (this.zoomBox) { this.zoomBox.destroy(); } this.zoomBox = null; if (this.pinchZoom) { this.pinchZoom.destroy(); } this.pinchZoom = null; OpenLayers.Control.prototype.destroy.apply(this, arguments); }, activate: function() { this.dragPan.activate(); if (this.zoomWheelEnabled) { this.handlers.wheel.activate(); } this.handlers.click.activate(); if (this.zoomBoxEnabled) { this.zoomBox.activate(); } if (this.pinchZoom) { this.pinchZoom.activate(); } return OpenLayers.Control.prototype.activate.apply(this, arguments); }, deactivate: function() { if (this.pinchZoom) { this.pinchZoom.deactivate(); } this.zoomBox.deactivate(); this.dragPan.deactivate(); this.handlers.click.deactivate(); this.handlers.wheel.deactivate(); return OpenLayers.Control.prototype.deactivate.apply(this, arguments); }, draw: function() { if (this.handleRightClicks) { this.map.viewPortDiv.oncontextmenu = OpenLayers.Function.False; } var clickCallbacks = { click: this.defaultClick, dblclick: this.defaultDblClick, dblrightclick: this.defaultDblRightClick }; var clickOptions = { double: true, stopDouble: true }; this.handlers.click = new OpenLayers.Handler.Click( this, clickCallbacks, clickOptions ); this.dragPan = new OpenLayers.Control.DragPan( OpenLayers.Util.extend( { map: this.map, documentDrag: this.documentDrag }, this.dragPanOptions ) ); this.zoomBox = new OpenLayers.Control.ZoomBox({ map: this.map, keyMask: this.zoomBoxKeyMask }); this.dragPan.draw(); this.zoomBox.draw(); this.handlers.wheel = new OpenLayers.Handler.MouseWheel( this, { up: this.wheelUp, down: this.wheelDown }, this.mouseWheelOptions ); if (OpenLayers.Control.PinchZoom) { this.pinchZoom = new OpenLayers.Control.PinchZoom( OpenLayers.Util.extend({ map: this.map }, this.pinchZoomOptions) ); } }, defaultClick: function(evt) { if (evt.lastTouches && evt.lastTouches.length == 2) { this.map.zoomOut(); } }, defaultDblClick: function(evt) { var newCenter = this.map.getLonLatFromViewPortPx(evt.xy); this.map.setCenter(newCenter, this.map.zoom + 1); }, defaultDblRightClick: function(evt) { var newCenter = this.map.getLonLatFromViewPortPx(evt.xy); this.map.setCenter(newCenter, this.map.zoom - 1); }, wheelChange: function(evt, deltaZ) { var currentZoom = this.map.getZoom(); var newZoom = this.map.getZoom() + Math.round(deltaZ); newZoom = Math.max(newZoom, 0); newZoom = Math.min(newZoom, this.map.getNumZoomLevels()); if (newZoom === currentZoom) { return; } var size = this.map.getSize(); var deltaX = size.w / 2 - evt.xy.x; var deltaY = evt.xy.y - size.h / 2; var newRes = this.map.baseLayer.getResolutionForZoom(newZoom); var zoomPoint = this.map.getLonLatFromPixel(evt.xy); var newCenter = new OpenLayers.LonLat( zoomPoint.lon + deltaX * newRes, zoomPoint.lat + deltaY * newRes ); this.map.setCenter(newCenter, newZoom); }, wheelUp: function(evt, delta) { this.wheelChange(evt, delta || 1); }, wheelDown: function(evt, delta) { this.wheelChange(evt, delta || -1); }, disableZoomBox: function() { this.zoomBoxEnabled = false; this.zoomBox.deactivate(); }, enableZoomBox: function() { this.zoomBoxEnabled = true; if (this.active) { this.zoomBox.activate(); } }, disableZoomWheel: function() { this.zoomWheelEnabled = false; this.handlers.wheel.deactivate(); }, enableZoomWheel: function() { this.zoomWheelEnabled = true; if (this.active) { this.handlers.wheel.activate(); } }, CLASS_NAME: "OpenLayers.Control.Navigation" }); OpenLayers.Layer.WMS = OpenLayers.Class(OpenLayers.Layer.Grid, { DEFAULT_PARAMS: { service: "WMS", version: "1.1.1", request: "GetMap", styles: "", format: "image/jpeg" }, isBaseLayer: true, encodeBBOX: false, noMagic: false, yx: {}, initialize: function(name, url, params, options) { var newArguments = []; params = OpenLayers.Util.upperCaseObject(params); if (parseFloat(params.VERSION) >= 1.3 && !params.EXCEPTIONS) { params.EXCEPTIONS = "INIMAGE"; } newArguments.push(name, url, params, options); OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments); OpenLayers.Util.applyDefaults( this.params, OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS) ); if ( !this.noMagic && this.params.TRANSPARENT && this.params.TRANSPARENT.toString().toLowerCase() == "true" ) { if (options == null || !options.isBaseLayer) { this.isBaseLayer = false; } if (this.params.FORMAT == "image/jpeg") { this.params.FORMAT = OpenLayers.Util.alphaHack() ? "image/gif" : "image/png"; } } }, clone: function(obj) { if (obj == null) { obj = new OpenLayers.Layer.WMS( this.name, this.url, this.params, this.getOptions() ); } obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]); return obj; }, reverseAxisOrder: function() { var projCode = this.projection.getCode(); return ( parseFloat(this.params.VERSION) >= 1.3 && !!(this.yx[projCode] || OpenLayers.Projection.defaults[projCode].yx) ); }, getURL: function(bounds) { bounds = this.adjustBounds(bounds); var imageSize = this.getImageSize(); var newParams = {}; var reverseAxisOrder = this.reverseAxisOrder(); newParams.BBOX = this.encodeBBOX ? bounds.toBBOX(null, reverseAxisOrder) : bounds.toArray(reverseAxisOrder); newParams.WIDTH = imageSize.w; newParams.HEIGHT = imageSize.h; var requestString = this.getFullRequestString(newParams); return requestString; }, mergeNewParams: function(newParams) { var upperParams = OpenLayers.Util.upperCaseObject(newParams); var newArguments = [upperParams]; return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply( this, newArguments ); }, getFullRequestString: function(newParams, altUrl) { var mapProjection = this.map.getProjectionObject(); var projectionCode = this.projection && this.projection.equals(mapProjection) ? this.projection.getCode() : mapProjection.getCode(); var value = projectionCode == "none" ? null : projectionCode; if (parseFloat(this.params.VERSION) >= 1.3) { this.params.CRS = value; } else { this.params.SRS = value; } if (typeof this.params.TRANSPARENT == "boolean") { newParams.TRANSPARENT = this.params.TRANSPARENT ? "TRUE" : "FALSE"; } return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply( this, arguments ); }, CLASS_NAME: "OpenLayers.Layer.WMS" }); OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, { xmlns: "http://www.w3.org/2000/svg", xlinkns: "http://www.w3.org/1999/xlink", MAX_PIXEL: 15000, translationParameters: null, symbolMetrics: null, initialize: function(containerID) { if (!this.supported()) { return; } OpenLayers.Renderer.Elements.prototype.initialize.apply(this, arguments); this.translationParameters = { x: 0, y: 0 }; this.symbolMetrics = {}; }, supported: function() { var svgFeature = "http://www.w3.org/TR/SVG11/feature#"; return ( document.implementation && (document.implementation.hasFeature("org.w3c.svg", "1.0") || document.implementation.hasFeature(svgFeature + "SVG", "1.1") || document.implementation.hasFeature( svgFeature + "BasicStructure", "1.1" )) ); }, inValidRange: function(x, y, xyOnly) { var left = x + (xyOnly ? 0 : this.translationParameters.x); var top = y + (xyOnly ? 0 : this.translationParameters.y); return ( left >= -this.MAX_PIXEL && left <= this.MAX_PIXEL && top >= -this.MAX_PIXEL && top <= this.MAX_PIXEL ); }, setExtent: function(extent, resolutionChanged) { var coordSysUnchanged = OpenLayers.Renderer.Elements.prototype.setExtent.apply( this, arguments ); var resolution = this.getResolution(), left = -extent.left / resolution, top = extent.top / resolution; if (resolutionChanged) { this.left = left; this.top = top; var extentString = "0 0 " + this.size.w + " " + this.size.h; this.rendererRoot.setAttributeNS(null, "viewBox", extentString); this.translate(this.xOffset, 0); return true; } else { var inRange = this.translate( left - this.left + this.xOffset, top - this.top ); if (!inRange) { this.setExtent(extent, true); } return coordSysUnchanged && inRange; } }, translate: function(x, y) { if (!this.inValidRange(x, y, true)) { return false; } else { var transformString = ""; if (x || y) { transformString = "translate(" + x + "," + y + ")"; } this.root.setAttributeNS(null, "transform", transformString); this.translationParameters = { x: x, y: y }; return true; } }, setSize: function(size) { OpenLayers.Renderer.prototype.setSize.apply(this, arguments); this.rendererRoot.setAttributeNS(null, "width", this.size.w); this.rendererRoot.setAttributeNS(null, "height", this.size.h); }, getNodeType: function(geometry, style) { var nodeType = null; switch (geometry.CLASS_NAME) { case "OpenLayers.Geometry.Point": if (style.externalGraphic) { nodeType = "image"; } else if (this.isComplexSymbol(style.graphicName)) { nodeType = "svg"; } else { nodeType = "circle"; } break; case "OpenLayers.Geometry.Rectangle": nodeType = "rect"; break; case "OpenLayers.Geometry.LineString": nodeType = "polyline"; break; case "OpenLayers.Geometry.LinearRing": nodeType = "polygon"; break; case "OpenLayers.Geometry.Polygon": case "OpenLayers.Geometry.Curve": nodeType = "path"; break; default: break; } return nodeType; }, setStyle: function(node, style, options) { style = style || node._style; options = options || node._options; var r = parseFloat(node.getAttributeNS(null, "r")); var widthFactor = 1; var pos; if (node._geometryClass == "OpenLayers.Geometry.Point" && r) { node.style.visibility = ""; if (style.graphic === false) { node.style.visibility = "hidden"; } else if (style.externalGraphic) { pos = this.getPosition(node); if (style.graphicTitle) { node.setAttributeNS(null, "title", style.graphicTitle); var titleNode = node.getElementsByTagName("title"); if (titleNode.length > 0) { titleNode[0].firstChild.textContent = style.graphicTitle; } else { var label = this.nodeFactory(null, "title"); label.textContent = style.graphicTitle; node.appendChild(label); } } if (style.graphicWidth && style.graphicHeight) { node.setAttributeNS(null, "preserveAspectRatio", "none"); } 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; node.setAttributeNS(null, "x", (pos.x + xOffset).toFixed()); node.setAttributeNS(null, "y", (pos.y + yOffset).toFixed()); node.setAttributeNS(null, "width", width); node.setAttributeNS(null, "height", height); node.setAttributeNS(this.xlinkns, "href", style.externalGraphic); node.setAttributeNS(null, "style", "opacity: " + opacity); node.onclick = OpenLayers.Renderer.SVG.preventDefault; } else if (this.isComplexSymbol(style.graphicName)) { var offset = style.pointRadius * 3; var size = offset * 2; var src = this.importSymbol(style.graphicName); pos = this.getPosition(node); widthFactor = (this.symbolMetrics[src.id][0] * 3) / size; var parent = node.parentNode; var nextSibling = node.nextSibling; if (parent) { parent.removeChild(node); } node.firstChild && node.removeChild(node.firstChild); node.appendChild(src.firstChild.cloneNode(true)); node.setAttributeNS( null, "viewBox", src.getAttributeNS(null, "viewBox") ); node.setAttributeNS(null, "width", size); node.setAttributeNS(null, "height", size); node.setAttributeNS(null, "x", pos.x - offset); node.setAttributeNS(null, "y", pos.y - offset); if (nextSibling) { parent.insertBefore(node, nextSibling); } else if (parent) { parent.appendChild(node); } } else { node.setAttributeNS(null, "r", style.pointRadius); } var rotation = style.rotation; if ((rotation !== undefined || node._rotation !== undefined) && pos) { node._rotation = rotation; rotation |= 0; if (node.nodeName !== "svg") { node.setAttributeNS( null, "transform", "rotate(" + rotation + " " + pos.x + " " + pos.y + ")" ); } else { var metrics = this.symbolMetrics[src.id]; node.firstChild.setAttributeNS( null, "transform", "rotate(" + rotation + " " + metrics[1] + " " + metrics[2] + ")" ); } } } if (options.isFilled) { node.setAttributeNS(null, "fill", style.fillColor); node.setAttributeNS(null, "fill-opacity", style.fillOpacity); } else { node.setAttributeNS(null, "fill", "none"); } if (options.isStroked) { node.setAttributeNS(null, "stroke", style.strokeColor); node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity); node.setAttributeNS( null, "stroke-width", style.strokeWidth * widthFactor ); node.setAttributeNS( null, "stroke-linecap", style.strokeLinecap || "round" ); node.setAttributeNS(null, "stroke-linejoin", "round"); style.strokeDashstyle && node.setAttributeNS( null, "stroke-dasharray", this.dashStyle(style, widthFactor) ); } else { node.setAttributeNS(null, "stroke", "none"); } if (style.pointerEvents) { node.setAttributeNS(null, "pointer-events", style.pointerEvents); } if (style.cursor != null) { node.setAttributeNS(null, "cursor", style.cursor); } return node; }, dashStyle: function(style, widthFactor) { var w = style.strokeWidth * widthFactor; var str = style.strokeDashstyle; switch (str) { case "solid": return "none"; case "dot": return [1, 4 * w].join(); case "dash": return [4 * w, 4 * w].join(); case "dashdot": return [4 * w, 4 * w, 1, 4 * w].join(); case "longdash": return [8 * w, 4 * w].join(); case "longdashdot": return [8 * w, 4 * w, 1, 4 * w].join(); default: return OpenLayers.String.trim(str).replace(/\s+/g, ","); } }, createNode: function(type, id) { var node = document.createElementNS(this.xmlns, type); if (id) { node.setAttributeNS(null, "id", id); } return node; }, nodeTypeCompare: function(node, type) { return type == node.nodeName; }, createRenderRoot: function() { var svg = this.nodeFactory(this.container.id + "_svgRoot", "svg"); svg.style.display = "block"; return svg; }, createRoot: function(suffix) { return this.nodeFactory(this.container.id + suffix, "g"); }, createDefs: function() { var defs = this.nodeFactory(this.container.id + "_defs", "defs"); this.rendererRoot.appendChild(defs); return defs; }, drawPoint: function(node, geometry) { return this.drawCircle(node, geometry, 1); }, drawCircle: function(node, geometry, radius) { var resolution = this.getResolution(); var x = (geometry.x - this.featureDx) / resolution + this.left; var y = this.top - geometry.y / resolution; if (this.inValidRange(x, y)) { node.setAttributeNS(null, "cx", x); node.setAttributeNS(null, "cy", y); node.setAttributeNS(null, "r", radius); return node; } else { return false; } }, drawLineString: function(node, geometry) { var componentsResult = this.getComponentsString(geometry.components); if (componentsResult.path) { node.setAttributeNS(null, "points", componentsResult.path); return componentsResult.complete ? node : null; } else { return false; } }, drawLinearRing: function(node, geometry) { var componentsResult = this.getComponentsString(geometry.components); if (componentsResult.path) { node.setAttributeNS(null, "points", componentsResult.path); return componentsResult.complete ? node : null; } else { return false; } }, drawPolygon: function(node, geometry) { var d = ""; var draw = true; var complete = true; var linearRingResult, path; for (var j = 0, len = geometry.components.length; j < len; j++) { d += " M"; linearRingResult = this.getComponentsString( geometry.components[j].components, " " ); path = linearRingResult.path; if (path) { d += " " + path; complete = linearRingResult.complete && complete; } else { draw = false; } } d += " z"; if (draw) { node.setAttributeNS(null, "d", d); node.setAttributeNS(null, "fill-rule", "evenodd"); return complete ? node : null; } else { return false; } }, drawRectangle: function(node, geometry) { var resolution = this.getResolution(); var x = (geometry.x - this.featureDx) / resolution + this.left; var y = this.top - geometry.y / resolution; if (this.inValidRange(x, y)) { node.setAttributeNS(null, "x", x); node.setAttributeNS(null, "y", y); node.setAttributeNS(null, "width", geometry.width / resolution); node.setAttributeNS(null, "height", geometry.height / resolution); return node; } else { return false; } }, drawText: function(featureId, style, location) { var drawOutline = !!style.labelOutlineWidth; if (drawOutline) { var outlineStyle = OpenLayers.Util.extend({}, style); outlineStyle.fontColor = outlineStyle.labelOutlineColor; outlineStyle.fontStrokeColor = outlineStyle.labelOutlineColor; outlineStyle.fontStrokeWidth = style.labelOutlineWidth; delete outlineStyle.labelOutlineWidth; this.drawText(featureId, outlineStyle, location); } var resolution = this.getResolution(); var x = (location.x - this.featureDx) / resolution + this.left; var y = location.y / resolution - this.top; var suffix = drawOutline ? this.LABEL_OUTLINE_SUFFIX : this.LABEL_ID_SUFFIX; var label = this.nodeFactory(featureId + suffix, "text"); label.setAttributeNS(null, "x", x); label.setAttributeNS(null, "y", -y); if (style.fontColor) { label.setAttributeNS(null, "fill", style.fontColor); } if (style.fontStrokeColor) { label.setAttributeNS(null, "stroke", style.fontStrokeColor); } if (style.fontStrokeWidth) { label.setAttributeNS(null, "stroke-width", style.fontStrokeWidth); } if (style.fontOpacity) { label.setAttributeNS(null, "opacity", style.fontOpacity); } if (style.fontFamily) { label.setAttributeNS(null, "font-family", style.fontFamily); } if (style.fontSize) { label.setAttributeNS(null, "font-size", style.fontSize); } if (style.fontWeight) { label.setAttributeNS(null, "font-weight", style.fontWeight); } if (style.fontStyle) { label.setAttributeNS(null, "font-style", style.fontStyle); } if (style.labelSelect === true) { label.setAttributeNS(null, "pointer-events", "visible"); label._featureId = featureId; } else { label.setAttributeNS(null, "pointer-events", "none"); } var align = style.labelAlign || OpenLayers.Renderer.defaultSymbolizer.labelAlign; label.setAttributeNS( null, "text-anchor", OpenLayers.Renderer.SVG.LABEL_ALIGN[align[0]] || "middle" ); if (OpenLayers.IS_GECKO === true) { label.setAttributeNS( null, "dominant-baseline", OpenLayers.Renderer.SVG.LABEL_ALIGN[align[1]] || "central" ); } var labelRows = style.label.split("\n"); var numRows = labelRows.length; while (label.childNodes.length > numRows) { label.removeChild(label.lastChild); } for (var i = 0; i < numRows; i++) { var tspan = this.nodeFactory(featureId + suffix + "_tspan_" + i, "tspan"); if (style.labelSelect === true) { tspan._featureId = featureId; tspan._geometry = location; tspan._geometryClass = location.CLASS_NAME; } if (OpenLayers.IS_GECKO === false) { tspan.setAttributeNS( null, "baseline-shift", OpenLayers.Renderer.SVG.LABEL_VSHIFT[align[1]] || "-35%" ); } tspan.setAttribute("x", x); if (i == 0) { var vfactor = OpenLayers.Renderer.SVG.LABEL_VFACTOR[align[1]]; if (vfactor == null) { vfactor = -0.5; } tspan.setAttribute("dy", vfactor * (numRows - 1) + "em"); } else { tspan.setAttribute("dy", "1em"); } tspan.textContent = labelRows[i] === "" ? " " : labelRows[i]; if (!tspan.parentNode) { label.appendChild(tspan); } } if (!label.parentNode) { this.textRoot.appendChild(label); } }, getComponentsString: function(components, separator) { var renderCmp = []; var complete = true; var len = components.length; var strings = []; var str, component; for (var i = 0; i < len; i++) { component = components[i]; renderCmp.push(component); str = this.getShortString(component); if (str) { strings.push(str); } else { if (i > 0) { if (this.getShortString(components[i - 1])) { strings.push(this.clipLine(components[i], components[i - 1])); } } if (i < len - 1) { if (this.getShortString(components[i + 1])) { strings.push(this.clipLine(components[i], components[i + 1])); } } complete = false; } } return { path: strings.join(separator || ","), complete: complete }; }, clipLine: function(badComponent, goodComponent) { if (goodComponent.equals(badComponent)) { return ""; } var resolution = this.getResolution(); var maxX = this.MAX_PIXEL - this.translationParameters.x; var maxY = this.MAX_PIXEL - this.translationParameters.y; var x1 = (goodComponent.x - this.featureDx) / resolution + this.left; var y1 = this.top - goodComponent.y / resolution; var x2 = (badComponent.x - this.featureDx) / resolution + this.left; var y2 = this.top - badComponent.y / resolution; var k; if (x2 < -maxX || x2 > maxX) { k = (y2 - y1) / (x2 - x1); x2 = x2 < 0 ? -maxX : maxX; y2 = y1 + (x2 - x1) * k; } if (y2 < -maxY || y2 > maxY) { k = (x2 - x1) / (y2 - y1); y2 = y2 < 0 ? -maxY : maxY; x2 = x1 + (y2 - y1) * k; } return x2 + "," + y2; }, getShortString: function(point) { var resolution = this.getResolution(); var x = (point.x - this.featureDx) / resolution + this.left; var y = this.top - point.y / resolution; if (this.inValidRange(x, y)) { return x + "," + y; } else { return false; } }, getPosition: function(node) { return { x: parseFloat(node.getAttributeNS(null, "cx")), y: parseFloat(node.getAttributeNS(null, "cy")) }; }, importSymbol: function(graphicName) { if (!this.defs) { this.defs = this.createDefs(); } var id = this.container.id + "-" + graphicName; var existing = document.getElementById(id); if (existing != null) { return existing; } var symbol = OpenLayers.Renderer.symbol[graphicName]; if (!symbol) { throw new Error(graphicName + " is not a valid symbol name"); } var symbolNode = this.nodeFactory(id, "symbol"); var node = this.nodeFactory(null, "polygon"); symbolNode.appendChild(node); var symbolExtent = new OpenLayers.Bounds( Number.MAX_VALUE, Number.MAX_VALUE, 0, 0 ); var points = []; var x, y; for (var i = 0; i < symbol.length; i = i + 2) { x = symbol[i]; y = symbol[i + 1]; symbolExtent.left = Math.min(symbolExtent.left, x); symbolExtent.bottom = Math.min(symbolExtent.bottom, y); symbolExtent.right = Math.max(symbolExtent.right, x); symbolExtent.top = Math.max(symbolExtent.top, y); points.push(x, ",", y); } node.setAttributeNS(null, "points", points.join(" ")); var width = symbolExtent.getWidth(); var height = symbolExtent.getHeight(); var viewBox = [ symbolExtent.left - width, symbolExtent.bottom - height, width * 3, height * 3 ]; symbolNode.setAttributeNS(null, "viewBox", viewBox.join(" ")); this.symbolMetrics[id] = [ Math.max(width, height), symbolExtent.getCenterLonLat().lon, symbolExtent.getCenterLonLat().lat ]; this.defs.appendChild(symbolNode); return symbolNode; }, getFeatureIdFromEvent: function(evt) { var featureId = OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply( this, arguments ); if (!featureId) { var target = evt.target; featureId = target.parentNode && target != this.rendererRoot ? target.parentNode._featureId : undefined; } return featureId; }, CLASS_NAME: "OpenLayers.Renderer.SVG" }); OpenLayers.Renderer.SVG.LABEL_ALIGN = { l: "start", r: "end", b: "bottom", t: "hanging" }; OpenLayers.Renderer.SVG.LABEL_VSHIFT = { t: "-70%", b: "0" }; OpenLayers.Renderer.SVG.LABEL_VFACTOR = { t: 0, b: -1 }; OpenLayers.Renderer.SVG.preventDefault = function(e) { e.preventDefault && e.preventDefault(); }; OpenLayers.Format = OpenLayers.Class({ options: null, externalProjection: null, internalProjection: null, data: null, keepData: false, initialize: function(options) { OpenLayers.Util.extend(this, options); this.options = options; }, destroy: function() {}, read: function(data) { throw new Error("Read not implemented."); }, write: function(object) { throw new Error("Write not implemented."); }, CLASS_NAME: "OpenLayers.Format" }); OpenLayers.Format.JSON = OpenLayers.Class(OpenLayers.Format, { indent: " ", space: " ", newline: "\n", level: 0, pretty: false, nativeJSON: (function() { return !!( window.JSON && typeof JSON.parse == "function" && typeof JSON.stringify == "function" ); })(), read: function(json, filter) { var object; if (this.nativeJSON) { object = JSON.parse(json, filter); } else try { if ( /^[\],:{}\s]*$/.test( json .replace(/\\["\\\/bfnrtu]/g, "@") .replace( /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]" ) .replace(/(?:^|:|,)(?:\s*\[)+/g, "") ) ) { object = eval("(" + json + ")"); if (typeof filter === "function") { function walk(k, v) { if (v && typeof v === "object") { for (var i in v) { if (v.hasOwnProperty(i)) { v[i] = walk(i, v[i]); } } } return filter(k, v); } object = walk("", object); } } } catch (e) {} if (this.keepData) { this.data = object; } return object; }, write: function(value, pretty) { this.pretty = !!pretty; var json = null; var type = typeof value; if (this.serialize[type]) { try { json = !this.pretty && this.nativeJSON ? JSON.stringify(value) : this.serialize[type].apply(this, [value]); } catch (err) { OpenLayers.Console.error("Trouble serializing: " + err); } } return json; }, writeIndent: function() { var pieces = []; if (this.pretty) { for (var i = 0; i < this.level; ++i) { pieces.push(this.indent); } } return pieces.join(""); }, writeNewline: function() { return this.pretty ? this.newline : ""; }, writeSpace: function() { return this.pretty ? this.space : ""; }, serialize: { object: function(object) { if (object == null) { return "null"; } if (object.constructor == Date) { return this.serialize.date.apply(this, [object]); } if (object.constructor == Array) { return this.serialize.array.apply(this, [object]); } var pieces = ["{"]; this.level += 1; var key, keyJSON, valueJSON; var addComma = false; for (key in object) { if (object.hasOwnProperty(key)) { keyJSON = OpenLayers.Format.JSON.prototype.write.apply(this, [ key, this.pretty ]); valueJSON = OpenLayers.Format.JSON.prototype.write.apply(this, [ object[key], this.pretty ]); if (keyJSON != null && valueJSON != null) { if (addComma) { pieces.push(","); } pieces.push( this.writeNewline(), this.writeIndent(), keyJSON, ":", this.writeSpace(), valueJSON ); addComma = true; } } } this.level -= 1; pieces.push(this.writeNewline(), this.writeIndent(), "}"); return pieces.join(""); }, array: function(array) { var json; var pieces = ["["]; this.level += 1; for (var i = 0, len = array.length; i < len; ++i) { json = OpenLayers.Format.JSON.prototype.write.apply(this, [ array[i], this.pretty ]); if (json != null) { if (i > 0) { pieces.push(","); } pieces.push(this.writeNewline(), this.writeIndent(), json); } } this.level -= 1; pieces.push(this.writeNewline(), this.writeIndent(), "]"); return pieces.join(""); }, string: function(string) { var m = { "\b": "\\b", "\t": "\\t", "\n": "\\n", "\f": "\\f", "\r": "\\r", '"': '\\"', "\\": "\\\\" }; if (/["\\\x00-\x1f]/.test(string)) { return ( '"' + string.replace(/([\x00-\x1f\\"])/g, function(a, b) { var c = m[b]; if (c) { return c; } c = b.charCodeAt(); return ( "\\u00" + Math.floor(c / 16).toString(16) + (c % 16).toString(16) ); }) + '"' ); } return '"' + string + '"'; }, number: function(number) { return isFinite(number) ? String(number) : "null"; }, boolean: function(bool) { return String(bool); }, date: function(date) { function format(number) { return number < 10 ? "0" + number : number; } return ( '"' + date.getFullYear() + "-" + format(date.getMonth() + 1) + "-" + format(date.getDate()) + "T" + format(date.getHours()) + ":" + format(date.getMinutes()) + ":" + format(date.getSeconds()) + '"' ); } }, CLASS_NAME: "OpenLayers.Format.JSON" }); OpenLayers.Format.GeoJSON = OpenLayers.Class(OpenLayers.Format.JSON, { ignoreExtraDims: false, read: function(json, type, filter) { type = type ? type : "FeatureCollection"; var results = null; var obj = null; if (typeof json == "string") { obj = OpenLayers.Format.JSON.prototype.read.apply(this, [json, filter]); } else { obj = json; } if (!obj) { OpenLayers.Console.error("Bad JSON: " + json); } else if (typeof obj.type != "string") { OpenLayers.Console.error("Bad GeoJSON - no type: " + json); } else if (this.isValidType(obj, type)) { switch (type) { case "Geometry": try { results = this.parseGeometry(obj); } catch (err) { OpenLayers.Console.error(err); } break; case "Feature": try { results = this.parseFeature(obj); results.type = "Feature"; } catch (err) { OpenLayers.Console.error(err); } break; case "FeatureCollection": results = []; switch (obj.type) { case "Feature": try { results.push(this.parseFeature(obj)); } catch (err) { results = null; OpenLayers.Console.error(err); } break; case "FeatureCollection": for (var i = 0, len = obj.features.length; i < len; ++i) { try { results.push(this.parseFeature(obj.features[i])); } catch (err) { results = null; OpenLayers.Console.error(err); } } break; default: try { var geom = this.parseGeometry(obj); results.push(new OpenLayers.Feature.Vector(geom)); } catch (err) { results = null; OpenLayers.Console.error(err); } } break; } } return results; }, isValidType: function(obj, type) { var valid = false; switch (type) { case "Geometry": if ( OpenLayers.Util.indexOf( [ "Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon", "Box", "GeometryCollection" ], obj.type ) == -1 ) { OpenLayers.Console.error("Unsupported geometry type: " + obj.type); } else { valid = true; } break; case "FeatureCollection": valid = true; break; default: if (obj.type == type) { valid = true; } else { OpenLayers.Console.error( "Cannot convert types from " + obj.type + " to " + type ); } } return valid; }, parseFeature: function(obj) { var feature, geometry, attributes, bbox; attributes = obj.properties ? obj.properties : {}; bbox = (obj.geometry && obj.geometry.bbox) || obj.bbox; try { geometry = this.parseGeometry(obj.geometry); } catch (err) { throw err; } feature = new OpenLayers.Feature.Vector(geometry, attributes); if (bbox) { feature.bounds = OpenLayers.Bounds.fromArray(bbox); } if (obj.id) { feature.fid = obj.id; } return feature; }, parseGeometry: function(obj) { if (obj == null) { return null; } var geometry, collection = false; if (obj.type == "GeometryCollection") { if (!OpenLayers.Util.isArray(obj.geometries)) { throw "GeometryCollection must have geometries array: " + obj; } var numGeom = obj.geometries.length; var components = new Array(numGeom); for (var i = 0; i < numGeom; ++i) { components[i] = this.parseGeometry.apply(this, [obj.geometries[i]]); } geometry = new OpenLayers.Geometry.Collection(components); collection = true; } else { if (!OpenLayers.Util.isArray(obj.coordinates)) { throw "Geometry must have coordinates array: " + obj; } if (!this.parseCoords[obj.type.toLowerCase()]) { throw "Unsupported geometry type: " + obj.type; } try { geometry = this.parseCoords[obj.type.toLowerCase()].apply(this, [ obj.coordinates ]); } catch (err) { throw err; } } if (this.internalProjection && this.externalProjection && !collection) { geometry.transform(this.externalProjection, this.internalProjection); } return geometry; }, parseCoords: { point: function(array) { if (this.ignoreExtraDims == false && array.length != 2) { throw "Only 2D points are supported: " + array; } return new OpenLayers.Geometry.Point(array[0], array[1]); }, multipoint: function(array) { var points = []; var p = null; for (var i = 0, len = array.length; i < len; ++i) { try { p = this.parseCoords["point"].apply(this, [array[i]]); } catch (err) { throw err; } points.push(p); } return new OpenLayers.Geometry.MultiPoint(points); }, linestring: function(array) { var points = []; var p = null; for (var i = 0, len = array.length; i < len; ++i) { try { p = this.parseCoords["point"].apply(this, [array[i]]); } catch (err) { throw err; } points.push(p); } return new OpenLayers.Geometry.LineString(points); }, multilinestring: function(array) { var lines = []; var l = null; for (var i = 0, len = array.length; i < len; ++i) { try { l = this.parseCoords["linestring"].apply(this, [array[i]]); } catch (err) { throw err; } lines.push(l); } return new OpenLayers.Geometry.MultiLineString(lines); }, polygon: function(array) { var rings = []; var r, l; for (var i = 0, len = array.length; i < len; ++i) { try { l = this.parseCoords["linestring"].apply(this, [array[i]]); } catch (err) { throw err; } r = new OpenLayers.Geometry.LinearRing(l.components); rings.push(r); } return new OpenLayers.Geometry.Polygon(rings); }, multipolygon: function(array) { var polys = []; var p = null; for (var i = 0, len = array.length; i < len; ++i) { try { p = this.parseCoords["polygon"].apply(this, [array[i]]); } catch (err) { throw err; } polys.push(p); } return new OpenLayers.Geometry.MultiPolygon(polys); }, box: function(array) { if (array.length != 2) { throw "GeoJSON box coordinates must have 2 elements"; } return new OpenLayers.Geometry.Polygon([ new OpenLayers.Geometry.LinearRing([ new OpenLayers.Geometry.Point(array[0][0], array[0][1]), new OpenLayers.Geometry.Point(array[1][0], array[0][1]), new OpenLayers.Geometry.Point(array[1][0], array[1][1]), new OpenLayers.Geometry.Point(array[0][0], array[1][1]), new OpenLayers.Geometry.Point(array[0][0], array[0][1]) ]) ]); } }, write: function(obj, pretty) { var geojson = { type: null }; if (OpenLayers.Util.isArray(obj)) { geojson.type = "FeatureCollection"; var numFeatures = obj.length; geojson.features = new Array(numFeatures); for (var i = 0; i < numFeatures; ++i) { var element = obj[i]; if (!element instanceof OpenLayers.Feature.Vector) { var msg = "FeatureCollection only supports collections " + "of features: " + element; throw msg; } geojson.features[i] = this.extract.feature.apply(this, [element]); } } else if (obj.CLASS_NAME.indexOf("OpenLayers.Geometry") == 0) { geojson = this.extract.geometry.apply(this, [obj]); } else if (obj instanceof OpenLayers.Feature.Vector) { geojson = this.extract.feature.apply(this, [obj]); if (obj.layer && obj.layer.projection) { geojson.crs = this.createCRSObject(obj); } } return OpenLayers.Format.JSON.prototype.write.apply(this, [ geojson, pretty ]); }, createCRSObject: function(object) { var proj = object.layer.projection.toString(); var crs = {}; if (proj.match(/epsg:/i)) { var code = parseInt(proj.substring(proj.indexOf(":") + 1)); if (code == 4326) { crs = { type: "name", properties: { name: "urn:ogc:def:crs:OGC:1.3:CRS84" } }; } else { crs = { type: "name", properties: { name: "EPSG:" + code } }; } } return crs; }, extract: { feature: function(feature) { var geom = this.extract.geometry.apply(this, [feature.geometry]); var json = { type: "Feature", properties: feature.attributes, geometry: geom }; if (feature.fid != null) { json.id = feature.fid; } return json; }, geometry: function(geometry) { if (geometry == null) { return null; } if (this.internalProjection && this.externalProjection) { geometry = geometry.clone(); geometry.transform(this.internalProjection, this.externalProjection); } var geometryType = geometry.CLASS_NAME.split(".")[2]; var data = this.extract[geometryType.toLowerCase()].apply(this, [ geometry ]); var json; if (geometryType == "Collection") { json = { type: "GeometryCollection", geometries: data }; } else { json = { type: geometryType, coordinates: data }; } return json; }, point: function(point) { return [point.x, point.y]; }, multipoint: function(multipoint) { var array = []; for (var i = 0, len = multipoint.components.length; i < len; ++i) { array.push(this.extract.point.apply(this, [multipoint.components[i]])); } return array; }, linestring: function(linestring) { var array = []; for (var i = 0, len = linestring.components.length; i < len; ++i) { array.push(this.extract.point.apply(this, [linestring.components[i]])); } return array; }, multilinestring: function(multilinestring) { var array = []; for (var i = 0, len = multilinestring.components.length; i < len; ++i) { array.push( this.extract.linestring.apply(this, [multilinestring.components[i]]) ); } return array; }, polygon: function(polygon) { var array = []; for (var i = 0, len = polygon.components.length; i < len; ++i) { array.push( this.extract.linestring.apply(this, [polygon.components[i]]) ); } return array; }, multipolygon: function(multipolygon) { var array = []; for (var i = 0, len = multipolygon.components.length; i < len; ++i) { array.push( this.extract.polygon.apply(this, [multipolygon.components[i]]) ); } return array; }, collection: function(collection) { var len = collection.components.length; var array = new Array(len); for (var i = 0; i < len; ++i) { array[i] = this.extract.geometry.apply(this, [ collection.components[i] ]); } return array; } }, CLASS_NAME: "OpenLayers.Format.GeoJSON" }); OpenLayers.Popup = OpenLayers.Class({ events: null, id: "", lonlat: null, div: null, contentSize: null, size: null, contentHTML: null, backgroundColor: "", opacity: "", border: "", contentDiv: null, groupDiv: null, closeDiv: null, autoSize: false, minSize: null, maxSize: null, displayClass: "olPopup", contentDisplayClass: "olPopupContent", padding: 0, disableFirefoxOverflowHack: false, fixPadding: function() { if (typeof this.padding == "number") { this.padding = new OpenLayers.Bounds( this.padding, this.padding, this.padding, this.padding ); } }, panMapIfOutOfView: false, keepInMap: false, closeOnMove: false, map: null, initialize: function( id, lonlat, contentSize, contentHTML, closeBox, closeBoxCallback ) { if (id == null) { id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); } this.id = id; this.lonlat = lonlat; this.contentSize = contentSize != null ? contentSize : new OpenLayers.Size(OpenLayers.Popup.WIDTH, OpenLayers.Popup.HEIGHT); if (contentHTML != null) { this.contentHTML = contentHTML; } this.backgroundColor = OpenLayers.Popup.COLOR; this.opacity = OpenLayers.Popup.OPACITY; this.border = OpenLayers.Popup.BORDER; this.div = OpenLayers.Util.createDiv( this.id, null, null, null, null, null, "hidden" ); this.div.className = this.displayClass; var groupDivId = this.id + "_GroupDiv"; this.groupDiv = OpenLayers.Util.createDiv( groupDivId, null, null, null, "relative", null, "hidden" ); var id = this.div.id + "_contentDiv"; this.contentDiv = OpenLayers.Util.createDiv( id, null, this.contentSize.clone(), null, "relative" ); this.contentDiv.className = this.contentDisplayClass; this.groupDiv.appendChild(this.contentDiv); this.div.appendChild(this.groupDiv); if (closeBox) { this.addCloseBox(closeBoxCallback); } this.registerEvents(); }, destroy: function() { this.id = null; this.lonlat = null; this.size = null; this.contentHTML = null; this.backgroundColor = null; this.opacity = null; this.border = null; if (this.closeOnMove && this.map) { this.map.events.unregister("movestart", this, this.hide); } this.events.destroy(); this.events = null; if (this.closeDiv) { OpenLayers.Event.stopObservingElement(this.closeDiv); this.groupDiv.removeChild(this.closeDiv); } this.closeDiv = null; this.div.removeChild(this.groupDiv); this.groupDiv = null; if (this.map != null) { this.map.removePopup(this); } this.map = null; this.div = null; this.autoSize = null; this.minSize = null; this.maxSize = null; this.padding = null; this.panMapIfOutOfView = null; }, draw: function(px) { if (px == null) { if (this.lonlat != null && this.map != null) { px = this.map.getLayerPxFromLonLat(this.lonlat); } } if (this.closeOnMove) { this.map.events.register("movestart", this, this.hide); } if ( !this.disableFirefoxOverflowHack && OpenLayers.BROWSER_NAME == "firefox" ) { this.map.events.register("movestart", this, function() { var style = document.defaultView.getComputedStyle( this.contentDiv, null ); var currentOverflow = style.getPropertyValue("overflow"); if (currentOverflow != "hidden") { this.contentDiv._oldOverflow = currentOverflow; this.contentDiv.style.overflow = "hidden"; } }); this.map.events.register("moveend", this, function() { var oldOverflow = this.contentDiv._oldOverflow; if (oldOverflow) { this.contentDiv.style.overflow = oldOverflow; this.contentDiv._oldOverflow = null; } }); } this.moveTo(px); if (!this.autoSize && !this.size) { this.setSize(this.contentSize); } this.setBackgroundColor(); this.setOpacity(); this.setBorder(); this.setContentHTML(); if (this.panMapIfOutOfView) { this.panIntoView(); } return this.div; }, updatePosition: function() { if (this.lonlat && this.map) { var px = this.map.getLayerPxFromLonLat(this.lonlat); if (px) { this.moveTo(px); } } }, moveTo: function(px) { if (px != null && this.div != null) { this.div.style.left = px.x + "px"; this.div.style.top = px.y + "px"; } }, visible: function() { return OpenLayers.Element.visible(this.div); }, toggle: function() { if (this.visible()) { this.hide(); } else { this.show(); } }, show: function() { this.div.style.display = ""; if (this.panMapIfOutOfView) { this.panIntoView(); } }, hide: function() { this.div.style.display = "none"; }, setSize: function(contentSize) { this.size = contentSize.clone(); var contentDivPadding = this.getContentDivPadding(); var wPadding = contentDivPadding.left + contentDivPadding.right; var hPadding = contentDivPadding.top + contentDivPadding.bottom; this.fixPadding(); wPadding += this.padding.left + this.padding.right; hPadding += this.padding.top + this.padding.bottom; if (this.closeDiv) { var closeDivWidth = parseInt(this.closeDiv.style.width); wPadding += closeDivWidth + contentDivPadding.right; } this.size.w += wPadding; this.size.h += hPadding; if (OpenLayers.BROWSER_NAME == "msie") { this.contentSize.w += contentDivPadding.left + contentDivPadding.right; this.contentSize.h += contentDivPadding.bottom + contentDivPadding.top; } if (this.div != null) { this.div.style.width = this.size.w + "px"; this.div.style.height = this.size.h + "px"; } if (this.contentDiv != null) { this.contentDiv.style.width = contentSize.w + "px"; this.contentDiv.style.height = contentSize.h + "px"; } }, updateSize: function() { var preparedHTML = "
" + this.contentDiv.innerHTML + "
"; var containerElement = this.map ? this.map.div : document.body; var realSize = OpenLayers.Util.getRenderedDimensions(preparedHTML, null, { displayClass: this.displayClass, containerElement: containerElement }); var safeSize = this.getSafeContentSize(realSize); var newSize = null; if (safeSize.equals(realSize)) { newSize = realSize; } else { var fixedSize = { w: safeSize.w < realSize.w ? safeSize.w : null, h: safeSize.h < realSize.h ? safeSize.h : null }; if (fixedSize.w && fixedSize.h) { newSize = safeSize; } else { var clippedSize = OpenLayers.Util.getRenderedDimensions( preparedHTML, fixedSize, { displayClass: this.contentDisplayClass, containerElement: containerElement } ); var currentOverflow = OpenLayers.Element.getStyle( this.contentDiv, "overflow" ); if (currentOverflow != "hidden" && clippedSize.equals(safeSize)) { var scrollBar = OpenLayers.Util.getScrollbarWidth(); if (fixedSize.w) { clippedSize.h += scrollBar; } else { clippedSize.w += scrollBar; } } newSize = this.getSafeContentSize(clippedSize); } } this.setSize(newSize); }, setBackgroundColor: function(color) { if (color != undefined) { this.backgroundColor = color; } if (this.div != null) { this.div.style.backgroundColor = this.backgroundColor; } }, setOpacity: function(opacity) { if (opacity != undefined) { this.opacity = opacity; } if (this.div != null) { this.div.style.opacity = this.opacity; this.div.style.filter = "alpha(opacity=" + this.opacity * 100 + ")"; } }, setBorder: function(border) { if (border != undefined) { this.border = border; } if (this.div != null) { this.div.style.border = this.border; } }, setContentHTML: function(contentHTML) { if (contentHTML != null) { this.contentHTML = contentHTML; } if ( this.contentDiv != null && this.contentHTML != null && this.contentHTML != this.contentDiv.innerHTML ) { this.contentDiv.innerHTML = this.contentHTML; if (this.autoSize) { this.registerImageListeners(); this.updateSize(); } } }, registerImageListeners: function() { var onImgLoad = function() { if (this.popup.id === null) { return; } this.popup.updateSize(); if (this.popup.visible() && this.popup.panMapIfOutOfView) { this.popup.panIntoView(); } OpenLayers.Event.stopObserving(this.img, "load", this.img._onImageLoad); }; var images = this.contentDiv.getElementsByTagName("img"); for (var i = 0, len = images.length; i < len; i++) { var img = images[i]; if (img.width == 0 || img.height == 0) { var context = { popup: this, img: img }; img._onImgLoad = OpenLayers.Function.bind(onImgLoad, context); OpenLayers.Event.observe(img, "load", img._onImgLoad); } } }, getSafeContentSize: function(size) { var safeContentSize = size.clone(); var contentDivPadding = this.getContentDivPadding(); var wPadding = contentDivPadding.left + contentDivPadding.right; var hPadding = contentDivPadding.top + contentDivPadding.bottom; this.fixPadding(); wPadding += this.padding.left + this.padding.right; hPadding += this.padding.top + this.padding.bottom; if (this.closeDiv) { var closeDivWidth = parseInt(this.closeDiv.style.width); wPadding += closeDivWidth + contentDivPadding.right; } if (this.minSize) { safeContentSize.w = Math.max( safeContentSize.w, this.minSize.w - wPadding ); safeContentSize.h = Math.max( safeContentSize.h, this.minSize.h - hPadding ); } if (this.maxSize) { safeContentSize.w = Math.min( safeContentSize.w, this.maxSize.w - wPadding ); safeContentSize.h = Math.min( safeContentSize.h, this.maxSize.h - hPadding ); } if (this.map && this.map.size) { var extraX = 0, extraY = 0; if (this.keepInMap && !this.panMapIfOutOfView) { var px = this.map.getPixelFromLonLat(this.lonlat); switch (this.relativePosition) { case "tr": extraX = px.x; extraY = this.map.size.h - px.y; break; case "tl": extraX = this.map.size.w - px.x; extraY = this.map.size.h - px.y; break; case "bl": extraX = this.map.size.w - px.x; extraY = px.y; break; case "br": extraX = px.x; extraY = px.y; break; default: extraX = px.x; extraY = this.map.size.h - px.y; break; } } var maxY = this.map.size.h - this.map.paddingForPopups.top - this.map.paddingForPopups.bottom - hPadding - extraY; var maxX = this.map.size.w - this.map.paddingForPopups.left - this.map.paddingForPopups.right - wPadding - extraX; safeContentSize.w = Math.min(safeContentSize.w, maxX); safeContentSize.h = Math.min(safeContentSize.h, maxY); } return safeContentSize; }, getContentDivPadding: function() { var contentDivPadding = this._contentDivPadding; if (!contentDivPadding) { if (this.div.parentNode == null) { this.div.style.display = "none"; document.body.appendChild(this.div); } contentDivPadding = new OpenLayers.Bounds( OpenLayers.Element.getStyle(this.contentDiv, "padding-left"), OpenLayers.Element.getStyle(this.contentDiv, "padding-bottom"), OpenLayers.Element.getStyle(this.contentDiv, "padding-right"), OpenLayers.Element.getStyle(this.contentDiv, "padding-top") ); this._contentDivPadding = contentDivPadding; if (this.div.parentNode == document.body) { document.body.removeChild(this.div); this.div.style.display = ""; } } return contentDivPadding; }, addCloseBox: function(callback) { this.closeDiv = OpenLayers.Util.createDiv(this.id + "_close", null, { w: 17, h: 17 }); this.closeDiv.className = "olPopupCloseBox"; var contentDivPadding = this.getContentDivPadding(); this.closeDiv.style.right = contentDivPadding.right + "px"; this.closeDiv.style.top = contentDivPadding.top + "px"; this.groupDiv.appendChild(this.closeDiv); var closePopup = callback || function(e) { this.hide(); OpenLayers.Event.stop(e); }; OpenLayers.Event.observe( this.closeDiv, "touchend", OpenLayers.Function.bindAsEventListener(closePopup, this) ); OpenLayers.Event.observe( this.closeDiv, "click", OpenLayers.Function.bindAsEventListener(closePopup, this) ); }, panIntoView: function() { var mapSize = this.map.getSize(); var origTL = this.map.getViewPortPxFromLayerPx( new OpenLayers.Pixel( parseInt(this.div.style.left), parseInt(this.div.style.top) ) ); var newTL = origTL.clone(); if (origTL.x < this.map.paddingForPopups.left) { newTL.x = this.map.paddingForPopups.left; } else if ( origTL.x + this.size.w > mapSize.w - this.map.paddingForPopups.right ) { newTL.x = mapSize.w - this.map.paddingForPopups.right - this.size.w; } if (origTL.y < this.map.paddingForPopups.top) { newTL.y = this.map.paddingForPopups.top; } else if ( origTL.y + this.size.h > mapSize.h - this.map.paddingForPopups.bottom ) { newTL.y = mapSize.h - this.map.paddingForPopups.bottom - this.size.h; } var dx = origTL.x - newTL.x; var dy = origTL.y - newTL.y; this.map.pan(dx, dy); }, registerEvents: function() { this.events = new OpenLayers.Events(this, this.div, null, true); function onTouchstart(evt) { OpenLayers.Event.stop(evt, true); } this.events.on({ mousedown: this.onmousedown, mousemove: this.onmousemove, mouseup: this.onmouseup, click: this.onclick, mouseout: this.onmouseout, dblclick: this.ondblclick, touchstart: onTouchstart, scope: this }); }, onmousedown: function(evt) { this.mousedown = true; OpenLayers.Event.stop(evt, true); }, onmousemove: function(evt) { if (this.mousedown) { OpenLayers.Event.stop(evt, true); } }, onmouseup: function(evt) { if (this.mousedown) { this.mousedown = false; OpenLayers.Event.stop(evt, true); } }, onclick: function(evt) { OpenLayers.Event.stop(evt, true); }, onmouseout: function(evt) { this.mousedown = false; }, ondblclick: function(evt) { OpenLayers.Event.stop(evt, true); }, CLASS_NAME: "OpenLayers.Popup" }); OpenLayers.Popup.WIDTH = 200; OpenLayers.Popup.HEIGHT = 200; OpenLayers.Popup.COLOR = "white"; OpenLayers.Popup.OPACITY = 1; OpenLayers.Popup.BORDER = "0px"; OpenLayers.Popup.Anchored = OpenLayers.Class(OpenLayers.Popup, { relativePosition: null, keepInMap: true, anchor: null, initialize: function( id, lonlat, contentSize, contentHTML, anchor, closeBox, closeBoxCallback ) { var newArguments = [ id, lonlat, contentSize, contentHTML, closeBox, closeBoxCallback ]; OpenLayers.Popup.prototype.initialize.apply(this, newArguments); this.anchor = anchor != null ? anchor : { size: new OpenLayers.Size(0, 0), offset: new OpenLayers.Pixel(0, 0) }; }, destroy: function() { this.anchor = null; this.relativePosition = null; OpenLayers.Popup.prototype.destroy.apply(this, arguments); }, show: function() { this.updatePosition(); OpenLayers.Popup.prototype.show.apply(this, arguments); }, moveTo: function(px) { var oldRelativePosition = this.relativePosition; this.relativePosition = this.calculateRelativePosition(px); var newPx = this.calculateNewPx(px); var newArguments = new Array(newPx); OpenLayers.Popup.prototype.moveTo.apply(this, newArguments); if (this.relativePosition != oldRelativePosition) { this.updateRelativePosition(); } }, setSize: function(contentSize) { OpenLayers.Popup.prototype.setSize.apply(this, arguments); if (this.lonlat && this.map) { var px = this.map.getLayerPxFromLonLat(this.lonlat); this.moveTo(px); } }, calculateRelativePosition: function(px) { var lonlat = this.map.getLonLatFromLayerPx(px); var extent = this.map.getExtent(); var quadrant = extent.determineQuadrant(lonlat); return OpenLayers.Bounds.oppositeQuadrant(quadrant); }, updateRelativePosition: function() {}, calculateNewPx: function(px) { var newPx = px.offset(this.anchor.offset); var size = this.size || this.contentSize; var top = this.relativePosition.charAt(0) == "t"; newPx.y += top ? -size.h : this.anchor.size.h; var left = this.relativePosition.charAt(1) == "l"; newPx.x += left ? -size.w : this.anchor.size.w; return newPx; }, CLASS_NAME: "OpenLayers.Popup.Anchored" }); OpenLayers.Popup.Framed = OpenLayers.Class(OpenLayers.Popup.Anchored, { imageSrc: null, imageSize: null, isAlphaImage: false, positionBlocks: null, blocks: null, fixedRelativePosition: false, initialize: function( id, lonlat, contentSize, contentHTML, anchor, closeBox, closeBoxCallback ) { OpenLayers.Popup.Anchored.prototype.initialize.apply(this, arguments); if (this.fixedRelativePosition) { this.updateRelativePosition(); this.calculateRelativePosition = function(px) { return this.relativePosition; }; } this.contentDiv.style.position = "absolute"; this.contentDiv.style.zIndex = 1; if (closeBox) { this.closeDiv.style.zIndex = 1; } this.groupDiv.style.position = "absolute"; this.groupDiv.style.top = "0px"; this.groupDiv.style.left = "0px"; this.groupDiv.style.height = "100%"; this.groupDiv.style.width = "100%"; }, destroy: function() { this.imageSrc = null; this.imageSize = null; this.isAlphaImage = null; this.fixedRelativePosition = false; this.positionBlocks = null; for (var i = 0; i < this.blocks.length; i++) { var block = this.blocks[i]; if (block.image) { block.div.removeChild(block.image); } block.image = null; if (block.div) { this.groupDiv.removeChild(block.div); } block.div = null; } this.blocks = null; OpenLayers.Popup.Anchored.prototype.destroy.apply(this, arguments); }, setBackgroundColor: function(color) {}, setBorder: function() {}, setOpacity: function(opacity) {}, setSize: function(contentSize) { OpenLayers.Popup.Anchored.prototype.setSize.apply(this, arguments); this.updateBlocks(); }, updateRelativePosition: function() { this.padding = this.positionBlocks[this.relativePosition].padding; if (this.closeDiv) { var contentDivPadding = this.getContentDivPadding(); this.closeDiv.style.right = contentDivPadding.right + this.padding.right + "px"; this.closeDiv.style.top = contentDivPadding.top + this.padding.top + "px"; } this.updateBlocks(); }, calculateNewPx: function(px) { var newPx = OpenLayers.Popup.Anchored.prototype.calculateNewPx.apply( this, arguments ); newPx = newPx.offset(this.positionBlocks[this.relativePosition].offset); return newPx; }, createBlocks: function() { this.blocks = []; var firstPosition = null; for (var key in this.positionBlocks) { firstPosition = key; break; } var position = this.positionBlocks[firstPosition]; for (var i = 0; i < position.blocks.length; i++) { var block = {}; this.blocks.push(block); var divId = this.id + "_FrameDecorationDiv_" + i; block.div = OpenLayers.Util.createDiv( divId, null, null, null, "absolute", null, "hidden", null ); var imgId = this.id + "_FrameDecorationImg_" + i; var imageCreator = this.isAlphaImage ? OpenLayers.Util.createAlphaImageDiv : OpenLayers.Util.createImage; block.image = imageCreator( imgId, null, this.imageSize, this.imageSrc, "absolute", null, null, null ); block.div.appendChild(block.image); this.groupDiv.appendChild(block.div); } }, updateBlocks: function() { if (!this.blocks) { this.createBlocks(); } if (this.size && this.relativePosition) { var position = this.positionBlocks[this.relativePosition]; for (var i = 0; i < position.blocks.length; i++) { var positionBlock = position.blocks[i]; var block = this.blocks[i]; var l = positionBlock.anchor.left; var b = positionBlock.anchor.bottom; var r = positionBlock.anchor.right; var t = positionBlock.anchor.top; var w = isNaN(positionBlock.size.w) ? this.size.w - (r + l) : positionBlock.size.w; var h = isNaN(positionBlock.size.h) ? this.size.h - (b + t) : positionBlock.size.h; block.div.style.width = (w < 0 ? 0 : w) + "px"; block.div.style.height = (h < 0 ? 0 : h) + "px"; block.div.style.left = l != null ? l + "px" : ""; block.div.style.bottom = b != null ? b + "px" : ""; block.div.style.right = r != null ? r + "px" : ""; block.div.style.top = t != null ? t + "px" : ""; block.image.style.left = positionBlock.position.x + "px"; block.image.style.top = positionBlock.position.y + "px"; } this.contentDiv.style.left = this.padding.left + "px"; this.contentDiv.style.top = this.padding.top + "px"; } }, CLASS_NAME: "OpenLayers.Popup.Framed" }); OpenLayers.Layer.Google.v3 = { DEFAULTS: { sphericalMercator: true, projection: "EPSG:900913" }, animationEnabled: true, loadMapObject: function() { if (!this.type) { this.type = google.maps.MapTypeId.ROADMAP; } var mapObject; var cache = OpenLayers.Layer.Google.cache[this.map.id]; if (cache) { mapObject = cache.mapObject; ++cache.count; } else { var container = this.map.viewPortDiv; var div = document.createElement("div"); div.id = this.map.id + "_GMapContainer"; div.style.position = "absolute"; div.style.width = "100%"; div.style.height = "100%"; container.appendChild(div); var center = this.map.getCenter(); mapObject = new google.maps.Map(div, { center: center ? new google.maps.LatLng(center.lat, center.lon) : new google.maps.LatLng(0, 0), zoom: this.map.getZoom() || 0, mapTypeId: this.type, disableDefaultUI: true, keyboardShortcuts: false, draggable: false, disableDoubleClickZoom: true, scrollwheel: false, streetViewControl: false }); cache = { mapObject: mapObject, count: 1 }; OpenLayers.Layer.Google.cache[this.map.id] = cache; this.repositionListener = google.maps.event.addListenerOnce( mapObject, "center_changed", OpenLayers.Function.bind(this.repositionMapElements, this) ); } this.mapObject = mapObject; this.setGMapVisibility(this.visibility); }, repositionMapElements: function() { google.maps.event.trigger(this.mapObject, "resize"); var div = this.mapObject.getDiv().firstChild; if (!div || div.childNodes.length < 3) { this.repositionTimer = window.setTimeout( OpenLayers.Function.bind(this.repositionMapElements, this), 250 ); return false; } var cache = OpenLayers.Layer.Google.cache[this.map.id]; var container = this.map.viewPortDiv; for (var i = div.children.length - 1; i >= 0; --i) { if (div.children[i].style.zIndex == 1000001) { var termsOfUse = div.children[i]; container.appendChild(termsOfUse); termsOfUse.style.zIndex = "1100"; termsOfUse.style.bottom = ""; termsOfUse.className = "olLayerGoogleCopyright olLayerGoogleV3"; termsOfUse.style.display = ""; cache.termsOfUse = termsOfUse; } if (div.children[i].style.zIndex == 1000000) { var poweredBy = div.children[i]; container.appendChild(poweredBy); poweredBy.style.zIndex = "1100"; poweredBy.style.bottom = ""; poweredBy.className = "olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint"; poweredBy.style.display = ""; cache.poweredBy = poweredBy; } if (div.children[i].style.zIndex == 10000002) { container.appendChild(div.children[i]); } } this.setGMapVisibility(this.visibility); }, onMapResize: function() { if (this.visibility) { google.maps.event.trigger(this.mapObject, "resize"); } else { var cache = OpenLayers.Layer.Google.cache[this.map.id]; if (!cache.resized) { var layer = this; google.maps.event.addListenerOnce( this.mapObject, "tilesloaded", function() { google.maps.event.trigger(layer.mapObject, "resize"); layer.moveTo(layer.map.getCenter(), layer.map.getZoom()); delete cache.resized; } ); } cache.resized = true; } }, setGMapVisibility: function(visible) { var cache = OpenLayers.Layer.Google.cache[this.map.id]; if (cache) { var type = this.type; var layers = this.map.layers; var layer; for (var i = layers.length - 1; i >= 0; --i) { layer = layers[i]; if ( layer instanceof OpenLayers.Layer.Google && layer.visibility === true && layer.inRange === true ) { type = layer.type; visible = true; break; } } var container = this.mapObject.getDiv(); if (visible === true) { this.mapObject.setMapTypeId(type); container.style.left = ""; if (cache.termsOfUse && cache.termsOfUse.style) { cache.termsOfUse.style.left = ""; cache.termsOfUse.style.display = ""; cache.poweredBy.style.display = ""; } cache.displayed = this.id; } else { delete cache.displayed; container.style.left = "-9999px"; if (cache.termsOfUse && cache.termsOfUse.style) { cache.termsOfUse.style.display = "none"; cache.termsOfUse.style.left = "-9999px"; cache.poweredBy.style.display = "none"; } } } }, getMapContainer: function() { return this.mapObject.getDiv(); }, getMapObjectBoundsFromOLBounds: function(olBounds) { var moBounds = null; if (olBounds != null) { var sw = this.sphericalMercator ? this.inverseMercator(olBounds.bottom, olBounds.left) : new OpenLayers.LonLat(olBounds.bottom, olBounds.left); var ne = this.sphericalMercator ? this.inverseMercator(olBounds.top, olBounds.right) : new OpenLayers.LonLat(olBounds.top, olBounds.right); moBounds = new google.maps.LatLngBounds( new google.maps.LatLng(sw.lat, sw.lon), new google.maps.LatLng(ne.lat, ne.lon) ); } return moBounds; }, getMapObjectLonLatFromMapObjectPixel: function(moPixel) { var size = this.map.getSize(); var lon = this.getLongitudeFromMapObjectLonLat(this.mapObject.center); var lat = this.getLatitudeFromMapObjectLonLat(this.mapObject.center); var res = this.map.getResolution(); var delta_x = moPixel.x - size.w / 2; var delta_y = moPixel.y - size.h / 2; var lonlat = new OpenLayers.LonLat( lon + delta_x * res, lat - delta_y * res ); if (this.wrapDateLine) { lonlat = lonlat.wrapDateLine(this.maxExtent); } return this.getMapObjectLonLatFromLonLat(lonlat.lon, lonlat.lat); }, getMapObjectPixelFromMapObjectLonLat: function(moLonLat) { var lon = this.getLongitudeFromMapObjectLonLat(moLonLat); var lat = this.getLatitudeFromMapObjectLonLat(moLonLat); var res = this.map.getResolution(); var extent = this.map.getExtent(); return this.getMapObjectPixelFromXY( (1 / res) * (lon - extent.left), (1 / res) * (extent.top - lat) ); }, setMapObjectCenter: function(center, zoom) { if (this.animationEnabled === false && zoom != this.mapObject.zoom) { var mapContainer = this.getMapContainer(); google.maps.event.addListenerOnce(this.mapObject, "idle", function() { mapContainer.style.visibility = ""; }); mapContainer.style.visibility = "hidden"; } this.mapObject.setOptions({ center: center, zoom: zoom }); }, getMapObjectZoomFromMapObjectBounds: function(moBounds) { return this.mapObject.getBoundsZoomLevel(moBounds); }, getMapObjectLonLatFromLonLat: function(lon, lat) { var gLatLng; if (this.sphericalMercator) { var lonlat = this.inverseMercator(lon, lat); gLatLng = new google.maps.LatLng(lonlat.lat, lonlat.lon); } else { gLatLng = new google.maps.LatLng(lat, lon); } return gLatLng; }, getMapObjectPixelFromXY: function(x, y) { return new google.maps.Point(x, y); }, destroy: function() { if (this.repositionListener) { google.maps.event.removeListener(this.repositionListener); } if (this.repositionTimer) { window.clearTimeout(this.repositionTimer); } OpenLayers.Layer.Google.prototype.destroy.apply(this, arguments); } }; OpenLayers.ProxyHost = ""; OpenLayers.Request = { 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 }, URL_SPLIT_REGEX: /([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/, events: new OpenLayers.Events(this), 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); } } else { OpenLayers.Console.warn(OpenLayers.i18n("proxyNeeded"), { url: url }); } } return url; }, issue: function(config) { var defaultConfig = OpenLayers.Util.extend(this.DEFAULT_CONFIG, { proxy: OpenLayers.ProxyHost }); config = OpenLayers.Util.applyDefaults(config, defaultConfig); 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) { config.headers["X-Requested-With"] = "XMLHttpRequest"; } 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; 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 }); } } }; if (config.async === false) { request.send(config.data); } else { window.setTimeout(function() { if (request.readyState !== 0) { request.send(config.data); } }, 0); } return request; }, runCallbacks: function(options) { var request = options.request; var config = options.config; var complete = config.scope ? OpenLayers.Function.bind(config.callback, config.scope) : config.callback; var success; if (config.success) { success = config.scope ? OpenLayers.Function.bind(config.success, config.scope) : config.success; } 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); } } }, GET: function(config) { config = OpenLayers.Util.extend(config, { method: "GET" }); return OpenLayers.Request.issue(config); }, POST: function(config) { config = OpenLayers.Util.extend(config, { method: "POST" }); 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); }, PUT: function(config) { config = OpenLayers.Util.extend(config, { method: "PUT" }); 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); }, DELETE: function(config) { config = OpenLayers.Util.extend(config, { method: "DELETE" }); return OpenLayers.Request.issue(config); }, HEAD: function(config) { config = OpenLayers.Util.extend(config, { method: "HEAD" }); return OpenLayers.Request.issue(config); }, OPTIONS: function(config) { config = OpenLayers.Util.extend(config, { method: "OPTIONS" }); return OpenLayers.Request.issue(config); } }; (function() { var oXMLHttpRequest = window.XMLHttpRequest; var bGecko = !!window.controllers, bIE = window.document.all && !window.opera, bIE7 = bIE && window.navigator.userAgent.match(/MSIE 7.0/); function fXMLHttpRequest() { this._object = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest() : new window.ActiveXObject("Microsoft.XMLHTTP"); this._listeners = []; } function cXMLHttpRequest() { return new fXMLHttpRequest(); } cXMLHttpRequest.prototype = fXMLHttpRequest.prototype; if (bGecko && oXMLHttpRequest.wrapped) cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped; cXMLHttpRequest.UNSENT = 0; cXMLHttpRequest.OPENED = 1; cXMLHttpRequest.HEADERS_RECEIVED = 2; cXMLHttpRequest.LOADING = 3; cXMLHttpRequest.DONE = 4; cXMLHttpRequest.prototype.readyState = cXMLHttpRequest.UNSENT; cXMLHttpRequest.prototype.responseText = ""; cXMLHttpRequest.prototype.responseXML = null; cXMLHttpRequest.prototype.status = 0; cXMLHttpRequest.prototype.statusText = ""; cXMLHttpRequest.prototype.priority = "NORMAL"; cXMLHttpRequest.prototype.onreadystatechange = null; cXMLHttpRequest.onreadystatechange = null; cXMLHttpRequest.onopen = null; cXMLHttpRequest.onsend = null; cXMLHttpRequest.onabort = null; cXMLHttpRequest.prototype.open = function( sMethod, sUrl, bAsync, sUser, sPassword ) { delete this._headers; if (arguments.length < 3) bAsync = true; this._async = bAsync; var oRequest = this, nState = this.readyState, fOnUnload; if (bIE && bAsync) { fOnUnload = function() { if (nState != cXMLHttpRequest.DONE) { fCleanTransport(oRequest); oRequest.abort(); } }; window.attachEvent("onunload", fOnUnload); } 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; oRequest.readyState = oRequest._object.readyState; fSynchronizeValues(oRequest); if (oRequest._aborted) { oRequest.readyState = cXMLHttpRequest.UNSENT; return; } if (oRequest.readyState == cXMLHttpRequest.DONE) { delete oRequest._data; fCleanTransport(oRequest); if (bIE && bAsync) window.detachEvent("onunload", fOnUnload); } if (nState != oRequest.readyState) fReadyStateChange(oRequest); nState = oRequest.readyState; }; }; function fXMLHttpRequest_send(oRequest) { oRequest._object.send(oRequest._data); if (bGecko && !oRequest._async) { oRequest.readyState = cXMLHttpRequest.OPENED; fSynchronizeValues(oRequest); while (oRequest.readyState < cXMLHttpRequest.DONE) { oRequest.readyState++; fReadyStateChange(oRequest); if (oRequest._aborted) return; } } } cXMLHttpRequest.prototype.send = function(vData) { if (cXMLHttpRequest.onsend) cXMLHttpRequest.onsend.apply(this, arguments); if (!arguments.length) vData = null; 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; fXMLHttpRequest_send(this); }; cXMLHttpRequest.prototype.abort = function() { if (cXMLHttpRequest.onabort) cXMLHttpRequest.onabort.apply(this, arguments); if (this.readyState > cXMLHttpRequest.UNSENT) this._aborted = true; this._object.abort(); fCleanTransport(this); this.readyState = cXMLHttpRequest.UNSENT; delete this._data; }; cXMLHttpRequest.prototype.getAllResponseHeaders = function() { return this._object.getAllResponseHeaders(); }; cXMLHttpRequest.prototype.getResponseHeader = function(sName) { return this._object.getResponseHeader(sName); }; cXMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) { if (!this._headers) this._headers = {}; this._headers[sName] = sValue; return this._object.setRequestHeader(sName, sValue); }; 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; 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; 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() {}, preventDefault: function() {}, initEvent: function() {} }; if (oEventPseudo.type == "readystatechange" && this.onreadystatechange) (this.onreadystatechange.handleEvent || this.onreadystatechange).apply( this, [oEventPseudo] ); 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" + "]"; }; function fReadyStateChange(oRequest) { if (cXMLHttpRequest.onreadystatechange) cXMLHttpRequest.onreadystatechange.apply(oRequest); oRequest.dispatchEvent({ type: "readystatechange", bubbles: false, cancelable: false, timeStamp: new Date() + 0 }); } function fGetDocument(oRequest) { var oDocument = oRequest.responseXML, sResponse = oRequest.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); } 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) { oRequest._object.onreadystatechange = new window.Function(); } 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; }; } OpenLayers.Request.XMLHttpRequest = cXMLHttpRequest; })(); OpenLayers.Filter.Comparison = OpenLayers.Class(OpenLayers.Filter, { type: null, property: null, value: null, matchCase: true, lowerBoundary: null, upperBoundary: null, initialize: function(options) { OpenLayers.Filter.prototype.initialize.apply(this, [options]); if ( this.type === OpenLayers.Filter.Comparison.LIKE && options.matchCase === undefined ) { this.matchCase = null; } }, 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; } return result; }, value2regex: function(wildCard, singleChar, escapeChar) { if (wildCard == ".") { throw new Error( "'.' is an unsupported wildCard character for " + "OpenLayers.Filter.Comparison" ); } 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; }, regex2value: function() { var value = this.value; value = value.replace(/!/g, "!!"); value = value.replace(/(\\)?\\\./g, function($0, $1) { return $1 ? $0 : "!."; }); value = value.replace(/(\\)?\\\*/g, function($0, $1) { return $1 ? $0 : "!*"; }); value = value.replace(/\\\\/g, "\\"); value = value.replace(/\.\*/g, "*"); return value; }, 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.Popup.FramedCloud = OpenLayers.Class(OpenLayers.Popup.Framed, { contentDisplayClass: "olFramedCloudPopupContent", autoSize: true, panMapIfOutOfView: true, imageSize: new OpenLayers.Size(1276, 736), isAlphaImage: false, fixedRelativePosition: false, positionBlocks: { tl: { offset: new OpenLayers.Pixel(44, 0), padding: new OpenLayers.Bounds(8, 40, 8, 9), blocks: [ { size: new OpenLayers.Size("auto", "auto"), anchor: new OpenLayers.Bounds(0, 51, 22, 0), position: new OpenLayers.Pixel(0, 0) }, { size: new OpenLayers.Size(22, "auto"), anchor: new OpenLayers.Bounds(null, 50, 0, 0), position: new OpenLayers.Pixel(-1238, 0) }, { size: new OpenLayers.Size("auto", 19), anchor: new OpenLayers.Bounds(0, 32, 22, null), position: new OpenLayers.Pixel(0, -631) }, { size: new OpenLayers.Size(22, 18), anchor: new OpenLayers.Bounds(null, 32, 0, null), position: new OpenLayers.Pixel(-1238, -632) }, { size: new OpenLayers.Size(81, 35), anchor: new OpenLayers.Bounds(null, 0, 0, null), position: new OpenLayers.Pixel(0, -688) } ] }, tr: { offset: new OpenLayers.Pixel(-45, 0), padding: new OpenLayers.Bounds(8, 40, 8, 9), blocks: [ { size: new OpenLayers.Size("auto", "auto"), anchor: new OpenLayers.Bounds(0, 51, 22, 0), position: new OpenLayers.Pixel(0, 0) }, { size: new OpenLayers.Size(22, "auto"), anchor: new OpenLayers.Bounds(null, 50, 0, 0), position: new OpenLayers.Pixel(-1238, 0) }, { size: new OpenLayers.Size("auto", 19), anchor: new OpenLayers.Bounds(0, 32, 22, null), position: new OpenLayers.Pixel(0, -631) }, { size: new OpenLayers.Size(22, 19), anchor: new OpenLayers.Bounds(null, 32, 0, null), position: new OpenLayers.Pixel(-1238, -631) }, { size: new OpenLayers.Size(81, 35), anchor: new OpenLayers.Bounds(0, 0, null, null), position: new OpenLayers.Pixel(-215, -687) } ] }, bl: { offset: new OpenLayers.Pixel(45, 0), padding: new OpenLayers.Bounds(8, 9, 8, 40), blocks: [ { size: new OpenLayers.Size("auto", "auto"), anchor: new OpenLayers.Bounds(0, 21, 22, 32), position: new OpenLayers.Pixel(0, 0) }, { size: new OpenLayers.Size(22, "auto"), anchor: new OpenLayers.Bounds(null, 21, 0, 32), position: new OpenLayers.Pixel(-1238, 0) }, { size: new OpenLayers.Size("auto", 21), anchor: new OpenLayers.Bounds(0, 0, 22, null), position: new OpenLayers.Pixel(0, -629) }, { size: new OpenLayers.Size(22, 21), anchor: new OpenLayers.Bounds(null, 0, 0, null), position: new OpenLayers.Pixel(-1238, -629) }, { size: new OpenLayers.Size(81, 33), anchor: new OpenLayers.Bounds(null, null, 0, 0), position: new OpenLayers.Pixel(-101, -674) } ] }, br: { offset: new OpenLayers.Pixel(-44, 0), padding: new OpenLayers.Bounds(8, 9, 8, 40), blocks: [ { size: new OpenLayers.Size("auto", "auto"), anchor: new OpenLayers.Bounds(0, 21, 22, 32), position: new OpenLayers.Pixel(0, 0) }, { size: new OpenLayers.Size(22, "auto"), anchor: new OpenLayers.Bounds(null, 21, 0, 32), position: new OpenLayers.Pixel(-1238, 0) }, { size: new OpenLayers.Size("auto", 21), anchor: new OpenLayers.Bounds(0, 0, 22, null), position: new OpenLayers.Pixel(0, -629) }, { size: new OpenLayers.Size(22, 21), anchor: new OpenLayers.Bounds(null, 0, 0, null), position: new OpenLayers.Pixel(-1238, -629) }, { size: new OpenLayers.Size(81, 33), anchor: new OpenLayers.Bounds(0, null, null, 0), position: new OpenLayers.Pixel(-311, -674) } ] } }, minSize: new OpenLayers.Size(105, 10), maxSize: new OpenLayers.Size(1200, 660), initialize: function( id, lonlat, contentSize, contentHTML, anchor, closeBox, closeBoxCallback ) { this.imageSrc = OpenLayers.Util.getImageLocation( "cloud-popup-relative.png" ); OpenLayers.Popup.Framed.prototype.initialize.apply(this, arguments); this.contentDiv.className = this.contentDisplayClass; }, CLASS_NAME: "OpenLayers.Popup.FramedCloud" }); OpenLayers.Rule = OpenLayers.Class({ id: null, name: null, title: null, description: null, context: null, filter: null, elseFilter: false, symbolizer: null, symbolizers: null, minScaleDenominator: null, maxScaleDenominator: null, initialize: function(options) { this.symbolizer = {}; OpenLayers.Util.extend(this, options); if (this.symbolizers) { delete this.symbolizer; } this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); }, destroy: function() { for (var i in this.symbolizer) { this.symbolizer[i] = null; } this.symbolizer = null; delete this.symbolizers; }, evaluate: function(feature) { var context = this.getContext(feature); var applies = true; if (this.minScaleDenominator || this.maxScaleDenominator) { var scale = feature.layer.map.getScale(); } if (this.minScaleDenominator) { applies = scale >= OpenLayers.Style.createLiteral(this.minScaleDenominator, context); } if (applies && this.maxScaleDenominator) { applies = scale < OpenLayers.Style.createLiteral(this.maxScaleDenominator, context); } if (applies && this.filter) { if (this.filter.CLASS_NAME == "OpenLayers.Filter.FeatureId") { applies = this.filter.evaluate(feature); } else { applies = this.filter.evaluate(context); } } return applies; }, getContext: function(feature) { var context = this.context; if (!context) { context = feature.attributes || feature.data; } if (typeof this.context == "function") { context = this.context(feature); } return context; }, clone: function() { var options = OpenLayers.Util.extend({}, this); if (this.symbolizers) { var len = this.symbolizers.length; options.symbolizers = new Array(len); for (var i = 0; i < len; ++i) { options.symbolizers[i] = this.symbolizers[i].clone(); } } else { options.symbolizer = {}; var value, type; for (var key in this.symbolizer) { value = this.symbolizer[key]; type = typeof value; if (type === "object") { options.symbolizer[key] = OpenLayers.Util.extend({}, value); } else if (type === "string") { options.symbolizer[key] = value; } } } options.filter = this.filter && this.filter.clone(); options.context = this.context && OpenLayers.Util.extend({}, this.context); return new OpenLayers.Rule(options); }, CLASS_NAME: "OpenLayers.Rule" }); OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, { xmlns: "urn:schemas-microsoft-com:vml", symbolCache: {}, offset: null, initialize: function(containerID) { if (!this.supported()) { return; } if (!document.namespaces.olv) { document.namespaces.add("olv", this.xmlns); var style = document.createStyleSheet(); var shapes = [ "shape", "rect", "oval", "fill", "stroke", "imagedata", "group", "textbox" ]; for (var i = 0, len = shapes.length; i < len; i++) { style.addRule( "olv\\:" + shapes[i], "behavior: url(#default#VML); " + "position: absolute; display: inline-block;" ); } } OpenLayers.Renderer.Elements.prototype.initialize.apply(this, arguments); }, supported: function() { return !!document.namespaces; }, setExtent: function(extent, resolutionChanged) { var coordSysUnchanged = OpenLayers.Renderer.Elements.prototype.setExtent.apply( this, arguments ); var resolution = this.getResolution(); var left = (extent.left / resolution) | 0; var top = (extent.top / resolution - this.size.h) | 0; if (resolutionChanged || !this.offset) { this.offset = { x: left, y: top }; left = 0; top = 0; } else { left = left - this.offset.x; top = top - this.offset.y; } var org = left - this.xOffset + " " + top; this.root.coordorigin = org; var roots = [this.root, this.vectorRoot, this.textRoot]; var root; for (var i = 0, len = roots.length; i < len; ++i) { root = roots[i]; var size = this.size.w + " " + this.size.h; root.coordsize = size; } this.root.style.flip = "y"; return coordSysUnchanged; }, setSize: function(size) { OpenLayers.Renderer.prototype.setSize.apply(this, arguments); var roots = [this.rendererRoot, this.root, this.vectorRoot, this.textRoot]; var w = this.size.w + "px"; var h = this.size.h + "px"; var root; for (var i = 0, len = roots.length; i < len; ++i) { root = roots[i]; root.style.width = w; root.style.height = h; } }, getNodeType: function(geometry, style) { var nodeType = null; switch (geometry.CLASS_NAME) { case "OpenLayers.Geometry.Point": if (style.externalGraphic) { nodeType = "olv:rect"; } else if (this.isComplexSymbol(style.graphicName)) { nodeType = "olv:shape"; } else { nodeType = "olv:oval"; } break; case "OpenLayers.Geometry.Rectangle": nodeType = "olv:rect"; break; case "OpenLayers.Geometry.LineString": case "OpenLayers.Geometry.LinearRing": case "OpenLayers.Geometry.Polygon": case "OpenLayers.Geometry.Curve": nodeType = "olv:shape"; break; default: break; } return nodeType; }, setStyle: function(node, style, options, geometry) { style = style || node._style; options = options || node._options; var fillColor = style.fillColor; if (node._geometryClass === "OpenLayers.Geometry.Point") { if (style.externalGraphic) { options.isFilled = true; if (style.graphicTitle) { node.title = style.graphicTitle; } 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 resolution = this.getResolution(); var xOffset = style.graphicXOffset != undefined ? style.graphicXOffset : -(0.5 * width); var yOffset = style.graphicYOffset != undefined ? style.graphicYOffset : -(0.5 * height); node.style.left = (((geometry.x - this.featureDx) / resolution - this.offset.x + xOffset) | 0) + "px"; node.style.top = ((geometry.y / resolution - this.offset.y - (yOffset + height)) | 0) + "px"; node.style.width = width + "px"; node.style.height = height + "px"; node.style.flip = "y"; fillColor = "none"; options.isStroked = false; } else if (this.isComplexSymbol(style.graphicName)) { var cache = this.importSymbol(style.graphicName); node.path = cache.path; node.coordorigin = cache.left + "," + cache.bottom; var size = cache.size; node.coordsize = size + "," + size; this.drawCircle(node, geometry, style.pointRadius); node.style.flip = "y"; } else { this.drawCircle(node, geometry, style.pointRadius); } } if (options.isFilled) { node.fillcolor = fillColor; } else { node.filled = "false"; } var fills = node.getElementsByTagName("fill"); var fill = fills.length == 0 ? null : fills[0]; if (!options.isFilled) { if (fill) { node.removeChild(fill); } } else { if (!fill) { fill = this.createNode("olv:fill", node.id + "_fill"); } fill.opacity = style.fillOpacity; if ( node._geometryClass === "OpenLayers.Geometry.Point" && style.externalGraphic ) { if (style.graphicOpacity) { fill.opacity = style.graphicOpacity; } fill.src = style.externalGraphic; fill.type = "frame"; if (!(style.graphicWidth && style.graphicHeight)) { fill.aspect = "atmost"; } } if (fill.parentNode != node) { node.appendChild(fill); } } var rotation = style.rotation; if (rotation !== undefined || node._rotation !== undefined) { node._rotation = rotation; if (style.externalGraphic) { this.graphicRotate(node, xOffset, yOffset, style); fill.opacity = 0; } else if (node._geometryClass === "OpenLayers.Geometry.Point") { node.style.rotation = rotation || 0; } } var strokes = node.getElementsByTagName("stroke"); var stroke = strokes.length == 0 ? null : strokes[0]; if (!options.isStroked) { node.stroked = false; if (stroke) { stroke.on = false; } } else { if (!stroke) { stroke = this.createNode("olv:stroke", node.id + "_stroke"); node.appendChild(stroke); } stroke.on = true; stroke.color = style.strokeColor; stroke.weight = style.strokeWidth + "px"; stroke.opacity = style.strokeOpacity; stroke.endcap = style.strokeLinecap == "butt" ? "flat" : style.strokeLinecap || "round"; if (style.strokeDashstyle) { stroke.dashstyle = this.dashStyle(style); } } if (style.cursor != "inherit" && style.cursor != null) { node.style.cursor = style.cursor; } return node; }, graphicRotate: function(node, xOffset, yOffset, style) { var style = style || node._style; var rotation = style.rotation || 0; var aspectRatio, size; if (!(style.graphicWidth && style.graphicHeight)) { var img = new Image(); img.onreadystatechange = OpenLayers.Function.bind(function() { if (img.readyState == "complete" || img.readyState == "interactive") { aspectRatio = img.width / img.height; size = Math.max( style.pointRadius * 2, style.graphicWidth || 0, style.graphicHeight || 0 ); xOffset = xOffset * aspectRatio; style.graphicWidth = size * aspectRatio; style.graphicHeight = size; this.graphicRotate(node, xOffset, yOffset, style); } }, this); img.src = style.externalGraphic; return; } else { size = Math.max(style.graphicWidth, style.graphicHeight); aspectRatio = style.graphicWidth / style.graphicHeight; } var width = Math.round(style.graphicWidth || size * aspectRatio); var height = Math.round(style.graphicHeight || size); node.style.width = width + "px"; node.style.height = height + "px"; var image = document.getElementById(node.id + "_image"); if (!image) { image = this.createNode("olv:imagedata", node.id + "_image"); node.appendChild(image); } image.style.width = width + "px"; image.style.height = height + "px"; image.src = style.externalGraphic; image.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(" + "src='', sizingMethod='scale')"; var rot = (rotation * Math.PI) / 180; var sintheta = Math.sin(rot); var costheta = Math.cos(rot); var filter = "progid:DXImageTransform.Microsoft.Matrix(M11=" + costheta + ",M12=" + -sintheta + ",M21=" + sintheta + ",M22=" + costheta + ",SizingMethod='auto expand')\n"; var opacity = style.graphicOpacity || style.fillOpacity; if (opacity && opacity != 1) { filter += "progid:DXImageTransform.Microsoft.BasicImage(opacity=" + opacity + ")\n"; } node.style.filter = filter; var centerPoint = new OpenLayers.Geometry.Point(-xOffset, -yOffset); var imgBox = new OpenLayers.Bounds(0, 0, width, height).toGeometry(); imgBox.rotate(style.rotation, centerPoint); var imgBounds = imgBox.getBounds(); node.style.left = Math.round(parseInt(node.style.left) + imgBounds.left) + "px"; node.style.top = Math.round(parseInt(node.style.top) - imgBounds.bottom) + "px"; }, postDraw: function(node) { node.style.visibility = "visible"; var fillColor = node._style.fillColor; var strokeColor = node._style.strokeColor; if (fillColor == "none" && node.fillcolor != fillColor) { node.fillcolor = fillColor; } if (strokeColor == "none" && node.strokecolor != strokeColor) { node.strokecolor = strokeColor; } }, setNodeDimension: function(node, geometry) { var bbox = geometry.getBounds(); if (bbox) { var resolution = this.getResolution(); var scaledBox = new OpenLayers.Bounds( ((bbox.left - this.featureDx) / resolution - this.offset.x) | 0, (bbox.bottom / resolution - this.offset.y) | 0, ((bbox.right - this.featureDx) / resolution - this.offset.x) | 0, (bbox.top / resolution - this.offset.y) | 0 ); node.style.left = scaledBox.left + "px"; node.style.top = scaledBox.top + "px"; node.style.width = scaledBox.getWidth() + "px"; node.style.height = scaledBox.getHeight() + "px"; node.coordorigin = scaledBox.left + " " + scaledBox.top; node.coordsize = scaledBox.getWidth() + " " + scaledBox.getHeight(); } }, dashStyle: function(style) { var dash = style.strokeDashstyle; switch (dash) { case "solid": case "dot": case "dash": case "dashdot": case "longdash": case "longdashdot": return dash; default: var parts = dash.split(/[ ,]/); if (parts.length == 2) { if (1 * parts[0] >= 2 * parts[1]) { return "longdash"; } return parts[0] == 1 || parts[1] == 1 ? "dot" : "dash"; } else if (parts.length == 4) { return 1 * parts[0] >= 2 * parts[1] ? "longdashdot" : "dashdot"; } return "solid"; } }, createNode: function(type, id) { var node = document.createElement(type); if (id) { node.id = id; } node.unselectable = "on"; node.onselectstart = OpenLayers.Function.False; return node; }, nodeTypeCompare: function(node, type) { var subType = type; var splitIndex = subType.indexOf(":"); if (splitIndex != -1) { subType = subType.substr(splitIndex + 1); } var nodeName = node.nodeName; splitIndex = nodeName.indexOf(":"); if (splitIndex != -1) { nodeName = nodeName.substr(splitIndex + 1); } return subType == nodeName; }, createRenderRoot: function() { return this.nodeFactory(this.container.id + "_vmlRoot", "div"); }, createRoot: function(suffix) { return this.nodeFactory(this.container.id + suffix, "olv:group"); }, drawPoint: function(node, geometry) { return this.drawCircle(node, geometry, 1); }, drawCircle: function(node, geometry, radius) { if (!isNaN(geometry.x) && !isNaN(geometry.y)) { var resolution = this.getResolution(); node.style.left = (((geometry.x - this.featureDx) / resolution - this.offset.x) | 0) - radius + "px"; node.style.top = ((geometry.y / resolution - this.offset.y) | 0) - radius + "px"; var diameter = radius * 2; node.style.width = diameter + "px"; node.style.height = diameter + "px"; return node; } return false; }, drawLineString: function(node, geometry) { return this.drawLine(node, geometry, false); }, drawLinearRing: function(node, geometry) { return this.drawLine(node, geometry, true); }, drawLine: function(node, geometry, closeLine) { this.setNodeDimension(node, geometry); var resolution = this.getResolution(); var numComponents = geometry.components.length; var parts = new Array(numComponents); var comp, x, y; for (var i = 0; i < numComponents; i++) { comp = geometry.components[i]; x = ((comp.x - this.featureDx) / resolution - this.offset.x) | 0; y = (comp.y / resolution - this.offset.y) | 0; parts[i] = " " + x + "," + y + " l "; } var end = closeLine ? " x e" : " e"; node.path = "m" + parts.join("") + end; return node; }, drawPolygon: function(node, geometry) { this.setNodeDimension(node, geometry); var resolution = this.getResolution(); var path = []; var j, jj, points, area, first, second, i, ii, comp, pathComp, x, y; for (j = 0, jj = geometry.components.length; j < jj; j++) { path.push("m"); points = geometry.components[j].components; area = j === 0; first = null; second = null; for (i = 0, ii = points.length; i < ii; i++) { comp = points[i]; x = ((comp.x - this.featureDx) / resolution - this.offset.x) | 0; y = (comp.y / resolution - this.offset.y) | 0; pathComp = " " + x + "," + y; path.push(pathComp); if (i == 0) { path.push(" l"); } if (!area) { if (!first) { first = pathComp; } else if (first != pathComp) { if (!second) { second = pathComp; } else if (second != pathComp) { area = true; } } } } path.push(area ? " x " : " "); } path.push("e"); node.path = path.join(""); return node; }, drawRectangle: function(node, geometry) { var resolution = this.getResolution(); node.style.left = (((geometry.x - this.featureDx) / resolution - this.offset.x) | 0) + "px"; node.style.top = ((geometry.y / resolution - this.offset.y) | 0) + "px"; node.style.width = ((geometry.width / resolution) | 0) + "px"; node.style.height = ((geometry.height / resolution) | 0) + "px"; return node; }, drawText: function(featureId, style, location) { var label = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX, "olv:rect"); var textbox = this.nodeFactory( featureId + this.LABEL_ID_SUFFIX + "_textbox", "olv:textbox" ); var resolution = this.getResolution(); label.style.left = (((location.x - this.featureDx) / resolution - this.offset.x) | 0) + "px"; label.style.top = ((location.y / resolution - this.offset.y) | 0) + "px"; label.style.flip = "y"; textbox.innerText = style.label; if (style.cursor != "inherit" && style.cursor != null) { textbox.style.cursor = style.cursor; } if (style.fontColor) { textbox.style.color = style.fontColor; } if (style.fontOpacity) { textbox.style.filter = "alpha(opacity=" + style.fontOpacity * 100 + ")"; } if (style.fontFamily) { textbox.style.fontFamily = style.fontFamily; } if (style.fontSize) { textbox.style.fontSize = style.fontSize; } if (style.fontWeight) { textbox.style.fontWeight = style.fontWeight; } if (style.fontStyle) { textbox.style.fontStyle = style.fontStyle; } if (style.labelSelect === true) { label._featureId = featureId; textbox._featureId = featureId; textbox._geometry = location; textbox._geometryClass = location.CLASS_NAME; } textbox.style.whiteSpace = "nowrap"; textbox.inset = "1px,0px,0px,0px"; if (!label.parentNode) { label.appendChild(textbox); this.textRoot.appendChild(label); } var align = style.labelAlign || "cm"; if (align.length == 1) { align += "m"; } var xshift = textbox.clientWidth * OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(0, 1)]; var yshift = textbox.clientHeight * OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(1, 1)]; label.style.left = parseInt(label.style.left) - xshift - 1 + "px"; label.style.top = parseInt(label.style.top) + yshift + "px"; }, moveRoot: function(renderer) { var layer = this.map.getLayer(renderer.container.id); if (layer instanceof OpenLayers.Layer.Vector.RootContainer) { layer = this.map.getLayer(this.container.id); } layer && layer.renderer.clear(); OpenLayers.Renderer.Elements.prototype.moveRoot.apply(this, arguments); layer && layer.redraw(); }, importSymbol: function(graphicName) { var id = this.container.id + "-" + graphicName; var cache = this.symbolCache[id]; if (cache) { return cache; } var symbol = OpenLayers.Renderer.symbol[graphicName]; if (!symbol) { throw new Error(graphicName + " is not a valid symbol name"); } var symbolExtent = new OpenLayers.Bounds( Number.MAX_VALUE, Number.MAX_VALUE, 0, 0 ); var pathitems = ["m"]; for (var i = 0; i < symbol.length; i = i + 2) { var x = symbol[i]; var y = symbol[i + 1]; symbolExtent.left = Math.min(symbolExtent.left, x); symbolExtent.bottom = Math.min(symbolExtent.bottom, y); symbolExtent.right = Math.max(symbolExtent.right, x); symbolExtent.top = Math.max(symbolExtent.top, y); pathitems.push(x); pathitems.push(y); if (i == 0) { pathitems.push("l"); } } pathitems.push("x e"); var path = pathitems.join(" "); var diff = (symbolExtent.getWidth() - symbolExtent.getHeight()) / 2; if (diff > 0) { symbolExtent.bottom = symbolExtent.bottom - diff; symbolExtent.top = symbolExtent.top + diff; } else { symbolExtent.left = symbolExtent.left + diff; symbolExtent.right = symbolExtent.right - diff; } cache = { path: path, size: symbolExtent.getWidth(), left: symbolExtent.left, bottom: symbolExtent.bottom }; this.symbolCache[id] = cache; return cache; }, CLASS_NAME: "OpenLayers.Renderer.VML" }); OpenLayers.Renderer.VML.LABEL_SHIFT = { l: 0, c: 0.5, r: 1, t: 0, m: 0.5, b: 1 }; OpenLayers.Protocol = OpenLayers.Class({ format: null, options: null, autoDestroy: true, defaultFilter: null, initialize: function(options) { options = options || {}; OpenLayers.Util.extend(this, options); this.options = options; }, 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; }, destroy: function() { this.options = null; this.format = null; }, read: function(options) { options = options || {}; options.filter = this.mergeWithDefaultFilter(options.filter); }, create: function() {}, update: function() {}, delete: function() {}, commit: function() {}, abort: function(response) {}, createCallback: function(method, response, options) { return OpenLayers.Function.bind(function() { method.apply(this, [response, options]); }, this); }, CLASS_NAME: "OpenLayers.Protocol" }); OpenLayers.Protocol.Response = OpenLayers.Class({ code: null, requestType: null, last: true, features: null, data: null, reqFeatures: null, priv: null, error: null, initialize: function(options) { OpenLayers.Util.extend(this, options); }, success: function() { return this.code > 0; }, CLASS_NAME: "OpenLayers.Protocol.Response" }); OpenLayers.Protocol.Response.SUCCESS = 1; OpenLayers.Protocol.Response.FAILURE = 0; OpenLayers.Protocol.HTTP = OpenLayers.Class(OpenLayers.Protocol, { url: null, headers: null, params: null, callback: null, scope: null, readWithPOST: false, updateWithPOST: false, deleteWithPOST: false, wildcarded: false, srsInBBOX: false, initialize: function(options) { options = options || {}; this.params = {}; this.headers = {}; OpenLayers.Protocol.prototype.initialize.apply(this, arguments); if (!this.filterToParams && OpenLayers.Format.QueryStringFilter) { var format = new OpenLayers.Format.QueryStringFilter({ wildcarded: this.wildcarded, srsInBBOX: this.srsInBBOX }); this.filterToParams = function(filter, params) { return format.write(filter, params); }; } }, destroy: function() { this.params = null; this.headers = null; OpenLayers.Protocol.prototype.destroy.apply(this); }, read: function(options) { OpenLayers.Protocol.prototype.read.apply(this, arguments); options = options || {}; options.params = OpenLayers.Util.applyDefaults( options.params, this.options.params ); options = OpenLayers.Util.applyDefaults(options, this.options); if (options.filter && this.filterToParams) { options.params = this.filterToParams(options.filter, options.params); } var readWithPOST = options.readWithPOST !== undefined ? options.readWithPOST : this.readWithPOST; var resp = new OpenLayers.Protocol.Response({ requestType: "read" }); if (readWithPOST) { var headers = options.headers || {}; headers["Content-Type"] = "application/x-www-form-urlencoded"; resp.priv = OpenLayers.Request.POST({ url: options.url, callback: this.createCallback(this.handleRead, resp, options), data: OpenLayers.Util.getParameterString(options.params), headers: headers }); } else { resp.priv = OpenLayers.Request.GET({ url: options.url, callback: this.createCallback(this.handleRead, resp, options), params: options.params, headers: options.headers }); } return resp; }, handleRead: function(resp, options) { this.handleResponse(resp, options); }, create: function(features, options) { options = OpenLayers.Util.applyDefaults(options, this.options); var resp = new OpenLayers.Protocol.Response({ reqFeatures: features, requestType: "create" }); resp.priv = OpenLayers.Request.POST({ url: options.url, callback: this.createCallback(this.handleCreate, resp, options), headers: options.headers, data: this.format.write(features) }); return resp; }, handleCreate: function(resp, options) { this.handleResponse(resp, options); }, update: function(feature, options) { options = options || {}; var url = options.url || feature.url || this.options.url + "/" + feature.fid; options = OpenLayers.Util.applyDefaults(options, this.options); var resp = new OpenLayers.Protocol.Response({ reqFeatures: feature, requestType: "update" }); var method = this.updateWithPOST ? "POST" : "PUT"; resp.priv = OpenLayers.Request[method]({ url: url, callback: this.createCallback(this.handleUpdate, resp, options), headers: options.headers, data: this.format.write(feature) }); return resp; }, handleUpdate: function(resp, options) { this.handleResponse(resp, options); }, delete: function(feature, options) { options = options || {}; var url = options.url || feature.url || this.options.url + "/" + feature.fid; options = OpenLayers.Util.applyDefaults(options, this.options); var resp = new OpenLayers.Protocol.Response({ reqFeatures: feature, requestType: "delete" }); var method = this.deleteWithPOST ? "POST" : "DELETE"; var requestOptions = { url: url, callback: this.createCallback(this.handleDelete, resp, options), headers: options.headers }; if (this.deleteWithPOST) { requestOptions.data = this.format.write(feature); } resp.priv = OpenLayers.Request[method](requestOptions); return resp; }, handleDelete: function(resp, options) { this.handleResponse(resp, options); }, handleResponse: function(resp, options) { var request = resp.priv; if (options.callback) { if (request.status >= 200 && request.status < 300) { if (resp.requestType != "delete") { resp.features = this.parseFeatures(request); } resp.code = OpenLayers.Protocol.Response.SUCCESS; } else { resp.code = OpenLayers.Protocol.Response.FAILURE; } options.callback.call(options.scope, resp); } }, parseFeatures: function(request) { var doc = request.responseXML; if (!doc || !doc.documentElement) { doc = request.responseText; } if (!doc || doc.length <= 0) { return null; } return this.format.read(doc); }, commit: function(features, options) { options = OpenLayers.Util.applyDefaults(options, this.options); var resp = [], nResponses = 0; var types = {}; types[OpenLayers.State.INSERT] = []; types[OpenLayers.State.UPDATE] = []; types[OpenLayers.State.DELETE] = []; var feature, list, requestFeatures = []; for (var i = 0, len = features.length; i < len; ++i) { feature = features[i]; list = types[feature.state]; if (list) { list.push(feature); requestFeatures.push(feature); } } var nRequests = (types[OpenLayers.State.INSERT].length > 0 ? 1 : 0) + types[OpenLayers.State.UPDATE].length + types[OpenLayers.State.DELETE].length; var success = true; var finalResponse = new OpenLayers.Protocol.Response({ reqFeatures: requestFeatures }); function insertCallback(response) { var len = response.features ? response.features.length : 0; var fids = new Array(len); for (var i = 0; i < len; ++i) { fids[i] = response.features[i].fid; } finalResponse.insertIds = fids; callback.apply(this, [response]); } function callback(response) { this.callUserCallback(response, options); success = success && response.success(); nResponses++; if (nResponses >= nRequests) { if (options.callback) { finalResponse.code = success ? OpenLayers.Protocol.Response.SUCCESS : OpenLayers.Protocol.Response.FAILURE; options.callback.apply(options.scope, [finalResponse]); } } } var queue = types[OpenLayers.State.INSERT]; if (queue.length > 0) { resp.push( this.create( queue, OpenLayers.Util.applyDefaults( { callback: insertCallback, scope: this }, options.create ) ) ); } queue = types[OpenLayers.State.UPDATE]; for (var i = queue.length - 1; i >= 0; --i) { resp.push( this.update( queue[i], OpenLayers.Util.applyDefaults( { callback: callback, scope: this }, options.update ) ) ); } queue = types[OpenLayers.State.DELETE]; for (var i = queue.length - 1; i >= 0; --i) { resp.push( this["delete"]( queue[i], OpenLayers.Util.applyDefaults( { callback: callback, scope: this }, options["delete"] ) ) ); } return resp; }, abort: function(response) { if (response) { response.priv.abort(); } }, callUserCallback: function(resp, options) { var opt = options[resp.requestType]; if (opt && opt.callback) { opt.callback.call(opt.scope, resp); } }, CLASS_NAME: "OpenLayers.Protocol.HTTP" }); OpenLayers.Control.LayerSwitcher = OpenLayers.Class(OpenLayers.Control, { roundedCorner: false, roundedCornerColor: "darkblue", layerStates: null, layersDiv: null, baseLayersDiv: null, baseLayers: null, dataLbl: null, dataLayersDiv: null, dataLayers: null, minimizeDiv: null, maximizeDiv: null, ascending: true, initialize: function(options) { OpenLayers.Control.prototype.initialize.apply(this, arguments); this.layerStates = []; if (this.roundedCorner) { OpenLayers.Console.warn("roundedCorner option is deprecated"); } }, destroy: function() { this.clearLayersArray("base"); this.clearLayersArray("data"); this.map.events.un({ buttonclick: this.onButtonClick, addlayer: this.redraw, changelayer: this.redraw, removelayer: this.redraw, changebaselayer: this.redraw, scope: this }); this.events.unregister("buttonclick", this, this.onButtonClick); OpenLayers.Control.prototype.destroy.apply(this, arguments); }, setMap: function(map) { OpenLayers.Control.prototype.setMap.apply(this, arguments); this.map.events.on({ addlayer: this.redraw, changelayer: this.redraw, removelayer: this.redraw, changebaselayer: this.redraw, scope: this }); if (this.outsideViewport) { this.events.attachToElement(this.div); this.events.register("buttonclick", this, this.onButtonClick); } else { this.map.events.register("buttonclick", this, this.onButtonClick); } }, draw: function() { OpenLayers.Control.prototype.draw.apply(this); this.loadContents(); if (!this.outsideViewport) { this.minimizeControl(); } this.redraw(); return this.div; }, onButtonClick: function(evt) { var button = evt.buttonElement; if (button === this.minimizeDiv) { this.minimizeControl(); } else if (button === this.maximizeDiv) { this.maximizeControl(); } else if (button._layerSwitcher === this.id) { if (button["for"]) { button = document.getElementById(button["for"]); } if (!button.disabled) { if (button.type == "radio") { button.checked = true; this.map.setBaseLayer(this.map.getLayer(button._layer)); } else { button.checked = !button.checked; this.updateMap(); } } } }, clearLayersArray: function(layersType) { this[layersType + "LayersDiv"].innerHTML = ""; this[layersType + "Layers"] = []; }, checkRedraw: function() { var redraw = false; if ( !this.layerStates.length || this.map.layers.length != this.layerStates.length ) { redraw = true; } else { for (var i = 0, len = this.layerStates.length; i < len; i++) { var layerState = this.layerStates[i]; var layer = this.map.layers[i]; if ( layerState.name != layer.name || layerState.inRange != layer.inRange || layerState.id != layer.id || layerState.visibility != layer.visibility ) { redraw = true; break; } } } return redraw; }, redraw: function() { if (!this.checkRedraw()) { return this.div; } this.clearLayersArray("base"); this.clearLayersArray("data"); var containsOverlays = false; var containsBaseLayers = false; var len = this.map.layers.length; this.layerStates = new Array(len); for (var i = 0; i < len; i++) { var layer = this.map.layers[i]; this.layerStates[i] = { name: layer.name, visibility: layer.visibility, inRange: layer.inRange, id: layer.id }; } var layers = this.map.layers.slice(); if (!this.ascending) { layers.reverse(); } for (var i = 0, len = layers.length; i < len; i++) { var layer = layers[i]; var baseLayer = layer.isBaseLayer; if (layer.displayInLayerSwitcher) { if (baseLayer) { containsBaseLayers = true; } else { containsOverlays = true; } var checked = baseLayer ? layer == this.map.baseLayer : layer.getVisibility(); var inputElem = document.createElement("input"); inputElem.id = this.id + "_input_" + layer.name; inputElem.name = baseLayer ? this.id + "_baseLayers" : layer.name; inputElem.type = baseLayer ? "radio" : "checkbox"; inputElem.value = layer.name; inputElem.checked = checked; inputElem.defaultChecked = checked; inputElem.className = "olButton"; inputElem._layer = layer.id; inputElem._layerSwitcher = this.id; if (!baseLayer && !layer.inRange) { inputElem.disabled = true; } var labelSpan = document.createElement("label"); labelSpan["for"] = inputElem.id; OpenLayers.Element.addClass(labelSpan, "labelSpan olButton"); labelSpan._layer = layer.id; labelSpan._layerSwitcher = this.id; if (!baseLayer && !layer.inRange) { labelSpan.style.color = "gray"; } labelSpan.innerHTML = layer.name; labelSpan.style.verticalAlign = baseLayer ? "bottom" : "baseline"; var br = document.createElement("br"); var groupArray = baseLayer ? this.baseLayers : this.dataLayers; groupArray.push({ layer: layer, inputElem: inputElem, labelSpan: labelSpan }); var groupDiv = baseLayer ? this.baseLayersDiv : this.dataLayersDiv; groupDiv.appendChild(inputElem); groupDiv.appendChild(labelSpan); groupDiv.appendChild(br); } } this.dataLbl.style.display = containsOverlays ? "" : "none"; this.baseLbl.style.display = containsBaseLayers ? "" : "none"; return this.div; }, updateMap: function() { for (var i = 0, len = this.baseLayers.length; i < len; i++) { var layerEntry = this.baseLayers[i]; if (layerEntry.inputElem.checked) { this.map.setBaseLayer(layerEntry.layer, false); } } for (var i = 0, len = this.dataLayers.length; i < len; i++) { var layerEntry = this.dataLayers[i]; layerEntry.layer.setVisibility(layerEntry.inputElem.checked); } }, maximizeControl: function(e) { this.div.style.width = ""; this.div.style.height = ""; this.showControls(false); if (e != null) { OpenLayers.Event.stop(e); } }, minimizeControl: function(e) { this.div.style.width = "0px"; this.div.style.height = "0px"; this.showControls(true); if (e != null) { OpenLayers.Event.stop(e); } }, showControls: function(minimize) { this.maximizeDiv.style.display = minimize ? "" : "none"; this.minimizeDiv.style.display = minimize ? "none" : ""; this.layersDiv.style.display = minimize ? "none" : ""; }, loadContents: function() { this.layersDiv = document.createElement("div"); this.layersDiv.id = this.id + "_layersDiv"; OpenLayers.Element.addClass(this.layersDiv, "layersDiv"); this.baseLbl = document.createElement("div"); this.baseLbl.innerHTML = OpenLayers.i18n("Base Layer"); OpenLayers.Element.addClass(this.baseLbl, "baseLbl"); this.baseLayersDiv = document.createElement("div"); OpenLayers.Element.addClass(this.baseLayersDiv, "baseLayersDiv"); this.dataLbl = document.createElement("div"); this.dataLbl.innerHTML = OpenLayers.i18n("Overlays"); OpenLayers.Element.addClass(this.dataLbl, "dataLbl"); this.dataLayersDiv = document.createElement("div"); OpenLayers.Element.addClass(this.dataLayersDiv, "dataLayersDiv"); if (this.ascending) { this.layersDiv.appendChild(this.baseLbl); this.layersDiv.appendChild(this.baseLayersDiv); this.layersDiv.appendChild(this.dataLbl); this.layersDiv.appendChild(this.dataLayersDiv); } else { this.layersDiv.appendChild(this.dataLbl); this.layersDiv.appendChild(this.dataLayersDiv); this.layersDiv.appendChild(this.baseLbl); this.layersDiv.appendChild(this.baseLayersDiv); } this.div.appendChild(this.layersDiv); if (this.roundedCorner) { OpenLayers.Rico.Corner.round(this.div, { corners: "tl bl", bgColor: "transparent", color: this.roundedCornerColor, blend: false }); OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.75); } var img = OpenLayers.Util.getImageLocation("layer-switcher-maximize.png"); this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv( "OpenLayers_Control_MaximizeDiv", null, null, img, "absolute" ); OpenLayers.Element.addClass(this.maximizeDiv, "maximizeDiv olButton"); this.maximizeDiv.style.display = "none"; this.div.appendChild(this.maximizeDiv); var img = OpenLayers.Util.getImageLocation("layer-switcher-minimize.png"); this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv( "OpenLayers_Control_MinimizeDiv", null, null, img, "absolute" ); OpenLayers.Element.addClass(this.minimizeDiv, "minimizeDiv olButton"); this.minimizeDiv.style.display = "none"; this.div.appendChild(this.minimizeDiv); }, CLASS_NAME: "OpenLayers.Control.LayerSwitcher" });