Delete old OpenLayers folder.
authorPhilipp Spitzer <philipp@spitzer.priv.at>
Mon, 11 Jan 2021 22:22:16 +0000 (23:22 +0100)
committerPhilipp Spitzer <philipp@spitzer.priv.at>
Mon, 11 Jan 2021 22:22:16 +0000 (23:22 +0100)
openlayers/OpenLayers.js [deleted file]
openlayers/OpenLayers.min.js [deleted file]
openlayers/wrmap.cfg [deleted file]

diff --git a/openlayers/OpenLayers.js b/openlayers/OpenLayers.js
deleted file mode 100644 (file)
index 8d47f6d..0000000
+++ /dev/null
@@ -1,43516 +0,0 @@
-/*
-
-  OpenLayers.js -- OpenLayers Map Viewer Library
-
-  Copyright (c) 2006-2015 by OpenLayers Contributors
-  Published under the 2-clause BSD license.
-  See https://raw.githubusercontent.com/openlayers/ol2/master/license.txt for the full text of the license, and https://raw.githubusercontent.com/openlayers/ol2/master/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: <https://github.com/openlayers/ol2>)
-
-*/
-
-/**
- * Contains XMLHttpRequest.js <http://code.google.com/p/xmlhttprequest/>
- * Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- */
-
-/**
- * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
- * Copyright (c) 2006, Yahoo! Inc.
- * All rights reserved.
- *
- * Redistribution and use of this software in source and binary forms, with or
- * without modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- *
- * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
- *   used to endorse or promote products derived from this software without
- *   specific prior written permission of Yahoo! Inc.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-/* ======================================================================
-    OpenLayers/SingleFile.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-var OpenLayers = {
-    /**
-     * Constant: VERSION_NUMBER
-     */
-    VERSION_NUMBER: "Release 2.14 dev",
-
-    /**
-     * Constant: singleFile
-     * TODO: remove this in 3.0 when we stop supporting build profiles that
-     * include OpenLayers.js
-     */
-    singleFile: true,
-
-    /**
-     * Method: _getScriptLocation
-     * Return the path to this script. This is also implemented in
-     * OpenLayers.js
-     *
-     * Returns:
-     * {String} Path to this script
-     */
-    _getScriptLocation: (function() {
-        var r = new RegExp("(^|(.*?\\/))(OpenLayers[^\\/]*?\\.js)(\\?|$)"),
-            s = document.getElementsByTagName('script'),
-            src, m, l = "";
-        for(var i=0, len=s.length; i<len; i++) {
-            src = s[i].getAttribute('src');
-            if(src) {
-                m = src.match(r);
-                if(m) {
-                    l = m[1];
-                    break;
-                }
-            }
-        }
-        return (function() { return l; });
-    })(),
-    
-    /**
-     * Property: ImgPath
-     * {String} Set this to the path where control images are stored, a path  
-     * given here must end with a slash. If set to '' (which is the default) 
-     * OpenLayers will use its script location + "img/".
-     * 
-     * You will need to set this property when you have a singlefile build of 
-     * OpenLayers that either is not named "OpenLayers.js" or if you move
-     * the file in a way such that the image directory cannot be derived from 
-     * the script location.
-     * 
-     * If your custom OpenLayers build is named "my-custom-ol.js" and the images
-     * of OpenLayers are in a folder "/resources/external/images/ol" a correct
-     * way of including OpenLayers in your HTML would be:
-     * 
-     * (code)
-     *   <script src="/path/to/my-custom-ol.js" type="text/javascript"></script>
-     *   <script type="text/javascript">
-     *      // tell OpenLayers where the control images are
-     *      // remember the trailing slash
-     *      OpenLayers.ImgPath = "/resources/external/images/ol/";
-     *   </script>
-     * (end code)
-     * 
-     * Please remember that when your OpenLayers script is not named 
-     * "OpenLayers.js" you will have to make sure that the default theme is 
-     * loaded into the page by including an appropriate <link>-tag, 
-     * e.g.:
-     * 
-     * (code)
-     *   <link rel="stylesheet" href="/path/to/default/style.css"  type="text/css">
-     * (end code)
-     */
-    ImgPath : ''
-};
-/* ======================================================================
-    OpenLayers/BaseTypes/Class.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/SingleFile.js
- */
-
-/**
- * Constructor: OpenLayers.Class
- * Base class used to construct all other classes. Includes support for 
- *     multiple inheritance. 
- *     
- * This constructor is new in OpenLayers 2.5.  At OpenLayers 3.0, the old 
- *     syntax for creating classes and dealing with inheritance 
- *     will be removed.
- * 
- * To create a new OpenLayers-style class, use the following syntax:
- * (code)
- *     var MyClass = OpenLayers.Class(prototype);
- * (end)
- *
- * To create a new OpenLayers-style class with multiple inheritance, use the
- *     following syntax:
- * (code)
- *     var MyClass = OpenLayers.Class(Class1, Class2, prototype);
- * (end)
- * 
- * Note that instanceof reflection will only reveal Class1 as superclass.
- *
- */
-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;
-};
-
-/**
- * Function: OpenLayers.inherit
- *
- * Parameters:
- * C - {Object} the class that inherits
- * P - {Object} the superclass to inherit from
- *
- * In addition to the mandatory C and P parameters, an arbitrary number of
- * objects can be passed, which will extend C.
- */
-OpenLayers.inherit = function(C, P) {
-   var F = function() {};
-   F.prototype = P.prototype;
-   C.prototype = new F;
-   var i, l, o;
-   for(i=2, l=arguments.length; i<l; i++) {
-       o = arguments[i];
-       if(typeof o === "function") {
-           o = o.prototype;
-       }
-       OpenLayers.Util.extend(C.prototype, o);
-   }
-};
-
-/**
- * APIFunction: extend
- * Copy all properties of a source object to a destination object.  Modifies
- *     the passed in destination object.  Any properties on the source object
- *     that are set to undefined will not be (re)set on the destination object.
- *
- * Parameters:
- * destination - {Object} The object that will be modified
- * source - {Object} The object with properties to be set on the destination
- *
- * Returns:
- * {Object} The destination object.
- */
-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;
-            }
-        }
-
-        /**
-         * IE doesn't include the toString property when iterating over an object's
-         * properties with the for(property in object) syntax.  Explicitly check if
-         * the source has its own toString property.
-         */
-
-        /*
-         * FF/Windows < 2.0.0.13 reports "Illegal operation on WrappedNative
-         * prototype object" when calling hawOwnProperty if the source object
-         * is an instance of window.Event.
-         */
-
-        var sourceIsEvt = typeof window.Event == "function"
-                          && source instanceof window.Event;
-
-        if (!sourceIsEvt
-           && source.hasOwnProperty && source.hasOwnProperty("toString")) {
-            destination.toString = source.toString;
-        }
-    }
-    return destination;
-};
-/* ======================================================================
-    OpenLayers/BaseTypes.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/SingleFile.js
- */
-
-/** 
- * Header: OpenLayers Base Types
- * OpenLayers custom string, number and function functions are described here.
- */
-
-/**
- * Namespace: OpenLayers.String
- * Contains convenience functions for string manipulation.
- */
-OpenLayers.String = {
-
-    /**
-     * APIFunction: startsWith
-     * Test whether a string starts with another string. 
-     * 
-     * Parameters:
-     * str - {String} The string to test.
-     * sub - {String} The substring to look for.
-     *  
-     * Returns:
-     * {Boolean} The first string starts with the second.
-     */
-    startsWith: function(str, sub) {
-        return (str.indexOf(sub) == 0);
-    },
-
-    /**
-     * APIFunction: contains
-     * Test whether a string contains another string.
-     * 
-     * Parameters:
-     * str - {String} The string to test.
-     * sub - {String} The substring to look for.
-     * 
-     * Returns:
-     * {Boolean} The first string contains the second.
-     */
-    contains: function(str, sub) {
-        return (str.indexOf(sub) != -1);
-    },
-    
-    /**
-     * APIFunction: trim
-     * Removes leading and trailing whitespace characters from a string.
-     * 
-     * Parameters:
-     * str - {String} The (potentially) space padded string.  This string is not
-     *     modified.
-     * 
-     * Returns:
-     * {String} A trimmed version of the string with all leading and 
-     *     trailing spaces removed.
-     */
-    trim: function(str) {
-        return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
-    },
-    
-    /**
-     * APIFunction: camelize
-     * Camel-case a hyphenated string. 
-     *     Ex. "chicken-head" becomes "chickenHead", and
-     *     "-chicken-head" becomes "ChickenHead".
-     *
-     * Parameters:
-     * str - {String} The string to be camelized.  The original is not modified.
-     * 
-     * Returns:
-     * {String} The string, camelized
-     */
-    camelize: function(str) {
-        var oStringList = str.split('-');
-        var camelizedString = oStringList[0];
-        for (var i=1, len=oStringList.length; i<len; i++) {
-            var s = oStringList[i];
-            camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
-        }
-        return camelizedString;
-    },
-    
-    /**
-     * APIFunction: format
-     * Given a string with tokens in the form ${token}, return a string
-     *     with tokens replaced with properties from the given context
-     *     object.  Represent a literal "${" by doubling it, e.g. "${${".
-     *
-     * Parameters:
-     * template - {String} A string with tokens to be replaced.  A template
-     *     has the form "literal ${token}" where the token will be replaced
-     *     by the value of context["token"].
-     * context - {Object} An optional object with properties corresponding
-     *     to the tokens in the format string.  If no context is sent, the
-     *     window object will be used.
-     * args - {Array} Optional arguments to pass to any functions found in
-     *     the context.  If a context property is a function, the token
-     *     will be replaced by the return from the function called with
-     *     these arguments.
-     *
-     * Returns:
-     * {String} A string with tokens replaced from the context object.
-     */
-    format: function(template, context, args) {
-        if(!context) {
-            context = window;
-        }
-
-        // Example matching: 
-        // str   = ${foo.bar}
-        // match = foo.bar
-        var replacer = function(str, match) {
-            var replacement;
-
-            // Loop through all subs. Example: ${a.b.c}
-            // 0 -> replacement = context[a];
-            // 1 -> replacement = context[a][b];
-            // 2 -> replacement = context[a][b][c];
-            var subs = match.split(/\.+/);
-            for (var i=0; i< subs.length; i++) {
-                if (i == 0) {
-                    replacement = context;
-                }
-                if (replacement === undefined) {
-                    break;
-                }
-                replacement = replacement[subs[i]];
-            }
-
-            if(typeof replacement == "function") {
-                replacement = args ?
-                    replacement.apply(null, args) :
-                    replacement();
-            }
-
-            // If replacement is undefined, return the string 'undefined'.
-            // This is a workaround for a bugs in browsers not properly 
-            // dealing with non-participating groups in regular expressions:
-            // http://blog.stevenlevithan.com/archives/npcg-javascript
-            if (typeof replacement == 'undefined') {
-                return 'undefined';
-            } else {
-                return replacement; 
-            }
-        };
-
-        return template.replace(OpenLayers.String.tokenRegEx, replacer);
-    },
-
-    /**
-     * Property: tokenRegEx
-     * Used to find tokens in a string.
-     * Examples: ${a}, ${a.b.c}, ${a-b}, ${5}
-     */
-    tokenRegEx:  /\$\{([\w.]+?)\}/g,
-    
-    /**
-     * Property: numberRegEx
-     * Used to test strings as numbers.
-     */
-    numberRegEx: /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,
-    
-    /**
-     * APIFunction: isNumeric
-     * Determine whether a string contains only a numeric value.
-     *
-     * Examples:
-     * (code)
-     * OpenLayers.String.isNumeric("6.02e23") // true
-     * OpenLayers.String.isNumeric("12 dozen") // false
-     * OpenLayers.String.isNumeric("4") // true
-     * OpenLayers.String.isNumeric(" 4 ") // false
-     * (end)
-     *
-     * Returns:
-     * {Boolean} String contains only a number.
-     */
-    isNumeric: function(value) {
-        return OpenLayers.String.numberRegEx.test(value);
-    },
-    
-    /**
-     * APIFunction: numericIf
-     * Converts a string that appears to be a numeric value into a number.
-     * 
-     * Parameters:
-     * value - {String}
-     * trimWhitespace - {Boolean}
-     *
-     * Returns:
-     * {Number|String} a Number if the passed value is a number, a String
-     *     otherwise. 
-     */
-    numericIf: function(value, trimWhitespace) {
-        var originalValue = value;
-        if (trimWhitespace === true && value != null && value.replace) {
-            value = value.replace(/^\s*|\s*$/g, "");
-        }
-        return OpenLayers.String.isNumeric(value) ? parseFloat(value) : originalValue;
-    }
-
-};
-
-/**
- * Namespace: OpenLayers.Number
- * Contains convenience functions for manipulating numbers.
- */
-OpenLayers.Number = {
-
-    /**
-     * Property: decimalSeparator
-     * Decimal separator to use when formatting numbers.
-     */
-    decimalSeparator: ".",
-    
-    /**
-     * Property: thousandsSeparator
-     * Thousands separator to use when formatting numbers.
-     */
-    thousandsSeparator: ",",
-    
-    /**
-     * APIFunction: limitSigDigs
-     * Limit the number of significant digits on a float.
-     * 
-     * Parameters:
-     * num - {Float}
-     * sig - {Integer}
-     * 
-     * Returns:
-     * {Float} The number, rounded to the specified number of significant
-     *     digits.
-     */
-    limitSigDigs: function(num, sig) {
-        var fig = 0;
-        if (sig > 0) {
-            fig = parseFloat(num.toPrecision(sig));
-        }
-        return fig;
-    },
-    
-    /**
-     * APIFunction: format
-     * Formats a number for output.
-     * 
-     * Parameters:
-     * num  - {Float}
-     * dec  - {Integer} Number of decimal places to round to.
-     *        Defaults to 0. Set to null to leave decimal places unchanged.
-     * tsep - {String} Thousands separator.
-     *        Default is ",".
-     * dsep - {String} Decimal separator.
-     *        Default is ".".
-     *
-     * Returns:
-     * {String} A string representing the formatted number.
-     */
-    format: function(num, dec, tsep, dsep) {
-        dec = (typeof dec != "undefined") ? dec : 0; 
-        tsep = (typeof tsep != "undefined") ? tsep :
-            OpenLayers.Number.thousandsSeparator; 
-        dsep = (typeof dsep != "undefined") ? dsep :
-            OpenLayers.Number.decimalSeparator;
-
-        if (dec != null) {
-            num = parseFloat(num.toFixed(dec));
-        }
-
-        var parts = num.toString().split(".");
-        if (parts.length == 1 && dec == null) {
-            // integer where we do not want to touch the decimals
-            dec = 0;
-        }
-        
-        var integer = parts[0];
-        if (tsep) {
-            var thousands = /(-?[0-9]+)([0-9]{3})/; 
-            while(thousands.test(integer)) { 
-                integer = integer.replace(thousands, "$1" + tsep + "$2"); 
-            }
-        }
-        
-        var str;
-        if (dec == 0) {
-            str = integer;
-        } else {
-            var rem = parts.length > 1 ? parts[1] : "0";
-            if (dec != null) {
-                rem = rem + new Array(dec - rem.length + 1).join("0");
-            }
-            str = integer + dsep + rem;
-        }
-        return str;
-    },
-
-    /**
-     * Method: zeroPad
-     * Create a zero padded string optionally with a radix for casting numbers.
-     *
-     * Parameters:
-     * num - {Number} The number to be zero padded.
-     * len - {Number} The length of the string to be returned.
-     * radix - {Number} An integer between 2 and 36 specifying the base to use
-     *     for representing numeric values.
-     */
-    zeroPad: function(num, len, radix) {
-        var str = num.toString(radix || 10);
-        while (str.length < len) {
-            str = "0" + str;
-        }
-        return str;
-    }    
-};
-
-/**
- * Namespace: OpenLayers.Function
- * Contains convenience functions for function manipulation.
- */
-OpenLayers.Function = {
-    /**
-     * APIFunction: bind
-     * Bind a function to an object.  Method to easily create closures with
-     *     'this' altered.
-     * 
-     * Parameters:
-     * func - {Function} Input function.
-     * object - {Object} The object to bind to the input function (as this).
-     * 
-     * Returns:
-     * {Function} A closure with 'this' set to the passed in object.
-     */
-    bind: function(func, object) {
-        // create a reference to all arguments past the second one
-        var args = Array.prototype.slice.call(arguments, 2);
-        return function() {
-            // Push on any additional arguments from the actual function call.
-            // These will come after those sent to the bind call.
-            var newArgs = args.concat(
-                Array.prototype.slice.call(arguments, 0)
-            );
-            return func.apply(object, newArgs);
-        };
-    },
-    
-    /**
-     * APIFunction: bindAsEventListener
-     * Bind a function to an object, and configure it to receive the event
-     *     object as first parameter when called. 
-     * 
-     * Parameters:
-     * func - {Function} Input function to serve as an event listener.
-     * object - {Object} A reference to this.
-     * 
-     * Returns:
-     * {Function}
-     */
-    bindAsEventListener: function(func, object) {
-        return function(event) {
-            return func.call(object, event || window.event);
-        };
-    },
-    
-    /**
-     * APIFunction: False
-     * A simple function to that just does "return false". We use this to 
-     * avoid attaching anonymous functions to DOM event handlers, which 
-     * causes "issues" on IE<8.
-     * 
-     * Usage:
-     * document.onclick = OpenLayers.Function.False;
-     * 
-     * Returns:
-     * {Boolean}
-     */
-    False : function() {
-        return false;
-    },
-
-    /**
-     * APIFunction: True
-     * A simple function to that just does "return true". We use this to 
-     * avoid attaching anonymous functions to DOM event handlers, which 
-     * causes "issues" on IE<8.
-     * 
-     * Usage:
-     * document.onclick = OpenLayers.Function.True;
-     * 
-     * Returns:
-     * {Boolean}
-     */
-    True : function() {
-        return true;
-    },
-    
-    /**
-     * APIFunction: Void
-     * A reusable function that returns ``undefined``.
-     *
-     * Returns:
-     * {undefined}
-     */
-    Void: function() {}
-
-};
-
-/**
- * Namespace: OpenLayers.Array
- * Contains convenience functions for array manipulation.
- */
-OpenLayers.Array = {
-
-    /**
-     * APIMethod: filter
-     * Filter an array.  Provides the functionality of the
-     *     Array.prototype.filter extension to the ECMA-262 standard.  Where
-     *     available, Array.prototype.filter will be used.
-     *
-     * Based on well known example from http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/filter
-     *
-     * Parameters:
-     * array - {Array} The array to be filtered.  This array is not mutated.
-     *     Elements added to this array by the callback will not be visited.
-     * callback - {Function} A function that is called for each element in
-     *     the array.  If this function returns true, the element will be
-     *     included in the return.  The function will be called with three
-     *     arguments: the element in the array, the index of that element, and
-     *     the array itself.  If the optional caller parameter is specified
-     *     the callback will be called with this set to caller.
-     * caller - {Object} Optional object to be set as this when the callback
-     *     is called.
-     *
-     * Returns:
-     * {Array} An array of elements from the passed in array for which the
-     *     callback returns true.
-     */
-    filter: function(array, callback, caller) {
-        var selected = [];
-        if (Array.prototype.filter) {
-            selected = array.filter(callback, caller);
-        } else {
-            var len = array.length;
-            if (typeof callback != "function") {
-                throw new TypeError();
-            }
-            for(var i=0; i<len; i++) {
-                if (i in array) {
-                    var val = array[i];
-                    if (callback.call(caller, val, i, array)) {
-                        selected.push(val);
-                    }
-                }
-            }        
-        }
-        return selected;
-    }
-    
-};
-/* ======================================================================
-    OpenLayers/BaseTypes/Bounds.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- */
-
-/**
- * Class: OpenLayers.Bounds
- * Instances of this class represent bounding boxes.  Data stored as left,
- * bottom, right, top floats. All values are initialized to null, however,
- * you should make sure you set them before using the bounds for anything.
- * 
- * Possible use case:
- * (code)
- *     bounds = new OpenLayers.Bounds();
- *     bounds.extend(new OpenLayers.LonLat(4,5));
- *     bounds.extend(new OpenLayers.LonLat(5,6));
- *     bounds.toBBOX(); // returns 4,5,5,6
- * (end)
- */
-OpenLayers.Bounds = OpenLayers.Class({
-
-    /**
-     * Property: left
-     * {Number} Minimum horizontal coordinate.
-     */
-    left: null,
-
-    /**
-     * Property: bottom
-     * {Number} Minimum vertical coordinate.
-     */
-    bottom: null,
-
-    /**
-     * Property: right
-     * {Number} Maximum horizontal coordinate.
-     */
-    right: null,
-
-    /**
-     * Property: top
-     * {Number} Maximum vertical coordinate.
-     */
-    top: null,
-    
-    /**
-     * Property: centerLonLat
-     * {<OpenLayers.LonLat>} A cached center location.  This should not be
-     *     accessed directly.  Use <getCenterLonLat> instead.
-     */
-    centerLonLat: null,
-
-    /**
-     * Constructor: OpenLayers.Bounds
-     * Construct a new bounds object. Coordinates can either be passed as four
-     * arguments, or as a single argument.
-     *
-     * Parameters (four arguments):
-     * left - {Number} The left bounds of the box.  Note that for width
-     *        calculations, this is assumed to be less than the right value.
-     * bottom - {Number} The bottom bounds of the box.  Note that for height
-     *          calculations, this is assumed to be less than the top value.
-     * right - {Number} The right bounds.
-     * top - {Number} The top bounds.
-     *
-     * Parameters (single argument):
-     * bounds - {Array(Number)} [left, bottom, right, top]
-     */
-    initialize: function(left, bottom, right, top) {
-        if (OpenLayers.Util.isArray(left)) {
-            top = left[3];
-            right = left[2];
-            bottom = left[1];
-            left = left[0];
-        }
-        if (left != null) {
-            this.left = OpenLayers.Util.toFloat(left);
-        }
-        if (bottom != null) {
-            this.bottom = OpenLayers.Util.toFloat(bottom);
-        }
-        if (right != null) {
-            this.right = OpenLayers.Util.toFloat(right);
-        }
-        if (top != null) {
-            this.top = OpenLayers.Util.toFloat(top);
-        }
-    },
-
-    /**
-     * Method: clone
-     * Create a cloned instance of this bounds.
-     *
-     * Returns:
-     * {<OpenLayers.Bounds>} A fresh copy of the bounds
-     */
-    clone:function() {
-        return new OpenLayers.Bounds(this.left, this.bottom, 
-                                     this.right, this.top);
-    },
-
-    /**
-     * Method: equals
-     * Test a two bounds for equivalence.
-     *
-     * Parameters:
-     * bounds - {<OpenLayers.Bounds>}
-     *
-     * Returns:
-     * {Boolean} The passed-in bounds object has the same left,
-     *           right, top, bottom components as this.  Note that if bounds 
-     *           passed in is null, returns false.
-     */
-    equals:function(bounds) {
-        var equals = false;
-        if (bounds != null) {
-            equals = ((this.left == bounds.left) && 
-                      (this.right == bounds.right) &&
-                      (this.top == bounds.top) && 
-                      (this.bottom == bounds.bottom));
-        }
-        return equals;
-    },
-
-    /** 
-     * APIMethod: toString
-     * Returns a string representation of the bounds object.
-     * 
-     * Returns:
-     * {String} String representation of bounds object. 
-     */
-    toString:function() {
-        return [this.left, this.bottom, this.right, this.top].join(",");
-    },
-
-    /**
-     * APIMethod: toArray
-     * Returns an array representation of the bounds object.
-     *
-     * Returns an array of left, bottom, right, top properties, or -- when the
-     *     optional parameter is true -- an array of the  bottom, left, top,
-     *     right properties.
-     *
-     * Parameters:
-     * reverseAxisOrder - {Boolean} Should we reverse the axis order?
-     *
-     * Returns:
-     * {Array} array of left, bottom, right, top
-     */
-    toArray: function(reverseAxisOrder) {
-        if (reverseAxisOrder === true) {
-            return [this.bottom, this.left, this.top, this.right];
-        } else {
-            return [this.left, this.bottom, this.right, this.top];
-        }
-    },    
-
-    /** 
-     * APIMethod: toBBOX
-     * Returns a boundingbox-string representation of the bounds object.
-     * 
-     * Parameters:
-     * decimal - {Integer} How many decimal places in the bbox coords?
-     *                     Default is 6
-     * reverseAxisOrder - {Boolean} Should we reverse the axis order?
-     * 
-     * Returns:
-     * {String} Simple String representation of bounds object.
-     *          (e.g. "5,42,10,45")
-     */
-    toBBOX:function(decimal, reverseAxisOrder) {
-        if (decimal== null) {
-            decimal = 6; 
-        }
-        var mult = Math.pow(10, decimal);
-        var xmin = Math.round(this.left * mult) / mult;
-        var ymin = Math.round(this.bottom * mult) / mult;
-        var xmax = Math.round(this.right * mult) / mult;
-        var ymax = Math.round(this.top * mult) / mult;
-        if (reverseAxisOrder === true) {
-            return ymin + "," + xmin + "," + ymax + "," + xmax;
-        } else {
-            return xmin + "," + ymin + "," + xmax + "," + ymax;
-        }
-    },
-    /**
-     * APIMethod: toGeometry
-     * Create a new polygon geometry based on this bounds.
-     *
-     * Returns:
-     * {<OpenLayers.Geometry.Polygon>} A new polygon with the coordinates
-     *     of this bounds.
-     */
-    toGeometry: function() {
-        return new OpenLayers.Geometry.Polygon([
-            new OpenLayers.Geometry.LinearRing([
-                new OpenLayers.Geometry.Point(this.left, this.bottom),
-                new OpenLayers.Geometry.Point(this.right, this.bottom),
-                new OpenLayers.Geometry.Point(this.right, this.top),
-                new OpenLayers.Geometry.Point(this.left, this.top)
-            ])
-        ]);
-    },
-    
-    /**
-     * APIMethod: getWidth
-     * Returns the width of the bounds.
-     * 
-     * Returns:
-     * {Float} The width of the bounds (right minus left).
-     */
-    getWidth:function() {
-        return (this.right - this.left);
-    },
-
-    /**
-     * APIMethod: getHeight
-     * Returns the height of the bounds.
-     * 
-     * Returns:
-     * {Float} The height of the bounds (top minus bottom).
-     */
-    getHeight:function() {
-        return (this.top - this.bottom);
-    },
-
-    /**
-     * APIMethod: getSize
-     * Returns an <OpenLayers.Size> object of the bounds.
-     * 
-     * Returns:
-     * {<OpenLayers.Size>} The size of the bounds.
-     */
-    getSize:function() {
-        return new OpenLayers.Size(this.getWidth(), this.getHeight());
-    },
-
-    /**
-     * APIMethod: getCenterPixel
-     * Returns the <OpenLayers.Pixel> object which represents the center of the
-     *     bounds.
-     * 
-     * Returns:
-     * {<OpenLayers.Pixel>} The center of the bounds in pixel space.
-     */
-    getCenterPixel:function() {
-        return new OpenLayers.Pixel( (this.left + this.right) / 2,
-                                     (this.bottom + this.top) / 2);
-    },
-
-    /**
-     * APIMethod: getCenterLonLat
-     * Returns the <OpenLayers.LonLat> object which represents the center of the
-     *     bounds.
-     *
-     * Returns:
-     * {<OpenLayers.LonLat>} The center of the bounds in map space.
-     */
-    getCenterLonLat:function() {
-        if(!this.centerLonLat) {
-            this.centerLonLat = new OpenLayers.LonLat(
-                (this.left + this.right) / 2, (this.bottom + this.top) / 2
-            );
-        }
-        return this.centerLonLat;
-    },
-
-    /**
-     * APIMethod: scale
-     * Scales the bounds around a pixel or lonlat. Note that the new 
-     *     bounds may return non-integer properties, even if a pixel
-     *     is passed. 
-     * 
-     * Parameters:
-     * ratio - {Float} 
-     * origin - {<OpenLayers.Pixel> or <OpenLayers.LonLat>}
-     *          Default is center.
-     *
-     * Returns:
-     * {<OpenLayers.Bounds>} A new bounds that is scaled by ratio
-     *                      from origin.
-     */
-    scale: function(ratio, origin){
-        if(origin == null){
-            origin = this.getCenterLonLat();
-        }
-        
-        var origx,origy;
-
-        // get origin coordinates
-        if(origin.CLASS_NAME == "OpenLayers.LonLat"){
-            origx = origin.lon;
-            origy = origin.lat;
-        } else {
-            origx = origin.x;
-            origy = origin.y;
-        }
-
-        var left = (this.left - origx) * ratio + origx;
-        var bottom = (this.bottom - origy) * ratio + origy;
-        var right = (this.right - origx) * ratio + origx;
-        var top = (this.top - origy) * ratio + origy;
-        
-        return new OpenLayers.Bounds(left, bottom, right, top);
-    },
-
-    /**
-     * APIMethod: add
-     * Shifts the coordinates of the bound by the given horizontal and vertical
-     *     deltas.
-     *
-     * (start code)
-     * var bounds = new OpenLayers.Bounds(0, 0, 10, 10);
-     * bounds.toString();
-     * // => "0,0,10,10"
-     *
-     * bounds.add(-1.5, 4).toString();
-     * // => "-1.5,4,8.5,14"
-     * (end)
-     *
-     * This method will throw a TypeError if it is passed null as an argument.
-     *
-     * Parameters:
-     * x - {Float} horizontal delta
-     * y - {Float} vertical delta
-     *
-     * Returns:
-     * {<OpenLayers.Bounds>} A new bounds whose coordinates are the same as
-     *     this, but shifted by the passed-in x and y values.
-     */
-    add:function(x, y) {
-        if ( (x == null) || (y == null) ) {
-            throw new TypeError('Bounds.add cannot receive null values');
-        }
-        return new OpenLayers.Bounds(this.left + x, this.bottom + y,
-                                     this.right + x, this.top + y);
-    },
-    
-    /**
-     * APIMethod: extend
-     * Extend the bounds to include the <OpenLayers.LonLat>,
-     *     <OpenLayers.Geometry.Point> or <OpenLayers.Bounds> specified.
-     *
-     * Please note that this function assumes that left < right and
-     *     bottom < top.
-     *
-     * Parameters:
-     * object - {<OpenLayers.LonLat>, <OpenLayers.Geometry.Point> or
-     *     <OpenLayers.Bounds>} The object to be included in the new bounds
-     *     object.
-     */
-    extend:function(object) {
-        if (object) {
-            switch(object.CLASS_NAME) {
-                case "OpenLayers.LonLat":
-                    this.extendXY(object.lon, object.lat);
-                    break;
-                case "OpenLayers.Geometry.Point":
-                    this.extendXY(object.x, object.y);
-                    break;
-
-                case "OpenLayers.Bounds":
-                    // clear cached center location
-                    this.centerLonLat = null;
-
-                    if ( (this.left == null) || (object.left < this.left)) {
-                        this.left = object.left;
-                    }
-                    if ( (this.bottom == null) || (object.bottom < this.bottom) ) {
-                        this.bottom = object.bottom;
-                    }
-                    if ( (this.right == null) || (object.right > this.right) ) {
-                        this.right = object.right;
-                    }
-                    if ( (this.top == null) || (object.top > this.top) ) {
-                        this.top = object.top;
-                    }
-                    break;
-            }
-        }
-    },
-
-    /**
-     * APIMethod: extendXY
-     * Extend the bounds to include the XY coordinate specified.
-     *
-     * Parameters:
-     * x - {number} The X part of the the coordinate.
-     * y - {number} The Y part of the the coordinate.
-     */
-    extendXY:function(x, y) {
-        // clear cached center location
-        this.centerLonLat = null;
-
-        if ((this.left == null) || (x < this.left)) {
-            this.left = x;
-        }
-        if ((this.bottom == null) || (y < this.bottom)) {
-            this.bottom = y;
-        }
-        if ((this.right == null) || (x > this.right)) {
-            this.right = x;
-        }
-        if ((this.top == null) || (y > this.top)) {
-            this.top = y;
-        }
-    },
-
-    /**
-     * APIMethod: containsLonLat
-     * Returns whether the bounds object contains the given <OpenLayers.LonLat>.
-     * 
-     * Parameters:
-     * ll - {<OpenLayers.LonLat>|Object} OpenLayers.LonLat or an
-     *     object with a 'lon' and 'lat' properties.
-     * options - {Object} Optional parameters
-     *
-     * Acceptable options:
-     * inclusive - {Boolean} Whether or not to include the border.
-     *     Default is true.
-     * worldBounds - {<OpenLayers.Bounds>} If a worldBounds is provided, the
-     *     ll will be considered as contained if it exceeds the world bounds,
-     *     but can be wrapped around the dateline so it is contained by this
-     *     bounds.
-     *
-     * Returns:
-     * {Boolean} The passed-in lonlat is within this bounds.
-     */
-    containsLonLat: function(ll, options) {
-        if (typeof options === "boolean") {
-            options =  {inclusive: options};
-        }
-        options = options || {};
-        var contains = this.contains(ll.lon, ll.lat, options.inclusive),
-            worldBounds = options.worldBounds;
-        if (worldBounds && !contains) {
-            var worldWidth = worldBounds.getWidth();
-            var worldCenterX = (worldBounds.left + worldBounds.right) / 2;
-            var worldsAway = Math.round((ll.lon - worldCenterX) / worldWidth);
-            contains = this.containsLonLat({
-                lon: ll.lon - worldsAway * worldWidth,
-                lat: ll.lat
-            }, {inclusive: options.inclusive});
-        }
-        return contains;
-    },
-
-    /**
-     * APIMethod: containsPixel
-     * Returns whether the bounds object contains the given <OpenLayers.Pixel>.
-     * 
-     * Parameters:
-     * px - {<OpenLayers.Pixel>}
-     * inclusive - {Boolean} Whether or not to include the border. Default is
-     *     true.
-     *
-     * Returns:
-     * {Boolean} The passed-in pixel is within this bounds.
-     */
-    containsPixel:function(px, inclusive) {
-        return this.contains(px.x, px.y, inclusive);
-    },
-    
-    /**
-     * APIMethod: contains
-     * Returns whether the bounds object contains the given x and y.
-     * 
-     * Parameters:
-     * x - {Float}
-     * y - {Float}
-     * inclusive - {Boolean} Whether or not to include the border. Default is
-     *     true.
-     *
-     * Returns:
-     * {Boolean} Whether or not the passed-in coordinates are within this
-     *     bounds.
-     */
-    contains:function(x, y, inclusive) {
-        //set default
-        if (inclusive == null) {
-            inclusive = true;
-        }
-
-        if (x == null || y == null) {
-            return false;
-        }
-
-        x = OpenLayers.Util.toFloat(x);
-        y = OpenLayers.Util.toFloat(y);
-
-        var contains = false;
-        if (inclusive) {
-            contains = ((x >= this.left) && (x <= this.right) && 
-                        (y >= this.bottom) && (y <= this.top));
-        } else {
-            contains = ((x > this.left) && (x < this.right) && 
-                        (y > this.bottom) && (y < this.top));
-        }              
-        return contains;
-    },
-
-    /**
-     * APIMethod: intersectsBounds
-     * Determine whether the target bounds intersects this bounds.  Bounds are
-     *     considered intersecting if any of their edges intersect or if one
-     *     bounds contains the other.
-     * 
-     * Parameters:
-     * bounds - {<OpenLayers.Bounds>} The target bounds.
-     * options - {Object} Optional parameters.
-     * 
-     * Acceptable options:
-     * inclusive - {Boolean} Treat coincident borders as intersecting.  Default
-     *     is true.  If false, bounds that do not overlap but only touch at the
-     *     border will not be considered as intersecting.
-     * worldBounds - {<OpenLayers.Bounds>} If a worldBounds is provided, two
-     *     bounds will be considered as intersecting if they intersect when 
-     *     shifted to within the world bounds.  This applies only to bounds that
-     *     cross or are completely outside the world bounds.
-     *
-     * Returns:
-     * {Boolean} The passed-in bounds object intersects this bounds.
-     */
-    intersectsBounds:function(bounds, options) {
-        if (typeof options === "boolean") {
-            options =  {inclusive: options};
-        }
-        options = options || {};
-        if (options.worldBounds) {
-            var self = this.wrapDateLine(options.worldBounds);
-            bounds = bounds.wrapDateLine(options.worldBounds);
-        } else {
-            self = this;
-        }
-        if (options.inclusive == null) {
-            options.inclusive = true;
-        }
-        var intersects = false;
-        var mightTouch = (
-            self.left == bounds.right ||
-            self.right == bounds.left ||
-            self.top == bounds.bottom ||
-            self.bottom == bounds.top
-        );
-        
-        // if the two bounds only touch at an edge, and inclusive is false,
-        // then the bounds don't *really* intersect.
-        if (options.inclusive || !mightTouch) {
-            // otherwise, if one of the boundaries even partially contains another,
-            // inclusive of the edges, then they do intersect.
-            var inBottom = (
-                ((bounds.bottom >= self.bottom) && (bounds.bottom <= self.top)) ||
-                ((self.bottom >= bounds.bottom) && (self.bottom <= bounds.top))
-            );
-            var inTop = (
-                ((bounds.top >= self.bottom) && (bounds.top <= self.top)) ||
-                ((self.top > bounds.bottom) && (self.top < bounds.top))
-            );
-            var inLeft = (
-                ((bounds.left >= self.left) && (bounds.left <= self.right)) ||
-                ((self.left >= bounds.left) && (self.left <= bounds.right))
-            );
-            var inRight = (
-                ((bounds.right >= self.left) && (bounds.right <= self.right)) ||
-                ((self.right >= bounds.left) && (self.right <= bounds.right))
-            );
-            intersects = ((inBottom || inTop) && (inLeft || inRight));
-        }
-        // document me
-        if (options.worldBounds && !intersects) {
-            var world = options.worldBounds;
-            var width = world.getWidth();
-            var selfCrosses = !world.containsBounds(self);
-            var boundsCrosses = !world.containsBounds(bounds);
-            if (selfCrosses && !boundsCrosses) {
-                bounds = bounds.add(-width, 0);
-                intersects = self.intersectsBounds(bounds, {inclusive: options.inclusive});
-            } else if (boundsCrosses && !selfCrosses) {
-                self = self.add(-width, 0);
-                intersects = bounds.intersectsBounds(self, {inclusive: options.inclusive});                
-            }
-        }
-        return intersects;
-    },
-    
-    /**
-     * APIMethod: containsBounds
-     * Returns whether the bounds object contains the given <OpenLayers.Bounds>.
-     * 
-     * bounds - {<OpenLayers.Bounds>} The target bounds.
-     * partial - {Boolean} If any of the target corners is within this bounds
-     *     consider the bounds contained.  Default is false.  If false, the
-     *     entire target bounds must be contained within this bounds.
-     * inclusive - {Boolean} Treat shared edges as contained.  Default is
-     *     true.
-     *
-     * Returns:
-     * {Boolean} The passed-in bounds object is contained within this bounds. 
-     */
-    containsBounds:function(bounds, partial, inclusive) {
-        if (partial == null) {
-            partial = false;
-        }
-        if (inclusive == null) {
-            inclusive = true;
-        }
-        var bottomLeft  = this.contains(bounds.left, bounds.bottom, inclusive);
-        var bottomRight = this.contains(bounds.right, bounds.bottom, inclusive);
-        var topLeft  = this.contains(bounds.left, bounds.top, inclusive);
-        var topRight = this.contains(bounds.right, bounds.top, inclusive);
-        
-        return (partial) ? (bottomLeft || bottomRight || topLeft || topRight)
-                         : (bottomLeft && bottomRight && topLeft && topRight);
-    },
-
-    /** 
-     * APIMethod: determineQuadrant
-     * Returns the the quadrant ("br", "tr", "tl", "bl") in which the given
-     *     <OpenLayers.LonLat> lies.
-     *
-     * Parameters:
-     * lonlat - {<OpenLayers.LonLat>}
-     *
-     * Returns:
-     * {String} The quadrant ("br" "tr" "tl" "bl") of the bounds in which the
-     *     coordinate lies.
-     */
-    determineQuadrant: function(lonlat) {
-    
-        var quadrant = "";
-        var center = this.getCenterLonLat();
-        
-        quadrant += (lonlat.lat < center.lat) ? "b" : "t";
-        quadrant += (lonlat.lon < center.lon) ? "l" : "r";
-    
-        return quadrant; 
-    },
-    
-    /**
-     * APIMethod: transform
-     * Transform the Bounds object from source to dest. 
-     *
-     * Parameters: 
-     * source - {<OpenLayers.Projection>} Source projection. 
-     * dest   - {<OpenLayers.Projection>} Destination projection. 
-     *
-     * Returns:
-     * {<OpenLayers.Bounds>} Itself, for use in chaining operations.
-     */
-    transform: function(source, dest) {
-        // clear cached center location
-        this.centerLonLat = null;
-        var ll = OpenLayers.Projection.transform(
-            {'x': this.left, 'y': this.bottom}, source, dest);
-        var lr = OpenLayers.Projection.transform(
-            {'x': this.right, 'y': this.bottom}, source, dest);
-        var ul = OpenLayers.Projection.transform(
-            {'x': this.left, 'y': this.top}, source, dest);
-        var ur = OpenLayers.Projection.transform(
-            {'x': this.right, 'y': this.top}, source, dest);
-        this.left   = Math.min(ll.x, ul.x);
-        this.bottom = Math.min(ll.y, lr.y);
-        this.right  = Math.max(lr.x, ur.x);
-        this.top    = Math.max(ul.y, ur.y);
-        return this;
-    },
-
-    /**
-     * APIMethod: wrapDateLine
-     * Wraps the bounds object around the dateline.
-     *  
-     * Parameters:
-     * maxExtent - {<OpenLayers.Bounds>}
-     * options - {Object} Some possible options are:
-     *
-     * Allowed Options:
-     *                    leftTolerance - {float} Allow for a margin of error 
-     *                                            with the 'left' value of this 
-     *                                            bound.
-     *                                            Default is 0.
-     *                    rightTolerance - {float} Allow for a margin of error 
-     *                                             with the 'right' value of 
-     *                                             this bound.
-     *                                             Default is 0.
-     * 
-     * Returns:
-     * {<OpenLayers.Bounds>} A copy of this bounds, but wrapped around the 
-     *                       "dateline" (as specified by the borders of 
-     *                       maxExtent). Note that this function only returns 
-     *                       a different bounds value if this bounds is 
-     *                       *entirely* outside of the maxExtent. If this 
-     *                       bounds straddles the dateline (is part in/part 
-     *                       out of maxExtent), the returned bounds will always 
-     *                       cross the left edge of the given maxExtent.
-     *.
-     */
-    wrapDateLine: function(maxExtent, options) {    
-        options = options || {};
-        
-        var leftTolerance = options.leftTolerance || 0;
-        var rightTolerance = options.rightTolerance || 0;
-
-        var newBounds = this.clone();
-    
-        if (maxExtent) {
-            var width = maxExtent.getWidth();
-
-            //shift right?
-            while (newBounds.left < maxExtent.left && 
-                   newBounds.right - rightTolerance <= maxExtent.left ) { 
-                newBounds = newBounds.add(width, 0);
-            }
-
-            //shift left?
-            while (newBounds.left + leftTolerance >= maxExtent.right && 
-                   newBounds.right > maxExtent.right ) { 
-                newBounds = newBounds.add(-width, 0);
-            }
-           
-            // crosses right only? force left
-            var newLeft = newBounds.left + leftTolerance;
-            if (newLeft < maxExtent.right && newLeft > maxExtent.left && 
-                   newBounds.right - rightTolerance > maxExtent.right) {
-                newBounds = newBounds.add(-width, 0);
-            }
-        }
-                
-        return newBounds;
-    },
-
-    CLASS_NAME: "OpenLayers.Bounds"
-});
-
-/** 
- * APIFunction: fromString
- * Alternative constructor that builds a new OpenLayers.Bounds from a 
- *     parameter string.
- *
- * (begin code)
- * OpenLayers.Bounds.fromString("5,42,10,45");
- * // => equivalent to ...
- * new OpenLayers.Bounds(5, 42, 10, 45);
- * (end)
- *
- * Parameters: 
- * str - {String} Comma-separated bounds string. (e.g. "5,42,10,45")
- * reverseAxisOrder - {Boolean} Does the string use reverse axis order?
- *
- * Returns:
- * {<OpenLayers.Bounds>} New bounds object built from the 
- *                       passed-in String.
- */
-OpenLayers.Bounds.fromString = function(str, reverseAxisOrder) {
-    var bounds = str.split(",");
-    return OpenLayers.Bounds.fromArray(bounds, reverseAxisOrder);
-};
-
-/** 
- * APIFunction: fromArray
- * Alternative constructor that builds a new OpenLayers.Bounds from an array.
- *
- * (begin code)
- * OpenLayers.Bounds.fromArray( [5, 42, 10, 45] );
- * // => equivalent to ...
- * new OpenLayers.Bounds(5, 42, 10, 45);
- * (end)
- *
- * Parameters:
- * bbox - {Array(Float)} Array of bounds values (e.g. [5,42,10,45])
- * reverseAxisOrder - {Boolean} Does the array use reverse axis order?
- *
- * Returns:
- * {<OpenLayers.Bounds>} New bounds object built from the passed-in Array.
- */
-OpenLayers.Bounds.fromArray = function(bbox, reverseAxisOrder) {
-    return reverseAxisOrder === true ?
-           new OpenLayers.Bounds(bbox[1], bbox[0], bbox[3], bbox[2]) :
-           new OpenLayers.Bounds(bbox[0], bbox[1], bbox[2], bbox[3]);
-};
-
-/** 
- * APIFunction: fromSize
- * Alternative constructor that builds a new OpenLayers.Bounds from a size.
- *
- * (begin code)
- * OpenLayers.Bounds.fromSize( new OpenLayers.Size(10, 20) );
- * // => equivalent to ...
- * new OpenLayers.Bounds(0, 20, 10, 0);
- * (end)
- *
- * Parameters:
- * size - {<OpenLayers.Size> or Object} <OpenLayers.Size> or an object with
- *     both 'w' and 'h' properties.
- *
- * Returns:
- * {<OpenLayers.Bounds>} New bounds object built from the passed-in size.
- */
-OpenLayers.Bounds.fromSize = function(size) {
-    return new OpenLayers.Bounds(0,
-                                 size.h,
-                                 size.w,
-                                 0);
-};
-
-/**
- * Function: oppositeQuadrant
- * Get the opposite quadrant for a given quadrant string.
- *
- * (begin code)
- * OpenLayers.Bounds.oppositeQuadrant( "tl" );
- * // => "br"
- *
- * OpenLayers.Bounds.oppositeQuadrant( "tr" );
- * // => "bl"
- * (end)
- *
- * Parameters:
- * quadrant - {String} two character quadrant shortstring
- *
- * Returns:
- * {String} The opposing quadrant ("br" "tr" "tl" "bl"). For Example, if 
- *          you pass in "bl" it returns "tr", if you pass in "br" it 
- *          returns "tl", etc.
- */
-OpenLayers.Bounds.oppositeQuadrant = function(quadrant) {
-    var opp = "";
-    
-    opp += (quadrant.charAt(0) == 't') ? 'b' : 't';
-    opp += (quadrant.charAt(1) == 'l') ? 'r' : 'l';
-    
-    return opp;
-};
-/* ======================================================================
-    OpenLayers/BaseTypes/Element.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/Util.js
- * @requires OpenLayers/BaseTypes.js
- */
-
-/**
- * Namespace: OpenLayers.Element
- */
-OpenLayers.Element = {
-
-    /**
-     * APIFunction: visible
-     * 
-     * Parameters: 
-     * element - {DOMElement}
-     * 
-     * Returns:
-     * {Boolean} Is the element visible?
-     */
-    visible: function(element) {
-        return OpenLayers.Util.getElement(element).style.display != 'none';
-    },
-
-    /**
-     * APIFunction: toggle
-     * Toggle the visibility of element(s) passed in
-     * 
-     * Parameters:
-     * element - {DOMElement} Actually user can pass any number of elements
-     */
-    toggle: function() {
-        for (var i=0, len=arguments.length; i<len; i++) {
-            var element = OpenLayers.Util.getElement(arguments[i]);
-            var display = OpenLayers.Element.visible(element) ? 'none' 
-                                                              : '';
-            element.style.display = display;
-        }
-    },
-
-    /**
-     * APIFunction: remove
-     * Remove the specified element from the DOM.
-     * 
-     * Parameters:
-     * element - {DOMElement}
-     */
-    remove: function(element) {
-        element = OpenLayers.Util.getElement(element);
-        element.parentNode.removeChild(element);
-    },
-
-    /**
-     * APIFunction: getHeight
-     *  
-     * Parameters:
-     * element - {DOMElement}
-     * 
-     * Returns:
-     * {Integer} The offset height of the element passed in
-     */
-    getHeight: function(element) {
-        element = OpenLayers.Util.getElement(element);
-        return element.offsetHeight;
-    },
-
-    /**
-     * Function: hasClass
-     * Tests if an element has the given CSS class name.
-     *
-     * Parameters:
-     * element - {DOMElement} A DOM element node.
-     * name - {String} The CSS class name to search for.
-     *
-     * Returns:
-     * {Boolean} The element has the given class name.
-     */
-    hasClass: function(element, name) {
-        var names = element.className;
-        return (!!names && new RegExp("(^|\\s)" + name + "(\\s|$)").test(names));
-    },
-    
-    /**
-     * Function: addClass
-     * Add a CSS class name to an element.  Safe where element already has
-     *     the class name.
-     *
-     * Parameters:
-     * element - {DOMElement} A DOM element node.
-     * name - {String} The CSS class name to add.
-     *
-     * Returns:
-     * {DOMElement} The element.
-     */
-    addClass: function(element, name) {
-        if(!OpenLayers.Element.hasClass(element, name)) {
-            element.className += (element.className ? " " : "") + name;
-        }
-        return element;
-    },
-
-    /**
-     * Function: removeClass
-     * Remove a CSS class name from an element.  Safe where element does not
-     *     have the class name.
-     *
-     * Parameters:
-     * element - {DOMElement} A DOM element node.
-     * name - {String} The CSS class name to remove.
-     *
-     * Returns:
-     * {DOMElement} The element.
-     */
-    removeClass: function(element, name) {
-        var names = element.className;
-        if(names) {
-            element.className = OpenLayers.String.trim(
-                names.replace(
-                    new RegExp("(^|\\s+)" + name + "(\\s+|$)"), " "
-                )
-            );
-        }
-        return element;
-    },
-
-    /**
-     * Function: toggleClass
-     * Remove a CSS class name from an element if it exists.  Add the class name
-     *     if it doesn't exist.
-     *
-     * Parameters:
-     * element - {DOMElement} A DOM element node.
-     * name - {String} The CSS class name to toggle.
-     *
-     * Returns:
-     * {DOMElement} The element.
-     */
-    toggleClass: function(element, name) {
-        if(OpenLayers.Element.hasClass(element, name)) {
-            OpenLayers.Element.removeClass(element, name);
-        } else {
-            OpenLayers.Element.addClass(element, name);
-        }
-        return element;
-    },
-
-    /**
-     * APIFunction: getStyle
-     * 
-     * Parameters:
-     * element - {DOMElement}
-     * style - {?}
-     * 
-     * Returns:
-     * {?}
-     */
-    getStyle: function(element, style) {
-        element = OpenLayers.Util.getElement(element);
-
-        var value = null;
-        if (element && element.style) {
-            value = element.style[OpenLayers.String.camelize(style)];
-            if (!value) {
-                if (document.defaultView && 
-                    document.defaultView.getComputedStyle) {
-                    
-                    var css = document.defaultView.getComputedStyle(element, null);
-                    value = css ? css.getPropertyValue(style) : null;
-                } else if (element.currentStyle) {
-                    value = element.currentStyle[OpenLayers.String.camelize(style)];
-                }
-            }
-        
-            var positions = ['left', 'top', 'right', 'bottom'];
-            if (window.opera &&
-                (OpenLayers.Util.indexOf(positions,style) != -1) &&
-                (OpenLayers.Element.getStyle(element, 'position') == 'static')) { 
-                value = 'auto';
-            }
-        }
-    
-        return value == 'auto' ? null : value;
-    }
-
-};
-/* ======================================================================
-    OpenLayers/BaseTypes/LonLat.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- */
-
-/**
- * Class: OpenLayers.LonLat
- * This class represents a longitude and latitude pair
- */
-OpenLayers.LonLat = OpenLayers.Class({
-
-    /** 
-     * APIProperty: lon
-     * {Float} The x-axis coodinate in map units
-     */
-    lon: 0.0,
-    
-    /** 
-     * APIProperty: lat
-     * {Float} The y-axis coordinate in map units
-     */
-    lat: 0.0,
-
-    /**
-     * Constructor: OpenLayers.LonLat
-     * Create a new map location. Coordinates can be passed either as two
-     * arguments, or as a single argument.
-     *
-     * Parameters (two arguments):
-     * lon - {Number} The x-axis coordinate in map units.  If your map is in
-     *     a geographic projection, this will be the Longitude.  Otherwise,
-     *     it will be the x coordinate of the map location in your map units.
-     * lat - {Number} The y-axis coordinate in map units.  If your map is in
-     *     a geographic projection, this will be the Latitude.  Otherwise,
-     *     it will be the y coordinate of the map location in your map units.
-     *
-     * Parameters (single argument):
-     * location - {Array(Float)} [lon, lat]
-     */
-    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);
-    },
-    
-    /**
-     * Method: toString
-     * Return a readable string version of the lonlat
-     *
-     * Returns:
-     * {String} String representation of OpenLayers.LonLat object. 
-     *           (e.g. <i>"lon=5,lat=42"</i>)
-     */
-    toString:function() {
-        return ("lon=" + this.lon + ",lat=" + this.lat);
-    },
-
-    /** 
-     * APIMethod: toShortString
-     * 
-     * Returns:
-     * {String} Shortened String representation of OpenLayers.LonLat object. 
-     *         (e.g. <i>"5, 42"</i>)
-     */
-    toShortString:function() {
-        return (this.lon + ", " + this.lat);
-    },
-
-    /** 
-     * APIMethod: clone
-     * 
-     * Returns:
-     * {<OpenLayers.LonLat>} New OpenLayers.LonLat object with the same lon 
-     *                       and lat values
-     */
-    clone:function() {
-        return new OpenLayers.LonLat(this.lon, this.lat);
-    },
-
-    /** 
-     * APIMethod: add
-     * 
-     * Parameters:
-     * lon - {Float}
-     * lat - {Float}
-     * 
-     * Returns:
-     * {<OpenLayers.LonLat>} A new OpenLayers.LonLat object with the lon and 
-     *                       lat passed-in added to this's. 
-     */
-    add:function(lon, lat) {
-        if ( (lon == null) || (lat == null) ) {
-            throw new TypeError('LonLat.add cannot receive null values');
-        }
-        return new OpenLayers.LonLat(this.lon + OpenLayers.Util.toFloat(lon), 
-                                     this.lat + OpenLayers.Util.toFloat(lat));
-    },
-
-    /** 
-     * APIMethod: equals
-     * 
-     * Parameters:
-     * ll - {<OpenLayers.LonLat>}
-     * 
-     * Returns:
-     * {Boolean} Boolean value indicating whether the passed-in 
-     *           <OpenLayers.LonLat> object has the same lon and lat 
-     *           components as this.
-     *           Note: if ll passed in is null, returns false
-     */
-    equals:function(ll) {
-        var equals = false;
-        if (ll != null) {
-            equals = ((this.lon == ll.lon && this.lat == ll.lat) ||
-                      (isNaN(this.lon) && isNaN(this.lat) && isNaN(ll.lon) && isNaN(ll.lat)));
-        }
-        return equals;
-    },
-
-    /**
-     * APIMethod: transform
-     * Transform the LonLat object from source to dest. This transformation is
-     *    *in place*: if you want a *new* lonlat, use .clone() first.
-     *
-     * Parameters: 
-     * source - {<OpenLayers.Projection>} Source projection. 
-     * dest   - {<OpenLayers.Projection>} Destination projection. 
-     *
-     * Returns:
-     * {<OpenLayers.LonLat>} Itself, for use in chaining operations.
-     */
-    transform: function(source, dest) {
-        var point = OpenLayers.Projection.transform(
-            {'x': this.lon, 'y': this.lat}, source, dest);
-        this.lon = point.x;
-        this.lat = point.y;
-        return this;
-    },
-    
-    /**
-     * APIMethod: wrapDateLine
-     * 
-     * Parameters:
-     * maxExtent - {<OpenLayers.Bounds>}
-     * 
-     * Returns:
-     * {<OpenLayers.LonLat>} A copy of this lonlat, but wrapped around the 
-     *                       "dateline" (as specified by the borders of 
-     *                       maxExtent)
-     */
-    wrapDateLine: function(maxExtent) {    
-
-        var newLonLat = this.clone();
-    
-        if (maxExtent) {
-            //shift right?
-            while (newLonLat.lon < maxExtent.left) {
-                newLonLat.lon +=  maxExtent.getWidth();
-            }    
-           
-            //shift left?
-            while (newLonLat.lon > maxExtent.right) {
-                newLonLat.lon -= maxExtent.getWidth();
-            }    
-        }
-                
-        return newLonLat;
-    },
-
-    CLASS_NAME: "OpenLayers.LonLat"
-});
-
-/** 
- * Function: fromString
- * Alternative constructor that builds a new <OpenLayers.LonLat> from a 
- *     parameter string
- * 
- * Parameters:
- * str - {String} Comma-separated Lon,Lat coordinate string. 
- *                 (e.g. <i>"5,40"</i>)
- * 
- * Returns:
- * {<OpenLayers.LonLat>} New <OpenLayers.LonLat> object built from the 
- *                       passed-in String.
- */
-OpenLayers.LonLat.fromString = function(str) {
-    var pair = str.split(",");
-    return new OpenLayers.LonLat(pair[0], pair[1]);
-};
-
-/** 
- * Function: fromArray
- * Alternative constructor that builds a new <OpenLayers.LonLat> from an 
- *     array of two numbers that represent lon- and lat-values.
- * 
- * Parameters:
- * arr - {Array(Float)} Array of lon/lat values (e.g. [5,-42])
- * 
- * Returns:
- * {<OpenLayers.LonLat>} New <OpenLayers.LonLat> object built from the 
- *                       passed-in array.
- */
-OpenLayers.LonLat.fromArray = function(arr) {
-    var gotArr = OpenLayers.Util.isArray(arr),
-        lon = gotArr && arr[0],
-        lat = gotArr && arr[1];
-    return new OpenLayers.LonLat(lon, lat);
-};
-/* ======================================================================
-    OpenLayers/BaseTypes/Pixel.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- */
-
-/**
- * Class: OpenLayers.Pixel
- * This class represents a screen coordinate, in x and y coordinates
- */
-OpenLayers.Pixel = OpenLayers.Class({
-    
-    /**
-     * APIProperty: x
-     * {Number} The x coordinate
-     */
-    x: 0.0,
-
-    /**
-     * APIProperty: y
-     * {Number} The y coordinate
-     */
-    y: 0.0,
-    
-    /**
-     * Constructor: OpenLayers.Pixel
-     * Create a new OpenLayers.Pixel instance
-     *
-     * Parameters:
-     * x - {Number} The x coordinate
-     * y - {Number} The y coordinate
-     *
-     * Returns:
-     * An instance of OpenLayers.Pixel
-     */
-    initialize: function(x, y) {
-        this.x = parseFloat(x);
-        this.y = parseFloat(y);
-    },
-    
-    /**
-     * Method: toString
-     * Cast this object into a string
-     *
-     * Returns:
-     * {String} The string representation of Pixel. ex: "x=200.4,y=242.2"
-     */
-    toString:function() {
-        return ("x=" + this.x + ",y=" + this.y);
-    },
-
-    /**
-     * APIMethod: clone
-     * Return a clone of this pixel object
-     *
-     * Returns:
-     * {<OpenLayers.Pixel>} A clone pixel
-     */
-    clone:function() {
-        return new OpenLayers.Pixel(this.x, this.y); 
-    },
-    
-    /**
-     * APIMethod: equals
-     * Determine whether one pixel is equivalent to another
-     *
-     * Parameters:
-     * px - {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an object with
-     *                                  a 'x' and 'y' properties.
-     *
-     * Returns:
-     * {Boolean} The point passed in as parameter is equal to this. Note that
-     * if px passed in is null, returns false.
-     */
-    equals:function(px) {
-        var equals = false;
-        if (px != null) {
-            equals = ((this.x == px.x && this.y == px.y) ||
-                      (isNaN(this.x) && isNaN(this.y) && isNaN(px.x) && isNaN(px.y)));
-        }
-        return equals;
-    },
-
-    /**
-     * APIMethod: distanceTo
-     * Returns the distance to the pixel point passed in as a parameter.
-     *
-     * Parameters:
-     * px - {<OpenLayers.Pixel>}
-     *
-     * Returns:
-     * {Float} The pixel point passed in as parameter to calculate the
-     *     distance to.
-     */
-    distanceTo:function(px) {
-        return Math.sqrt(
-            Math.pow(this.x - px.x, 2) +
-            Math.pow(this.y - px.y, 2)
-        );
-    },
-
-    /**
-     * APIMethod: add
-     *
-     * Parameters:
-     * x - {Integer}
-     * y - {Integer}
-     *
-     * Returns:
-     * {<OpenLayers.Pixel>} A new Pixel with this pixel's x&y augmented by the 
-     * values passed in.
-     */
-    add:function(x, y) {
-        if ( (x == null) || (y == null) ) {
-            throw new TypeError('Pixel.add cannot receive null values');
-        }
-        return new OpenLayers.Pixel(this.x + x, this.y + y);
-    },
-
-    /**
-    * APIMethod: offset
-    * 
-    * Parameters
-    * px - {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an object with
-    *                                  a 'x' and 'y' properties.
-    * 
-    * Returns:
-    * {<OpenLayers.Pixel>} A new Pixel with this pixel's x&y augmented by the 
-    *                      x&y values of the pixel passed in.
-    */
-    offset:function(px) {
-        var newPx = this.clone();
-        if (px) {
-            newPx = this.add(px.x, px.y);
-        }
-        return newPx;
-    },
-
-    CLASS_NAME: "OpenLayers.Pixel"
-});
-/* ======================================================================
-    OpenLayers/BaseTypes/Size.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- */
-
-/**
- * Class: OpenLayers.Size
- * Instances of this class represent a width/height pair
- */
-OpenLayers.Size = OpenLayers.Class({
-
-    /**
-     * APIProperty: w
-     * {Number} width
-     */
-    w: 0.0,
-    
-    /**
-     * APIProperty: h
-     * {Number} height
-     */
-    h: 0.0,
-
-
-    /**
-     * Constructor: OpenLayers.Size
-     * Create an instance of OpenLayers.Size
-     *
-     * Parameters:
-     * w - {Number} width
-     * h - {Number} height
-     */
-    initialize: function(w, h) {
-        this.w = parseFloat(w);
-        this.h = parseFloat(h);
-    },
-
-    /**
-     * Method: toString
-     * Return the string representation of a size object
-     *
-     * Returns:
-     * {String} The string representation of OpenLayers.Size object. 
-     * (e.g. <i>"w=55,h=66"</i>)
-     */
-    toString:function() {
-        return ("w=" + this.w + ",h=" + this.h);
-    },
-
-    /**
-     * APIMethod: clone
-     * Create a clone of this size object
-     *
-     * Returns:
-     * {<OpenLayers.Size>} A new OpenLayers.Size object with the same w and h
-     * values
-     */
-    clone:function() {
-        return new OpenLayers.Size(this.w, this.h);
-    },
-
-    /**
-     *
-     * APIMethod: equals
-     * Determine where this size is equal to another
-     *
-     * Parameters:
-     * sz - {<OpenLayers.Size>|Object} An OpenLayers.Size or an object with
-     *                                  a 'w' and 'h' properties.
-     *
-     * Returns: 
-     * {Boolean} The passed in size has the same h and w properties as this one.
-     * Note that if sz passed in is null, returns false.
-     */
-    equals:function(sz) {
-        var equals = false;
-        if (sz != null) {
-            equals = ((this.w == sz.w && this.h == sz.h) ||
-                      (isNaN(this.w) && isNaN(this.h) && isNaN(sz.w) && isNaN(sz.h)));
-        }
-        return equals;
-    },
-
-    CLASS_NAME: "OpenLayers.Size"
-});
-/* ======================================================================
-    OpenLayers/Console.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- */
-
-/**
- * Namespace: OpenLayers.Console
- * The OpenLayers.Console namespace is used for debugging and error logging.
- * If the Firebug Lite (../Firebug/firebug.js) is included before this script,
- * calls to OpenLayers.Console methods will get redirected to window.console.
- * This makes use of the Firebug extension where available and allows for
- * cross-browser debugging Firebug style.
- *
- * Note:
- * Note that behavior will differ with the Firebug extension and Firebug Lite.
- * Most notably, the Firebug Lite console does not currently allow for
- * hyperlinks to code or for clicking on object to explore their properties.
- * 
- */
-OpenLayers.Console = {
-    /**
-     * Create empty functions for all console methods.  The real value of these
-     * properties will be set if Firebug Lite (../Firebug/firebug.js script) is
-     * included.  We explicitly require the Firebug Lite script to trigger
-     * functionality of the OpenLayers.Console methods.
-     */
-    
-    /**
-     * APIFunction: log
-     * Log an object in the console.  The Firebug Lite console logs string
-     * representation of objects.  Given multiple arguments, they will
-     * be cast to strings and logged with a space delimiter.  If the first
-     * argument is a string with printf-like formatting, subsequent arguments
-     * will be used in string substitution.  Any additional arguments (beyond
-     * the number substituted in a format string) will be appended in a space-
-     * delimited line.
-     * 
-     * Parameters:
-     * object - {Object}
-     */
-    log: function() {},
-
-    /**
-     * APIFunction: debug
-     * Writes a message to the console, including a hyperlink to the line
-     * where it was called.
-     *
-     * May be called with multiple arguments as with OpenLayers.Console.log().
-     * 
-     * Parameters:
-     * object - {Object}
-     */
-    debug: function() {},
-
-    /**
-     * APIFunction: info
-     * Writes a message to the console with the visual "info" icon and color
-     * coding and a hyperlink to the line where it was called.
-     *
-     * May be called with multiple arguments as with OpenLayers.Console.log().
-     * 
-     * Parameters:
-     * object - {Object}
-     */
-    info: function() {},
-
-    /**
-     * APIFunction: warn
-     * Writes a message to the console with the visual "warning" icon and
-     * color coding and a hyperlink to the line where it was called.
-     *
-     * May be called with multiple arguments as with OpenLayers.Console.log().
-     * 
-     * Parameters:
-     * object - {Object}
-     */
-    warn: function() {},
-
-    /**
-     * APIFunction: error
-     * Writes a message to the console with the visual "error" icon and color
-     * coding and a hyperlink to the line where it was called.
-     *
-     * May be called with multiple arguments as with OpenLayers.Console.log().
-     * 
-     * Parameters:
-     * object - {Object}
-     */
-    error: function() {},
-    
-    /**
-     * APIFunction: userError
-     * A single interface for showing error messages to the user. The default
-     * behavior is a Javascript alert, though this can be overridden by
-     * reassigning OpenLayers.Console.userError to a different function.
-     *
-     * Expects a single error message
-     * 
-     * Parameters:
-     * error - {Object}
-     */
-    userError: function(error) {
-        alert(error);
-    },
-
-    /**
-     * APIFunction: assert
-     * Tests that an expression is true. If not, it will write a message to
-     * the console and throw an exception.
-     *
-     * May be called with multiple arguments as with OpenLayers.Console.log().
-     * 
-     * Parameters:
-     * object - {Object}
-     */
-    assert: function() {},
-
-    /**
-     * APIFunction: dir
-     * Prints an interactive listing of all properties of the object. This
-     * looks identical to the view that you would see in the DOM tab.
-     * 
-     * Parameters:
-     * object - {Object}
-     */
-    dir: function() {},
-
-    /**
-     * APIFunction: dirxml
-     * Prints the XML source tree of an HTML or XML element. This looks
-     * identical to the view that you would see in the HTML tab. You can click
-     * on any node to inspect it in the HTML tab.
-     * 
-     * Parameters:
-     * object - {Object}
-     */
-    dirxml: function() {},
-
-    /**
-     * APIFunction: trace
-     * Prints an interactive stack trace of JavaScript execution at the point
-     * where it is called.  The stack trace details the functions on the stack,
-     * as well as the values that were passed as arguments to each function.
-     * You can click each function to take you to its source in the Script tab,
-     * and click each argument value to inspect it in the DOM or HTML tabs.
-     * 
-     */
-    trace: function() {},
-
-    /**
-     * APIFunction: group
-     * Writes a message to the console and opens a nested block to indent all
-     * future messages sent to the console. Call OpenLayers.Console.groupEnd()
-     * to close the block.
-     *
-     * May be called with multiple arguments as with OpenLayers.Console.log().
-     * 
-     * Parameters:
-     * object - {Object}
-     */
-    group: function() {},
-
-    /**
-     * APIFunction: groupEnd
-     * Closes the most recently opened block created by a call to
-     * OpenLayers.Console.group
-     */
-    groupEnd: function() {},
-    
-    /**
-     * APIFunction: time
-     * Creates a new timer under the given name. Call
-     * OpenLayers.Console.timeEnd(name)
-     * with the same name to stop the timer and print the time elapsed.
-     *
-     * Parameters:
-     * name - {String}
-     */
-    time: function() {},
-
-    /**
-     * APIFunction: timeEnd
-     * Stops a timer created by a call to OpenLayers.Console.time(name) and
-     * writes the time elapsed.
-     *
-     * Parameters:
-     * name - {String}
-     */
-    timeEnd: function() {},
-
-    /**
-     * APIFunction: profile
-     * Turns on the JavaScript profiler. The optional argument title would
-     * contain the text to be printed in the header of the profile report.
-     *
-     * This function is not currently implemented in Firebug Lite.
-     * 
-     * Parameters:
-     * title - {String} Optional title for the profiler
-     */
-    profile: function() {},
-
-    /**
-     * APIFunction: profileEnd
-     * Turns off the JavaScript profiler and prints its report.
-     * 
-     * This function is not currently implemented in Firebug Lite.
-     */
-    profileEnd: function() {},
-
-    /**
-     * APIFunction: count
-     * Writes the number of times that the line of code where count was called
-     * was executed. The optional argument title will print a message in
-     * addition to the number of the count.
-     *
-     * This function is not currently implemented in Firebug Lite.
-     *
-     * Parameters:
-     * title - {String} Optional title to be printed with count
-     */
-    count: function() {},
-
-    CLASS_NAME: "OpenLayers.Console"
-};
-
-/**
- * Execute an anonymous function to extend the OpenLayers.Console namespace
- * if the firebug.js script is included.  This closure is used so that the
- * "scripts" and "i" variables don't pollute the global namespace.
- */
-(function() {
-    /**
-     * If Firebug Lite is included (before this script), re-route all
-     * OpenLayers.Console calls to the console object.
-     */
-    var scripts = document.getElementsByTagName("script");
-    for(var i=0, len=scripts.length; i<len; ++i) {
-        if(scripts[i].src.indexOf("firebug.js") != -1) {
-            if(console) {
-                OpenLayers.Util.extend(OpenLayers.Console, console);
-                break;
-            }
-        }
-    }
-})();
-/* ======================================================================
-    OpenLayers/Lang.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes.js
- * @requires OpenLayers/Console.js
- */
-
-/**
- * Namespace: OpenLayers.Lang
- * Internationalization namespace.  Contains dictionaries in various languages
- *     and methods to set and get the current language.
- */
-OpenLayers.Lang = {
-    
-    /** 
-     * Property: code
-     * {String}  Current language code to use in OpenLayers.  Use the
-     *     <setCode> method to set this value and the <getCode> method to
-     *     retrieve it.
-     */
-    code: null,
-
-    /** 
-     * APIProperty: defaultCode
-     * {String} Default language to use when a specific language can't be
-     *     found.  Default is "en".
-     */
-    defaultCode: "en",
-        
-    /**
-     * APIFunction: getCode
-     * Get the current language code.
-     *
-     * Returns:
-     * {String} The current language code.
-     */
-    getCode: function() {
-        if(!OpenLayers.Lang.code) {
-            OpenLayers.Lang.setCode();
-        }
-        return OpenLayers.Lang.code;
-    },
-    
-    /**
-     * APIFunction: setCode
-     * Set the language code for string translation.  This code is used by
-     *     the <OpenLayers.Lang.translate> method.
-     *
-     * Parameters:
-     * code - {String} These codes follow the IETF recommendations at
-     *     http://www.ietf.org/rfc/rfc3066.txt.  If no value is set, the
-     *     browser's language setting will be tested.  If no <OpenLayers.Lang>
-     *     dictionary exists for the code, the <OpenLayers.String.defaultLang>
-     *     will be used.
-     */
-    setCode: function(code) {
-        var lang;
-        if(!code) {
-            code = (OpenLayers.BROWSER_NAME == "msie") ?
-                navigator.userLanguage : navigator.language;
-        }
-        var parts = code.split('-');
-        parts[0] = parts[0].toLowerCase();
-        if(typeof OpenLayers.Lang[parts[0]] == "object") {
-            lang = parts[0];
-        }
-
-        // check for regional extensions
-        if(parts[1]) {
-            var testLang = parts[0] + '-' + parts[1].toUpperCase();
-            if(typeof OpenLayers.Lang[testLang] == "object") {
-                lang = testLang;
-            }
-        }
-        if(!lang) {
-            OpenLayers.Console.warn(
-                'Failed to find OpenLayers.Lang.' + parts.join("-") +
-                ' dictionary, falling back to default language'
-            );
-            lang = OpenLayers.Lang.defaultCode;
-        }
-        
-        OpenLayers.Lang.code = lang;
-    },
-
-    /**
-     * APIMethod: translate
-     * Looks up a key from a dictionary based on the current language string.
-     *     The value of <getCode> will be used to determine the appropriate
-     *     dictionary.  Dictionaries are stored in <OpenLayers.Lang>.
-     *
-     * Parameters:
-     * key - {String} The key for an i18n string value in the dictionary.
-     * context - {Object} Optional context to be used with
-     *     <OpenLayers.String.format>.
-     * 
-     * Returns:
-     * {String} A internationalized string.
-     */
-    translate: function(key, context) {
-        var dictionary = OpenLayers.Lang[OpenLayers.Lang.getCode()];
-        var message = dictionary && dictionary[key];
-        if(!message) {
-            // Message not found, fall back to message key
-            message = key;
-        }
-        if(context) {
-            message = OpenLayers.String.format(message, context);
-        }
-        return message;
-    }
-    
-};
-
-
-/**
- * APIMethod: OpenLayers.i18n
- * Alias for <OpenLayers.Lang.translate>.  Looks up a key from a dictionary
- *     based on the current language string. The value of
- *     <OpenLayers.Lang.getCode> will be used to determine the appropriate
- *     dictionary.  Dictionaries are stored in <OpenLayers.Lang>.
- *
- * Parameters:
- * key - {String} The key for an i18n string value in the dictionary.
- * context - {Object} Optional context to be used with
- *     <OpenLayers.String.format>.
- * 
- * Returns:
- * {String} A internationalized string.
- */
-OpenLayers.i18n = OpenLayers.Lang.translate;
-/* ======================================================================
-    OpenLayers/Util.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes.js
- * @requires OpenLayers/BaseTypes/Bounds.js
- * @requires OpenLayers/BaseTypes/Element.js
- * @requires OpenLayers/BaseTypes/LonLat.js
- * @requires OpenLayers/BaseTypes/Pixel.js
- * @requires OpenLayers/BaseTypes/Size.js
- * @requires OpenLayers/Lang.js
- */
-
-/**
- * Namespace: Util
- */
-OpenLayers.Util = OpenLayers.Util || {};
-
-/** 
- * Function: getElement
- * This is the old $() from prototype
- *
- * Parameters:
- * e - {String or DOMElement or Window}
- *
- * Returns:
- * {Array(DOMElement) or DOMElement}
- */
-OpenLayers.Util.getElement = function() {
-    var elements = [];
-
-    for (var i=0, len=arguments.length; i<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;
-};
-
-/**
- * Function: isElement
- * A cross-browser implementation of "e instanceof Element".
- *
- * Parameters:
- * o - {Object} The object to test.
- *
- * Returns:
- * {Boolean}
- */
-OpenLayers.Util.isElement = function(o) {
-    return !!(o && o.nodeType === 1);
-};
-
-/**
- * Function: isArray
- * Tests that the provided object is an array.
- * This test handles the cross-IFRAME case not caught
- * by "a instanceof Array" and should be used instead.
- * 
- * Parameters:
- * a - {Object} the object test.
- * 
- * Returns:
- * {Boolean} true if the object is an array.
- */
-OpenLayers.Util.isArray = function(a) {
-    return (Object.prototype.toString.call(a) === '[object Array]');
-};
-
-/** 
- * Function: removeItem
- * Remove an object from an array. Iterates through the array
- *     to find the item, then removes it.
- *
- * Parameters:
- * array - {Array}
- * item - {Object}
- * 
- * Returns:
- * {Array} A reference to the array
- */
-OpenLayers.Util.removeItem = function(array, item) {
-    for(var i = array.length - 1; i >= 0; i--) {
-        if(array[i] == item) {
-            array.splice(i,1);
-            //break;more than once??
-        }
-    }
-    return array;
-};
-
-/** 
- * Function: indexOf
- * Seems to exist already in FF, but not in MOZ.
- * 
- * Parameters:
- * array - {Array}
- * obj - {*}
- * 
- * Returns:
- * {Integer} The index at which the first object was found in the array.
- *           If not found, returns -1.
- */
-OpenLayers.Util.indexOf = function(array, obj) {
-    // use the build-in function if available.
-    if (typeof array.indexOf == "function") {
-        return array.indexOf(obj);
-    } else {
-        for (var i = 0, len = array.length; i < len; i++) {
-            if (array[i] == obj) {
-                return i;
-            }
-        }
-        return -1;   
-    }
-};
-
-
-/**
- * Property: dotless
- * {RegExp}
- * Compiled regular expression to match dots (".").  This is used for replacing
- *     dots in identifiers.  Because object identifiers are frequently used for
- *     DOM element identifiers by the library, we avoid using dots to make for
- *     more sensible CSS selectors.
- *
- * TODO: Use a module pattern to avoid bloating the API with stuff like this.
- */
-OpenLayers.Util.dotless = /\./g;
-
-/**
- * Function: modifyDOMElement
- * 
- * Modifies many properties of a DOM element all at once.  Passing in 
- * null to an individual parameter will avoid setting the attribute.
- *
- * Parameters:
- * element - {DOMElement} DOM element to modify.
- * id - {String} The element id attribute to set.  Note that dots (".") will be
- *     replaced with underscore ("_") in setting the element id.
- * px - {<OpenLayers.Pixel>|Object} The element left and top position,
- *                                  OpenLayers.Pixel or an object with
- *                                  a 'x' and 'y' properties.
- * sz - {<OpenLayers.Size>|Object} The element width and height,
- *                                 OpenLayers.Size or an object with a
- *                                 'w' and 'h' properties.
- * position - {String}       The position attribute.  eg: absolute, 
- *                           relative, etc.
- * border - {String}         The style.border attribute.  eg:
- *                           solid black 2px
- * overflow - {String}       The style.overview attribute.  
- * opacity - {Float}         Fractional value (0.0 - 1.0)
- */
-OpenLayers.Util.modifyDOMElement = function(element, id, px, sz, position, 
-                                            border, overflow, opacity) {
-
-    if (id) {
-        element.id = id.replace(OpenLayers.Util.dotless, "_");
-    }
-    if (px) {
-        element.style.left = px.x + "px";
-        element.style.top = px.y + "px";
-    }
-    if (sz) {
-        element.style.width = sz.w + "px";
-        element.style.height = sz.h + "px";
-    }
-    if (position) {
-        element.style.position = position;
-    }
-    if (border) {
-        element.style.border = border;
-    }
-    if (overflow) {
-        element.style.overflow = overflow;
-    }
-    if (parseFloat(opacity) >= 0.0 && parseFloat(opacity) < 1.0) {
-        element.style.filter = 'alpha(opacity=' + (opacity * 100) + ')';
-        element.style.opacity = opacity;
-    } else if (parseFloat(opacity) == 1.0) {
-        element.style.filter = '';
-        element.style.opacity = '';
-    }
-};
-
-/** 
- * Function: createDiv
- * Creates a new div and optionally set some standard attributes.
- * Null may be passed to each parameter if you do not wish to
- * set a particular attribute.
- * Note - zIndex is NOT set on the resulting div.
- * 
- * Parameters:
- * id - {String} An identifier for this element.  If no id is
- *               passed an identifier will be created 
- *               automatically.  Note that dots (".") will be replaced with
- *               underscore ("_") when generating ids.
- * px - {<OpenLayers.Pixel>|Object} The element left and top position,
- *                                  OpenLayers.Pixel or an object with
- *                                  a 'x' and 'y' properties.
- * sz - {<OpenLayers.Size>|Object} The element width and height,
- *                                 OpenLayers.Size or an object with a
- *                                 'w' and 'h' properties.
- * imgURL - {String} A url pointing to an image to use as a 
- *                   background image.
- * position - {String} The style.position value. eg: absolute,
- *                     relative etc.
- * border - {String} The the style.border value. 
- *                   eg: 2px solid black
- * overflow - {String} The style.overflow value. Eg. hidden
- * opacity - {Float} Fractional value (0.0 - 1.0)
- * 
- * Returns: 
- * {DOMElement} A DOM Div created with the specified attributes.
- */
-OpenLayers.Util.createDiv = function(id, px, sz, imgURL, position, 
-                                     border, overflow, opacity) {
-
-    var dom = document.createElement('div');
-
-    if (imgURL) {
-        dom.style.backgroundImage = 'url(' + imgURL + ')';
-    }
-
-    //set generic properties
-    if (!id) {
-        id = OpenLayers.Util.createUniqueID("OpenLayersDiv");
-    }
-    if (!position) {
-        position = "absolute";
-    }
-    OpenLayers.Util.modifyDOMElement(dom, id, px, sz, position, 
-                                     border, overflow, opacity);
-
-    return dom;
-};
-
-/**
- * Function: createImage
- * Creates an img element with specific attribute values.
- *  
- * Parameters:
- * id - {String} The id field for the img.  If none assigned one will be
- *               automatically generated.
- * px - {<OpenLayers.Pixel>|Object} The element left and top position,
- *                                  OpenLayers.Pixel or an object with
- *                                  a 'x' and 'y' properties.
- * sz - {<OpenLayers.Size>|Object} The element width and height,
- *                                 OpenLayers.Size or an object with a
- *                                 'w' and 'h' properties.
- * imgURL - {String} The url to use as the image source.
- * position - {String} The style.position value.
- * border - {String} The border to place around the image.
- * opacity - {Float} Fractional value (0.0 - 1.0)
- * delayDisplay - {Boolean} If true waits until the image has been
- *                          loaded.
- * 
- * Returns:
- * {DOMElement} A DOM Image created with the specified attributes.
- */
-OpenLayers.Util.createImage = function(id, px, sz, imgURL, position, border,
-                                       opacity, delayDisplay) {
-
-    var image = document.createElement("img");
-
-    //set generic properties
-    if (!id) {
-        id = OpenLayers.Util.createUniqueID("OpenLayersDiv");
-    }
-    if (!position) {
-        position = "relative";
-    }
-    OpenLayers.Util.modifyDOMElement(image, id, px, sz, position, 
-                                     border, null, opacity);
-
-    if (delayDisplay) {
-        image.style.display = "none";
-        function display() {
-            image.style.display = "";
-            OpenLayers.Event.stopObservingElement(image);
-        }
-        OpenLayers.Event.observe(image, "load", display);
-        OpenLayers.Event.observe(image, "error", display);
-    }
-    
-    //set special properties
-    image.style.alt = id;
-    image.galleryImg = "no";
-    if (imgURL) {
-        image.src = imgURL;
-    }
-        
-    return image;
-};
-
-/**
- * Property: IMAGE_RELOAD_ATTEMPTS
- * {Integer} How many times should we try to reload an image before giving up?
- *           Default is 0
- */
-OpenLayers.IMAGE_RELOAD_ATTEMPTS = 0;
-
-/**
- * Property: alphaHackNeeded
- * {Boolean} true if the png alpha hack is necessary and possible, false otherwise.
- */
-OpenLayers.Util.alphaHackNeeded = null;
-
-/**
- * Function: alphaHack
- * Checks whether it's necessary (and possible) to use the png alpha
- * hack which allows alpha transparency for png images under Internet
- * Explorer.
- * 
- * Returns:
- * {Boolean} true if the png alpha hack is necessary and possible, false otherwise.
- */
-OpenLayers.Util.alphaHack = function() {
-    if (OpenLayers.Util.alphaHackNeeded == null) {
-        var arVersion = navigator.appVersion.split("MSIE");
-        var version = parseFloat(arVersion[1]);
-        var filter = false;
-    
-        // IEs4Lin dies when trying to access document.body.filters, because 
-        // the property is there, but requires a DLL that can't be provided. This
-        // means that we need to wrap this in a try/catch so that this can
-        // continue.
-    
-        try { 
-            filter = !!(document.body.filters);
-        } catch (e) {}    
-    
-        OpenLayers.Util.alphaHackNeeded = (filter && 
-                                           (version >= 5.5) && (version < 7));
-    }
-    return OpenLayers.Util.alphaHackNeeded;
-};
-
-/** 
- * Function: modifyAlphaImageDiv
- * 
- * Parameters:
- * div - {DOMElement} Div containing Alpha-adjusted Image
- * id - {String}
- * px - {<OpenLayers.Pixel>|Object} OpenLayers.Pixel or an object with
- *                                  a 'x' and 'y' properties.
- * sz - {<OpenLayers.Size>|Object} OpenLayers.Size or an object with
- *                                 a 'w' and 'h' properties.
- * imgURL - {String}
- * position - {String}
- * border - {String}
- * sizing - {String} 'crop', 'scale', or 'image'. Default is "scale"
- * opacity - {Float} Fractional value (0.0 - 1.0)
- */ 
-OpenLayers.Util.modifyAlphaImageDiv = function(div, id, px, sz, imgURL, 
-                                               position, border, sizing, 
-                                               opacity) {
-
-    OpenLayers.Util.modifyDOMElement(div, id, px, sz, position,
-                                     null, null, opacity);
-
-    var img = div.childNodes[0];
-
-    if (imgURL) {
-        img.src = imgURL;
-    }
-    OpenLayers.Util.modifyDOMElement(img, div.id + "_innerImage", null, sz, 
-                                     "relative", border);
-    
-    if (OpenLayers.Util.alphaHack()) {
-        if(div.style.display != "none") {
-            div.style.display = "inline-block";
-        }
-        if (sizing == null) {
-            sizing = "scale";
-        }
-        
-        div.style.filter = "progid:DXImageTransform.Microsoft" +
-                           ".AlphaImageLoader(src='" + img.src + "', " +
-                           "sizingMethod='" + sizing + "')";
-        if (parseFloat(div.style.opacity) >= 0.0 && 
-            parseFloat(div.style.opacity) < 1.0) {
-            div.style.filter += " alpha(opacity=" + div.style.opacity * 100 + ")";
-        }
-
-        img.style.filter = "alpha(opacity=0)";
-    }
-};
-
-/** 
- * Function: createAlphaImageDiv
- * 
- * Parameters:
- * id - {String}
- * px - {<OpenLayers.Pixel>|Object} OpenLayers.Pixel or an object with
- *                                  a 'x' and 'y' properties.
- * sz - {<OpenLayers.Size>|Object} OpenLayers.Size or an object with
- *                                 a 'w' and 'h' properties.
- * imgURL - {String}
- * position - {String}
- * border - {String}
- * sizing - {String} 'crop', 'scale', or 'image'. Default is "scale"
- * opacity - {Float} Fractional value (0.0 - 1.0)
- * delayDisplay - {Boolean} If true waits until the image has been
- *                          loaded.
- * 
- * Returns:
- * {DOMElement} A DOM Div created with a DOM Image inside it. If the hack is 
- *              needed for transparency in IE, it is added.
- */ 
-OpenLayers.Util.createAlphaImageDiv = function(id, px, sz, imgURL, 
-                                               position, border, sizing, 
-                                               opacity, delayDisplay) {
-    
-    var div = OpenLayers.Util.createDiv();
-    var img = OpenLayers.Util.createImage(null, null, null, null, null, null, 
-                                          null, delayDisplay);
-    img.className = "olAlphaImg";
-    div.appendChild(img);
-
-    OpenLayers.Util.modifyAlphaImageDiv(div, id, px, sz, imgURL, position, 
-                                        border, sizing, opacity);
-    
-    return div;
-};
-
-
-/** 
- * Function: upperCaseObject
- * Creates a new hashtable and copies over all the keys from the 
- *     passed-in object, but storing them under an uppercased
- *     version of the key at which they were stored.
- * 
- * Parameters: 
- * object - {Object}
- * 
- * Returns: 
- * {Object} A new Object with all the same keys but uppercased
- */
-OpenLayers.Util.upperCaseObject = function (object) {
-    var uObject = {};
-    for (var key in object) {
-        uObject[key.toUpperCase()] = object[key];
-    }
-    return uObject;
-};
-
-/** 
- * Function: applyDefaults
- * Takes an object and copies any properties that don't exist from
- *     another properties, by analogy with OpenLayers.Util.extend() from
- *     Prototype.js.
- * 
- * Parameters:
- * to - {Object} The destination object.
- * from - {Object} The source object.  Any properties of this object that
- *     are undefined in the to object will be set on the to object.
- *
- * Returns:
- * {Object} A reference to the to object.  Note that the to argument is modified
- *     in place and returned by this function.
- */
-OpenLayers.Util.applyDefaults = function (to, from) {
-    to = to || {};
-    /*
-     * FF/Windows < 2.0.0.13 reports "Illegal operation on WrappedNative
-     * prototype object" when calling hawOwnProperty if the source object is an
-     * instance of window.Event.
-     */
-    var fromIsEvt = typeof window.Event == "function"
-                    && from instanceof window.Event;
-
-    for (var key in from) {
-        if (to[key] === undefined ||
-            (!fromIsEvt && from.hasOwnProperty
-             && from.hasOwnProperty(key) && !to.hasOwnProperty(key))) {
-            to[key] = from[key];
-        }
-    }
-    /**
-     * IE doesn't include the toString property when iterating over an object's
-     * properties with the for(property in object) syntax.  Explicitly check if
-     * the source has its own toString property.
-     */
-    if(!fromIsEvt && from && from.hasOwnProperty
-       && from.hasOwnProperty('toString') && !to.hasOwnProperty('toString')) {
-        to.toString = from.toString;
-    }
-    
-    return to;
-};
-
-/**
- * Function: getParameterString
- * 
- * Parameters:
- * params - {Object}
- * 
- * Returns:
- * {String} A concatenation of the properties of an object in 
- *          http parameter notation. 
- *          (ex. <i>"key1=value1&key2=value2&key3=value3"</i>)
- *          If a parameter is actually a list, that parameter will then
- *          be set to a comma-seperated list of values (foo,bar) instead
- *          of being URL escaped (foo%3Abar). 
- */
-OpenLayers.Util.getParameterString = function(params) {
-    var paramsArray = [];
-    
-    for (var key in params) {
-      var value = params[key];
-      if ((value != null) && (typeof value != 'function')) {
-        var encodedValue;
-        if (typeof value == 'object' && value.constructor == Array) {
-          /* value is an array; encode items and separate with "," */
-          var encodedItemArray = [];
-          var item;
-          for (var itemIndex=0, len=value.length; itemIndex<len; itemIndex++) {
-            item = value[itemIndex];
-            encodedItemArray.push(encodeURIComponent(
-                (item === null || item === undefined) ? "" : item)
-            );
-          }
-          encodedValue = encodedItemArray.join(",");
-        }
-        else {
-          /* value is a string; simply encode */
-          encodedValue = encodeURIComponent(value);
-        }
-        paramsArray.push(encodeURIComponent(key) + "=" + encodedValue);
-      }
-    }
-    
-    return paramsArray.join("&");
-};
-
-/**
- * Function: urlAppend
- * Appends a parameter string to a url. This function includes the logic for
- * using the appropriate character (none, & or ?) to append to the url before
- * appending the param string.
- * 
- * Parameters:
- * url - {String} The url to append to
- * paramStr - {String} The param string to append
- * 
- * Returns:
- * {String} The new url
- */
-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;
-};
-
-/** 
- * Function: getImagesLocation
- * 
- * Returns:
- * {String} The fully formatted image location string
- */
-OpenLayers.Util.getImagesLocation = function() {
-    return OpenLayers.ImgPath || (OpenLayers._getScriptLocation() + "img/");
-};
-
-/** 
- * Function: getImageLocation
- * 
- * Returns:
- * {String} The fully formatted location string for a specified image
- */
-OpenLayers.Util.getImageLocation = function(image) {
-    return OpenLayers.Util.getImagesLocation() + image;
-};
-
-
-/** 
- * Function: Try
- * Execute functions until one of them doesn't throw an error. 
- *     Capitalized because "try" is a reserved word in JavaScript.
- *     Taken directly from OpenLayers.Util.Try()
- * 
- * Parameters:
- * [*] - {Function} Any number of parameters may be passed to Try()
- *    It will attempt to execute each of them until one of them 
- *    successfully executes. 
- *    If none executes successfully, returns null.
- * 
- * Returns:
- * {*} The value returned by the first successfully executed function.
- */
-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;
-};
-
-/**
- * Function: getXmlNodeValue
- * 
- * Parameters:
- * node - {XMLNode}
- * 
- * Returns:
- * {String} The text value of the given node, without breaking in firefox or IE
- */
-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;
-};
-
-/** 
- * Function: mouseLeft
- * 
- * Parameters:
- * evt - {Event}
- * div - {HTMLDivElement}
- * 
- * Returns:
- * {Boolean}
- */
-OpenLayers.Util.mouseLeft = function (evt, div) {
-    // start with the element to which the mouse has moved
-    var target = (evt.relatedTarget) ? evt.relatedTarget : evt.toElement;
-    // walk up the DOM tree.
-    while (target != div && target != null) {
-        target = target.parentNode;
-    }
-    // if the target we stop at isn't the div, then we've left the div.
-    return (target != div);
-};
-
-/**
- * Property: precision
- * {Number} The number of significant digits to retain to avoid
- * floating point precision errors.
- *
- * We use 14 as a "safe" default because, although IEEE 754 double floats
- * (standard on most modern operating systems) support up to about 16
- * significant digits, 14 significant digits are sufficient to represent
- * sub-millimeter accuracy in any coordinate system that anyone is likely to
- * use with OpenLayers.
- *
- * If DEFAULT_PRECISION is set to 0, the original non-truncating behavior
- * of OpenLayers <2.8 is preserved. Be aware that this will cause problems
- * with certain projections, e.g. spherical Mercator.
- *
- */
-OpenLayers.Util.DEFAULT_PRECISION = 14;
-
-/**
- * Function: toFloat
- * Convenience method to cast an object to a Number, rounded to the
- * desired floating point precision.
- *
- * Parameters:
- * number    - {Number} The number to cast and round.
- * precision - {Number} An integer suitable for use with
- *      Number.toPrecision(). Defaults to OpenLayers.Util.DEFAULT_PRECISION.
- *      If set to 0, no rounding is performed.
- *
- * Returns:
- * {Number} The cast, rounded number.
- */
-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));
-};
-
-/**
- * Function: rad
- * 
- * Parameters:
- * x - {Float}
- * 
- * Returns:
- * {Float}
- */
-OpenLayers.Util.rad = function(x) {return x*Math.PI/180;};
-
-/**
- * Function: deg
- *
- * Parameters:
- * x - {Float}
- *
- * Returns:
- * {Float}
- */
-OpenLayers.Util.deg = function(x) {return x*180/Math.PI;};
-
-/**
- * Property: VincentyConstants
- * {Object} Constants for Vincenty functions.
- */
-OpenLayers.Util.VincentyConstants = {
-    a: 6378137,
-    b: 6356752.3142,
-    f: 1/298.257223563
-};
-
-/**
- * APIFunction: distVincenty
- * Given two objects representing points with geographic coordinates, this
- *     calculates the distance between those points on the surface of an
- *     ellipsoid.
- *
- * Parameters:
- * p1 - {<OpenLayers.LonLat>} (or any object with both .lat, .lon properties)
- * p2 - {<OpenLayers.LonLat>} (or any object with both .lat, .lon properties)
- *
- * Returns:
- * {Float} The distance (in km) between the two input points as measured on an
- *     ellipsoid.  Note that the input point objects must be in geographic
- *     coordinates (decimal degrees) and the return distance is in kilometers.
- */
-OpenLayers.Util.distVincenty = function(p1, p2) {
-    var ct = OpenLayers.Util.VincentyConstants;
-    var a = ct.a, b = ct.b, f = ct.f;
-
-    var L = OpenLayers.Util.rad(p2.lon - p1.lon);
-    var U1 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p1.lat)));
-    var U2 = Math.atan((1-f) * Math.tan(OpenLayers.Util.rad(p2.lat)));
-    var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
-    var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
-    var lambda = L, lambdaP = 2*Math.PI;
-    var iterLimit = 20;
-    while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) {
-        var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
-        var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
-        (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
-        if (sinSigma==0) {
-            return 0;  // co-incident points
-        }
-        var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
-        var sigma = Math.atan2(sinSigma, cosSigma);
-        var alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma);
-        var cosSqAlpha = Math.cos(alpha) * Math.cos(alpha);
-        var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
-        var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
-        lambdaP = lambda;
-        lambda = L + (1-C) * f * Math.sin(alpha) *
-        (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
-    }
-    if (iterLimit==0) {
-        return NaN;  // formula failed to converge
-    }
-    var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
-    var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
-    var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
-    var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
-        B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
-    var s = b*A*(sigma-deltaSigma);
-    var d = s.toFixed(3)/1000; // round to 1mm precision
-    return d;
-};
-
-/**
- * APIFunction: destinationVincenty
- * Calculate destination point given start point lat/long (numeric degrees),
- * bearing (numeric degrees) & distance (in m).
- * Adapted from Chris Veness work, see
- * http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html
- *
- * Parameters:
- * lonlat  - {<OpenLayers.LonLat>} (or any object with both .lat, .lon
- *     properties) The start point.
- * brng     - {Float} The bearing (degrees).
- * dist     - {Float} The ground distance (meters).
- *
- * Returns:
- * {<OpenLayers.LonLat>} The destination point.
- */
-OpenLayers.Util.destinationVincenty = function(lonlat, brng, dist) {
-    var u = OpenLayers.Util;
-    var ct = u.VincentyConstants;
-    var a = ct.a, b = ct.b, f = ct.f;
-
-    var lon1 = lonlat.lon;
-    var lat1 = lonlat.lat;
-
-    var s = dist;
-    var alpha1 = u.rad(brng);
-    var sinAlpha1 = Math.sin(alpha1);
-    var cosAlpha1 = Math.cos(alpha1);
-
-    var tanU1 = (1-f) * Math.tan(u.rad(lat1));
-    var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
-    var sigma1 = Math.atan2(tanU1, cosAlpha1);
-    var sinAlpha = cosU1 * sinAlpha1;
-    var cosSqAlpha = 1 - sinAlpha*sinAlpha;
-    var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
-    var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
-    var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
-
-    var sigma = s / (b*A), sigmaP = 2*Math.PI;
-    while (Math.abs(sigma-sigmaP) > 1e-12) {
-        var cos2SigmaM = Math.cos(2*sigma1 + sigma);
-        var sinSigma = Math.sin(sigma);
-        var cosSigma = Math.cos(sigma);
-        var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
-            B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
-        sigmaP = sigma;
-        sigma = s / (b*A) + deltaSigma;
-    }
-
-    var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
-    var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
-        (1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));
-    var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
-    var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
-    var L = lambda - (1-C) * f * sinAlpha *
-        (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
-
-    var revAz = Math.atan2(sinAlpha, -tmp);  // final bearing
-
-    return new OpenLayers.LonLat(lon1+u.deg(L), u.deg(lat2));
-};
-
-/**
- * Function: getParameters
- * Parse the parameters from a URL or from the current page itself into a 
- *     JavaScript Object. Note that parameter values with commas are separated
- *     out into an Array.
- * 
- * Parameters:
- * url - {String} Optional url used to extract the query string.
- *                If url is null or is not supplied, query string is taken 
- *                from the page location.
- * options - {Object} Additional options. Optional.
- *
- * Valid options:
- *   splitArgs - {Boolean} Split comma delimited params into arrays? Default is
- *       true.
- * 
- * Returns:
- * {Object} An object of key/value pairs from the query string.
- */
-OpenLayers.Util.getParameters = function(url, options) {
-    options = options || {};
-    // if no url specified, take it from the location bar
-    url = (url === null || url === undefined) ? window.location.href : url;
-
-    //parse out parameters portion of url string
-    var paramsString = "";
-    if (OpenLayers.String.contains(url, '?')) {
-        var start = url.indexOf('?') + 1;
-        var end = OpenLayers.String.contains(url, "#") ?
-                    url.indexOf('#') : url.length;
-        paramsString = url.substring(start, end);
-    }
-
-    var parameters = {};
-    var pairs = paramsString.split(/[&;]/);
-    for(var i=0, len=pairs.length; i<len; ++i) {
-        var keyValue = pairs[i].split('=');
-        if (keyValue[0]) {
-
-            var key = keyValue[0];
-            try {
-                key = decodeURIComponent(key);
-            } catch (err) {
-                key = unescape(key);
-            }
-            
-            // being liberal by replacing "+" with " "
-            var value = (keyValue[1] || '').replace(/\+/g, " ");
-
-            try {
-                value = decodeURIComponent(value);
-            } catch (err) {
-                value = unescape(value);
-            }
-            
-            // follow OGC convention of comma delimited values
-            if (options.splitArgs !== false) {
-                value = value.split(",");
-            }
-
-            //if there's only one value, do not return as array                    
-            if (value.length == 1) {
-                value = value[0];
-            }                
-            
-            parameters[key] = value;
-         }
-     }
-    return parameters;
-};
-
-/**
- * Property: lastSeqID
- * {Integer} The ever-incrementing count variable.
- *           Used for generating unique ids.
- */
-OpenLayers.Util.lastSeqID = 0;
-
-/**
- * Function: createUniqueID
- * Create a unique identifier for this session.  Each time this function
- *     is called, a counter is incremented.  The return will be the optional
- *     prefix (defaults to "id_") appended with the counter value.
- * 
- * Parameters:
- * prefix - {String} Optional string to prefix unique id. Default is "id_".
- *     Note that dots (".") in the prefix will be replaced with underscore ("_").
- * 
- * Returns:
- * {String} A unique id string, built on the passed in prefix.
- */
-OpenLayers.Util.createUniqueID = function(prefix) {
-    if (prefix == null) {
-        prefix = "id_";
-    } else {
-        prefix = prefix.replace(OpenLayers.Util.dotless, "_");
-    }
-    OpenLayers.Util.lastSeqID += 1; 
-    return prefix + OpenLayers.Util.lastSeqID;        
-};
-
-/**
- * Constant: INCHES_PER_UNIT
- * {Object} Constant inches per unit -- borrowed from MapServer mapscale.c
- * derivation of nautical miles from http://en.wikipedia.org/wiki/Nautical_mile
- * Includes the full set of units supported by CS-MAP (http://trac.osgeo.org/csmap/)
- * and PROJ.4 (http://trac.osgeo.org/proj/)
- * The hardcoded table is maintain in a CS-MAP source code module named CSdataU.c
- * The hardcoded table of PROJ.4 units are in pj_units.c.
- */
-OpenLayers.INCHES_PER_UNIT = { 
-    'inches': 1.0,
-    'ft': 12.0,
-    'mi': 63360.0,
-    'm': 39.37,
-    'km': 39370,
-    '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;
-
-// Units from CS-Map
-OpenLayers.METERS_PER_INCH = 0.02540005080010160020;
-OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT, {
-    "Inch": OpenLayers.INCHES_PER_UNIT.inches,
-    "Meter": 1.0 / OpenLayers.METERS_PER_INCH,   //EPSG:9001
-    "Foot": 0.30480060960121920243 / OpenLayers.METERS_PER_INCH,   //EPSG:9003
-    "IFoot": 0.30480000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9002
-    "ClarkeFoot": 0.3047972651151 / OpenLayers.METERS_PER_INCH,   //EPSG:9005
-    "SearsFoot": 0.30479947153867624624 / OpenLayers.METERS_PER_INCH,   //EPSG:9041
-    "GoldCoastFoot": 0.30479971018150881758 / OpenLayers.METERS_PER_INCH,   //EPSG:9094
-    "IInch": 0.02540000000000000000 / OpenLayers.METERS_PER_INCH,
-    "MicroInch": 0.00002540000000000000 / OpenLayers.METERS_PER_INCH,
-    "Mil": 0.00000002540000000000 / OpenLayers.METERS_PER_INCH,
-    "Centimeter": 0.01000000000000000000 / OpenLayers.METERS_PER_INCH,
-    "Kilometer": 1000.00000000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9036
-    "Yard": 0.91440182880365760731 / OpenLayers.METERS_PER_INCH,
-    "SearsYard": 0.914398414616029 / OpenLayers.METERS_PER_INCH,   //EPSG:9040
-    "IndianYard": 0.91439853074444079983 / OpenLayers.METERS_PER_INCH,   //EPSG:9084
-    "IndianYd37": 0.91439523 / OpenLayers.METERS_PER_INCH,   //EPSG:9085
-    "IndianYd62": 0.9143988 / OpenLayers.METERS_PER_INCH,   //EPSG:9086
-    "IndianYd75": 0.9143985 / OpenLayers.METERS_PER_INCH,   //EPSG:9087
-    "IndianFoot": 0.30479951 / OpenLayers.METERS_PER_INCH,   //EPSG:9080
-    "IndianFt37": 0.30479841 / OpenLayers.METERS_PER_INCH,   //EPSG:9081
-    "IndianFt62": 0.3047996 / OpenLayers.METERS_PER_INCH,   //EPSG:9082
-    "IndianFt75": 0.3047995 / OpenLayers.METERS_PER_INCH,   //EPSG:9083
-    "Mile": 1609.34721869443738887477 / OpenLayers.METERS_PER_INCH,
-    "IYard": 0.91440000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9096
-    "IMile": 1609.34400000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9093
-    "NautM": 1852.00000000000000000000 / OpenLayers.METERS_PER_INCH,   //EPSG:9030
-    "Lat-66": 110943.316488932731 / OpenLayers.METERS_PER_INCH,
-    "Lat-83": 110946.25736872234125 / OpenLayers.METERS_PER_INCH,
-    "Decimeter": 0.10000000000000000000 / OpenLayers.METERS_PER_INCH,
-    "Millimeter": 0.00100000000000000000 / OpenLayers.METERS_PER_INCH,
-    "Dekameter": 10.00000000000000000000 / OpenLayers.METERS_PER_INCH,
-    "Decameter": 10.00000000000000000000 / OpenLayers.METERS_PER_INCH,
-    "Hectometer": 100.00000000000000000000 / OpenLayers.METERS_PER_INCH,
-    "GermanMeter": 1.0000135965 / OpenLayers.METERS_PER_INCH,   //EPSG:9031
-    "CaGrid": 0.999738 / OpenLayers.METERS_PER_INCH,
-    "ClarkeChain": 20.1166194976 / OpenLayers.METERS_PER_INCH,   //EPSG:9038
-    "GunterChain": 20.11684023368047 / OpenLayers.METERS_PER_INCH,   //EPSG:9033
-    "BenoitChain": 20.116782494375872 / OpenLayers.METERS_PER_INCH,   //EPSG:9062
-    "SearsChain": 20.11676512155 / OpenLayers.METERS_PER_INCH,   //EPSG:9042
-    "ClarkeLink": 0.201166194976 / OpenLayers.METERS_PER_INCH,   //EPSG:9039
-    "GunterLink": 0.2011684023368047 / OpenLayers.METERS_PER_INCH,   //EPSG:9034
-    "BenoitLink": 0.20116782494375872 / OpenLayers.METERS_PER_INCH,   //EPSG:9063
-    "SearsLink": 0.2011676512155 / OpenLayers.METERS_PER_INCH,   //EPSG:9043
-    "Rod": 5.02921005842012 / OpenLayers.METERS_PER_INCH,
-    "IntnlChain": 20.1168 / OpenLayers.METERS_PER_INCH,   //EPSG:9097
-    "IntnlLink": 0.201168 / OpenLayers.METERS_PER_INCH,   //EPSG:9098
-    "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.00000000000000000000 / 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
-});
-
-//unit abbreviations supported by PROJ.4
-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"],    //International Nautical Mile
-    "fath": OpenLayers.INCHES_PER_UNIT["Fathom"], //International Fathom
-    "ch": OpenLayers.INCHES_PER_UNIT["IntnlChain"],  //International Chain
-    "link": OpenLayers.INCHES_PER_UNIT["IntnlLink"], //International Link
-    "us-in": OpenLayers.INCHES_PER_UNIT["inches"], //U.S. Surveyor's Inch
-    "us-ft": OpenLayers.INCHES_PER_UNIT["Foot"], //U.S. Surveyor's Foot
-    "us-yd": OpenLayers.INCHES_PER_UNIT["Yard"], //U.S. Surveyor's Yard
-    "us-ch": OpenLayers.INCHES_PER_UNIT["GunterChain"], //U.S. Surveyor's Chain
-    "us-mi": OpenLayers.INCHES_PER_UNIT["Mile"],   //U.S. Surveyor's Statute Mile
-    "ind-yd": OpenLayers.INCHES_PER_UNIT["IndianYd37"],  //Indian Yard
-    "ind-ft": OpenLayers.INCHES_PER_UNIT["IndianFt37"],  //Indian Foot
-    "ind-ch": 20.11669506 / OpenLayers.METERS_PER_INCH  //Indian Chain
-});
-
-/** 
- * Constant: DOTS_PER_INCH
- * {Integer} 72 (A sensible default)
- */
-OpenLayers.DOTS_PER_INCH = 72;
-
-/**
- * Function: normalizeScale
- * 
- * Parameters:
- * scale - {float}
- * 
- * Returns:
- * {Float} A normalized scale value, in 1 / X format. 
- *         This means that if a value less than one ( already 1/x) is passed
- *         in, it just returns scale directly. Otherwise, it returns 
- *         1 / scale
- */
-OpenLayers.Util.normalizeScale = function (scale) {
-    var normScale = (scale > 1.0) ? (1.0 / scale) 
-                                  : scale;
-    return normScale;
-};
-
-/**
- * Function: getResolutionFromScale
- * 
- * Parameters:
- * scale - {Float}
- * units - {String} Index into OpenLayers.INCHES_PER_UNIT hashtable.
- *                  Default is degrees
- * 
- * Returns:
- * {Float} The corresponding resolution given passed-in scale and unit 
- *     parameters.  If the given scale is falsey, the returned resolution will
- *     be undefined.
- */
-OpenLayers.Util.getResolutionFromScale = function (scale, units) {
-    var resolution;
-    if (scale) {
-        if (units == null) {
-            units = "degrees";
-        }
-        var normScale = OpenLayers.Util.normalizeScale(scale);
-        resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units]
-                                        * OpenLayers.DOTS_PER_INCH);        
-    }
-    return resolution;
-};
-
-/**
- * Function: getScaleFromResolution
- * 
- * Parameters:
- * resolution - {Float}
- * units - {String} Index into OpenLayers.INCHES_PER_UNIT hashtable.
- *                  Default is degrees
- * 
- * Returns:
- * {Float} The corresponding scale given passed-in resolution and unit 
- *         parameters.
- */
-OpenLayers.Util.getScaleFromResolution = function (resolution, units) {
-
-    if (units == null) {
-        units = "degrees";
-    }
-
-    var scale = resolution * OpenLayers.INCHES_PER_UNIT[units] *
-                    OpenLayers.DOTS_PER_INCH;
-    return scale;
-};
-
-/**
- * Function: pagePosition
- * Calculates the position of an element on the page (see
- * http://code.google.com/p/doctype/wiki/ArticlePageOffset)
- *
- * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is
- * Copyright (c) 2006, Yahoo! Inc.
- * All rights reserved.
- * 
- * Redistribution and use of this software in source and binary forms, with or
- * without modification, are permitted provided that the following conditions
- * are met:
- * 
- * * Redistributions of source code must retain the above copyright notice,
- *   this list of conditions and the following disclaimer.
- * 
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- * 
- * * Neither the name of Yahoo! Inc. nor the names of its contributors may be
- *   used to endorse or promote products derived from this software without
- *   specific prior written permission of Yahoo! Inc.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Parameters:
- * forElement - {DOMElement}
- * 
- * Returns:
- * {Array} two item array, Left value then Top value.
- */
-OpenLayers.Util.pagePosition =  function(forElement) {
-    // NOTE: If element is hidden (display none or disconnected or any the
-    // ancestors are hidden) we get (0,0) by default but we still do the
-    // accumulation of scroll position.
-
-    var pos = [0, 0];
-    var viewportElement = OpenLayers.Util.getViewportElement();
-    if (!forElement || forElement == window || forElement == viewportElement) {
-        // viewport is always at 0,0 as that defined the coordinate system for
-        // this function - this avoids special case checks in the code below
-        return pos;
-    }
-
-    // Gecko browsers normally use getBoxObjectFor to calculate the position.
-    // When invoked for an element with an implicit absolute position though it
-    // can be off by one. Therefore the recursive implementation is used in
-    // those (relatively rare) cases.
-    var BUGGY_GECKO_BOX_OBJECT =
-        OpenLayers.IS_GECKO && document.getBoxObjectFor &&
-        OpenLayers.Element.getStyle(forElement, 'position') == 'absolute' &&
-        (forElement.style.top == '' || forElement.style.left == '');
-
-    var parent = null;
-    var box;
-
-    if (forElement.getBoundingClientRect) { // IE
-        box = forElement.getBoundingClientRect();
-        var scrollTop = window.pageYOffset || viewportElement.scrollTop;
-        var scrollLeft = window.pageXOffset || viewportElement.scrollLeft;
-        
-        pos[0] = box.left + scrollLeft;
-        pos[1] = box.top + scrollTop;
-
-    } else if (document.getBoxObjectFor && !BUGGY_GECKO_BOX_OBJECT) { // gecko
-        // Gecko ignores the scroll values for ancestors, up to 1.9.  See:
-        // https://bugzilla.mozilla.org/show_bug.cgi?id=328881 and
-        // https://bugzilla.mozilla.org/show_bug.cgi?id=330619
-
-        box = document.getBoxObjectFor(forElement);
-        var vpBox = document.getBoxObjectFor(viewportElement);
-        pos[0] = box.screenX - vpBox.screenX;
-        pos[1] = box.screenY - vpBox.screenY;
-
-    } else { // safari/opera
-        pos[0] = forElement.offsetLeft;
-        pos[1] = forElement.offsetTop;
-        parent = forElement.offsetParent;
-        if (parent != forElement) {
-            while (parent) {
-                pos[0] += parent.offsetLeft;
-                pos[1] += parent.offsetTop;
-                parent = parent.offsetParent;
-            }
-        }
-
-        var browser = OpenLayers.BROWSER_NAME;
-
-        // opera & (safari absolute) incorrectly account for body offsetTop
-        if (browser == "opera" || (browser == "safari" &&
-              OpenLayers.Element.getStyle(forElement, 'position') == 'absolute')) {
-            pos[1] -= document.body.offsetTop;
-        }
-
-        // accumulate the scroll positions for everything but the body element
-        parent = forElement.offsetParent;
-        while (parent && parent != document.body) {
-            pos[0] -= parent.scrollLeft;
-            // see https://bugs.opera.com/show_bug.cgi?id=249965
-            if (browser != "opera" || parent.tagName != 'TR') {
-                pos[1] -= parent.scrollTop;
-            }
-            parent = parent.offsetParent;
-        }
-    }
-    
-    return pos;
-};
-
-/**
- * Function: getViewportElement
- * Returns die viewport element of the document. The viewport element is
- * usually document.documentElement, except in IE,where it is either
- * document.body or document.documentElement, depending on the document's
- * compatibility mode (see
- * http://code.google.com/p/doctype/wiki/ArticleClientViewportElement)
- *
- * Returns:
- * {DOMElement}
- */
-OpenLayers.Util.getViewportElement = function() {
-    var viewportElement = arguments.callee.viewportElement;
-    if (viewportElement == undefined) {
-        viewportElement = (OpenLayers.BROWSER_NAME == "msie" &&
-            document.compatMode != 'CSS1Compat') ? document.body :
-            document.documentElement;
-        arguments.callee.viewportElement = viewportElement;
-    }
-    return viewportElement;
-};
-
-/** 
- * Function: isEquivalentUrl
- * Test two URLs for equivalence. 
- * 
- * Setting 'ignoreCase' allows for case-independent comparison.
- * 
- * Comparison is based on: 
- *  - Protocol
- *  - Host (evaluated without the port)
- *  - Port (set 'ignorePort80' to ignore "80" values)
- *  - Hash ( set 'ignoreHash' to disable)
- *  - Pathname (for relative <-> absolute comparison) 
- *  - Arguments (so they can be out of order)
- *  
- * Parameters:
- * url1 - {String}
- * url2 - {String}
- * options - {Object} Allows for customization of comparison:
- *                    'ignoreCase' - Default is True
- *                    'ignorePort80' - Default is True
- *                    'ignoreHash' - Default is True
- *
- * Returns:
- * {Boolean} Whether or not the two URLs are equivalent
- */
-OpenLayers.Util.isEquivalentUrl = function(url1, url2, options) {
-    options = options || {};
-
-    OpenLayers.Util.applyDefaults(options, {
-        ignoreCase: true,
-        ignorePort80: true,
-        ignoreHash: true,
-        splitArgs: false
-    });
-
-    var urlObj1 = OpenLayers.Util.createUrlObject(url1, options);
-    var urlObj2 = OpenLayers.Util.createUrlObject(url2, options);
-
-    //compare all keys except for "args" (treated below)
-    for(var key in urlObj1) {
-        if(key !== "args") {
-            if(urlObj1[key] != urlObj2[key]) {
-                return false;
-            }
-        }
-    }
-
-    // compare search args - irrespective of order
-    for(var key in urlObj1.args) {
-        if(urlObj1.args[key] != urlObj2.args[key]) {
-            return false;
-        }
-        delete urlObj2.args[key];
-    }
-    // urlObj2 shouldn't have any args left
-    for(var key in urlObj2.args) {
-        return false;
-    }
-    
-    return true;
-};
-
-/**
- * Function: createUrlObject
- * 
- * Parameters:
- * url - {String}
- * options - {Object} A hash of options.
- *
- * Valid options:
- *   ignoreCase - {Boolean} lowercase url,
- *   ignorePort80 - {Boolean} don't include explicit port if port is 80,
- *   ignoreHash - {Boolean} Don't include part of url after the hash (#).
- *   splitArgs - {Boolean} Split comma delimited params into arrays? Default is
- *       true.
- * 
- * Returns:
- * {Object} An object with separate url, a, port, host, and args parsed out 
- *          and ready for comparison
- */
-OpenLayers.Util.createUrlObject = function(url, options) {
-    options = options || {};
-
-    // deal with relative urls first
-    if(!(/^\w+:\/\//).test(url)) {
-        var loc = window.location;
-        var port = loc.port ? ":" + loc.port : "";
-        var fullUrl = loc.protocol + "//" + loc.host.split(":").shift() + port;
-        if(url.indexOf("/") === 0) {
-            // full pathname
-            url = fullUrl + url;
-        } else {
-            // relative to current path
-            var parts = loc.pathname.split("/");
-            parts.pop();
-            url = fullUrl + parts.join("/") + "/" + url;
-        }
-    }
-  
-    if (options.ignoreCase) {
-        url = url.toLowerCase(); 
-    }
-
-    var a = document.createElement('a');
-    a.href = url;
-    
-    var urlObject = {};
-    
-    //host (without port)
-    urlObject.host = a.host.split(":").shift();
-
-    //protocol
-    urlObject.protocol = a.protocol;  
-
-    //port (get uniform browser behavior with port 80 here)
-    if(options.ignorePort80) {
-        urlObject.port = (a.port == "80" || a.port == "0") ? "" : a.port;
-    } else {
-        urlObject.port = (a.port == "" || a.port == "0") ? "80" : a.port;
-    }
-
-    //hash
-    urlObject.hash = (options.ignoreHash || a.hash === "#") ? "" : a.hash;  
-    
-    //args
-    var queryString = a.search;
-    if (!queryString) {
-        var qMark = url.indexOf("?");
-        queryString = (qMark != -1) ? url.substr(qMark) : "";
-    }
-    urlObject.args = OpenLayers.Util.getParameters(queryString,
-            {splitArgs: options.splitArgs});
-
-    // pathname
-    //
-    // This is a workaround for Internet Explorer where
-    // window.location.pathname has a leading "/", but
-    // a.pathname has no leading "/".
-    urlObject.pathname = (a.pathname.charAt(0) == "/") ? a.pathname : "/" + a.pathname;
-    
-    return urlObject; 
-};
-/**
- * Function: removeTail
- * Takes a url and removes everything after the ? and #
- * 
- * Parameters:
- * url - {String} The url to process
- * 
- * Returns:
- * {String} The string with all queryString and Hash removed
- */
-OpenLayers.Util.removeTail = function(url) {
-    var head = null;
-    
-    var qMark = url.indexOf("?");
-    var hashMark = url.indexOf("#");
-
-    if (qMark == -1) {
-        head = (hashMark != -1) ? url.substr(0,hashMark) : url;
-    } else {
-        head = (hashMark != -1) ? url.substr(0,Math.min(qMark, hashMark)) 
-                                  : url.substr(0, qMark);
-    }
-    return head;
-};
-
-/**
- * Constant: IS_GECKO
- * {Boolean} True if the userAgent reports the browser to use the Gecko engine
- */
-OpenLayers.IS_GECKO = (function() {
-    var ua = navigator.userAgent.toLowerCase();
-    return ua.indexOf("webkit") == -1 && ua.indexOf("gecko") != -1;
-})();
-
-/**
- * Constant: CANVAS_SUPPORTED
- * {Boolean} True if canvas 2d is supported.
- */
-OpenLayers.CANVAS_SUPPORTED = (function() {
-    var elem = document.createElement('canvas');
-    return !!(elem.getContext && elem.getContext('2d'));
-})();
-
-/**
- * Constant: BROWSER_NAME
- * {String}
- * A substring of the navigator.userAgent property.  Depending on the userAgent
- *     property, this will be the empty string or one of the following:
- *     * "opera" -- Opera
- *     * "msie"  -- Internet Explorer
- *     * "safari" -- Safari
- *     * "firefox" -- Firefox
- *     * "mozilla" -- Mozilla
- */
-OpenLayers.BROWSER_NAME = (function() {
-    var name = "";
-    var ua = navigator.userAgent.toLowerCase();
-    if (ua.indexOf("opera") != -1) {
-        name = "opera";
-    } else if (ua.indexOf("msie") != -1) {
-        name = "msie";
-    } else if (ua.indexOf("safari") != -1) {
-        name = "safari";
-    } else if (ua.indexOf("mozilla") != -1) {
-        if (ua.indexOf("firefox") != -1) {
-            name = "firefox";
-        } else {
-            name = "mozilla";
-        }
-    }
-    return name;
-})();
-
-/**
- * Function: getBrowserName
- * 
- * Returns:
- * {String} A string which specifies which is the current 
- *          browser in which we are running. 
- * 
- *          Currently-supported browser detection and codes:
- *           * 'opera' -- Opera
- *           * 'msie'  -- Internet Explorer
- *           * 'safari' -- Safari
- *           * 'firefox' -- Firefox
- *           * 'mozilla' -- Mozilla
- * 
- *          If we are unable to property identify the browser, we 
- *           return an empty string.
- */
-OpenLayers.Util.getBrowserName = function() {
-    return OpenLayers.BROWSER_NAME;
-};
-
-/**
- * Method: getRenderedDimensions
- * Renders the contentHTML offscreen to determine actual dimensions for
- *     popup sizing. As we need layout to determine dimensions the content
- *     is rendered -9999px to the left and absolute to ensure the 
- *     scrollbars do not flicker
- *     
- * Parameters:
- * contentHTML
- * size - {<OpenLayers.Size>} If either the 'w' or 'h' properties is 
- *     specified, we fix that dimension of the div to be measured. This is 
- *     useful in the case where we have a limit in one dimension and must 
- *     therefore meaure the flow in the other dimension.
- * options - {Object}
- *
- * Allowed Options:
- *     displayClass - {String} Optional parameter.  A CSS class name(s) string
- *         to provide the CSS context of the rendered content.
- *     containerElement - {DOMElement} Optional parameter. Insert the HTML to 
- *         this node instead of the body root when calculating dimensions. 
- * 
- * Returns:
- * {<OpenLayers.Size>}
- */
-OpenLayers.Util.getRenderedDimensions = function(contentHTML, size, options) {
-    
-    var w, h;
-    
-    // create temp container div with restricted size
-    var container = document.createElement("div");
-    container.style.visibility = "hidden";
-        
-    var containerElement = (options && options.containerElement) 
-        ? options.containerElement : document.body;
-    
-    // Opera and IE7 can't handle a node with position:aboslute if it inherits
-    // position:absolute from a parent.
-    var parentHasPositionAbsolute = false;
-    var superContainer = null;
-    var parent = containerElement;
-    while (parent && parent.tagName.toLowerCase()!="body") {
-        var parentPosition = OpenLayers.Element.getStyle(parent, "position");
-        if(parentPosition == "absolute") {
-            parentHasPositionAbsolute = true;
-            break;
-        } else if (parentPosition && parentPosition != "static") {
-            break;
-        }
-        parent = parent.parentNode;
-    }
-    if(parentHasPositionAbsolute && (containerElement.clientHeight === 0 || 
-                                     containerElement.clientWidth === 0) ){
-        superContainer = document.createElement("div");
-        superContainer.style.visibility = "hidden";
-        superContainer.style.position = "absolute";
-        superContainer.style.overflow = "visible";
-        superContainer.style.width = document.body.clientWidth + "px";
-        superContainer.style.height = document.body.clientHeight + "px";
-        superContainer.appendChild(container);
-    }
-    container.style.position = "absolute";
-
-    //fix a dimension, if specified.
-    if (size) {
-        if (size.w) {
-            w = size.w;
-            container.style.width = w + "px";
-        } else if (size.h) {
-            h = size.h;
-            container.style.height = h + "px";
-        }
-    }
-
-    //add css classes, if specified
-    if (options && options.displayClass) {
-        container.className = options.displayClass;
-    }
-    
-    // create temp content div and assign content
-    var content = document.createElement("div");
-    content.innerHTML = contentHTML;
-    
-    // we need overflow visible when calculating the size
-    content.style.overflow = "visible";
-    if (content.childNodes) {
-        for (var i=0, l=content.childNodes.length; i<l; i++) {
-            if (!content.childNodes[i].style) continue;
-            content.childNodes[i].style.overflow = "visible";
-        }
-    }
-    
-    // add content to restricted container 
-    container.appendChild(content);
-    
-    // append container to body for rendering
-    if (superContainer) {
-        containerElement.appendChild(superContainer);
-    } else {
-        containerElement.appendChild(container);
-    }
-    
-    // calculate scroll width of content and add corners and shadow width
-    if (!w) {
-        w = parseInt(content.scrollWidth);
-    
-        // update container width to allow height to adjust
-        container.style.width = w + "px";
-    }        
-    // capture height and add shadow and corner image widths
-    if (!h) {
-        h = parseInt(content.scrollHeight);
-    }
-
-    // remove elements
-    container.removeChild(content);
-    if (superContainer) {
-        superContainer.removeChild(container);
-        containerElement.removeChild(superContainer);
-    } else {
-        containerElement.removeChild(container);
-    }
-    
-    return new OpenLayers.Size(w, h);
-};
-
-/**
- * APIFunction: getScrollbarWidth
- * This function has been modified by the OpenLayers from the original version,
- *     written by Matthew Eernisse and released under the Apache 2 
- *     license here:
- * 
- *     http://www.fleegix.org/articles/2006/05/30/getting-the-scrollbar-width-in-pixels
- * 
- *     It has been modified simply to cache its value, since it is physically 
- *     impossible that this code could ever run in more than one browser at 
- *     once. 
- * 
- * Returns:
- * {Integer}
- */
-OpenLayers.Util.getScrollbarWidth = function() {
-    
-    var scrollbarWidth = OpenLayers.Util._scrollbarWidth;
-    
-    if (scrollbarWidth == null) {
-        var scr = null;
-        var inn = null;
-        var wNoScroll = 0;
-        var wScroll = 0;
-    
-        // Outer scrolling div
-        scr = document.createElement('div');
-        scr.style.position = 'absolute';
-        scr.style.top = '-1000px';
-        scr.style.left = '-1000px';
-        scr.style.width = '100px';
-        scr.style.height = '50px';
-        // Start with no scrollbar
-        scr.style.overflow = 'hidden';
-    
-        // Inner content div
-        inn = document.createElement('div');
-        inn.style.width = '100%';
-        inn.style.height = '200px';
-    
-        // Put the inner div in the scrolling div
-        scr.appendChild(inn);
-        // Append the scrolling div to the doc
-        document.body.appendChild(scr);
-    
-        // Width of the inner div sans scrollbar
-        wNoScroll = inn.offsetWidth;
-    
-        // Add the scrollbar
-        scr.style.overflow = 'scroll';
-        // Width of the inner div width scrollbar
-        wScroll = inn.offsetWidth;
-    
-        // Remove the scrolling div from the doc
-        document.body.removeChild(document.body.lastChild);
-    
-        // Pixel width of the scroller
-        OpenLayers.Util._scrollbarWidth = (wNoScroll - wScroll);
-        scrollbarWidth = OpenLayers.Util._scrollbarWidth;
-    }
-
-    return scrollbarWidth;
-};
-
-/**
- * APIFunction: getFormattedLonLat
- * This function will return latitude or longitude value formatted as 
- *
- * Parameters:
- * coordinate - {Float} the coordinate value to be formatted
- * axis - {String} value of either 'lat' or 'lon' to indicate which axis is to
- *          to be formatted (default = lat)
- * dmsOption - {String} specify the precision of the output can be one of:
- *           'dms' show degrees minutes and seconds
- *           'dm' show only degrees and minutes
- *           'd' show only degrees
- * 
- * Returns:
- * {String} the coordinate value formatted as a string
- */
-OpenLayers.Util.getFormattedLonLat = function(coordinate, axis, dmsOption) {
-    if (!dmsOption) {
-        dmsOption = 'dms';    //default to show degree, minutes, seconds
-    }
-
-    coordinate = (coordinate+540)%360 - 180; // normalize for sphere being round
-
-    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;
-};
-
-/**
- * Function: getConstructor
- * Take an OpenLayers style CLASS_NAME and return a constructor.
- *
- * Parameters:
- * className - {String} The dot delimited class name (e.g. 'OpenLayers.Foo').
- * 
- * Returns:
- * {Function} The constructor.
- */
-OpenLayers.Util.getConstructor = function(className) {
-    var Constructor;
-    var parts = className.split('.');
-    if (parts[0] === "OpenLayers") {
-        Constructor = OpenLayers;
-    } else {
-        // someone extended our base class and used their own namespace
-        // this will not work when the library is evaluated in a closure
-        // but it is the best we can do (until we ourselves provide a global)
-        Constructor = window[parts[0]];
-    }
-    for (var i = 1, ii = parts.length; i < ii; ++i) {
-        Constructor = Constructor[parts[i]];
-    }
-    return Constructor;
-};
-/* ======================================================================
-    OpenLayers/Events.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-
-/**
- * @requires OpenLayers/Util.js
- */
-
-/**
- * Namespace: OpenLayers.Event
- * Utility functions for event handling.
- */
-OpenLayers.Event = {
-
-    /** 
-     * Property: observers 
-     * {Object} A hashtable cache of the event observers. Keyed by
-     * element._eventCacheID 
-     */
-    observers: false,
-
-    /**
-     * Constant: KEY_SPACE
-     * {int}
-     */
-    KEY_SPACE: 32,
-    
-    /** 
-     * Constant: KEY_BACKSPACE 
-     * {int} 
-     */
-    KEY_BACKSPACE: 8,
-
-    /** 
-     * Constant: KEY_TAB 
-     * {int} 
-     */
-    KEY_TAB: 9,
-
-    /** 
-     * Constant: KEY_RETURN 
-     * {int} 
-     */
-    KEY_RETURN: 13,
-
-    /** 
-     * Constant: KEY_ESC 
-     * {int} 
-     */
-    KEY_ESC: 27,
-
-    /** 
-     * Constant: KEY_LEFT 
-     * {int} 
-     */
-    KEY_LEFT: 37,
-
-    /** 
-     * Constant: KEY_UP 
-     * {int} 
-     */
-    KEY_UP: 38,
-
-    /** 
-     * Constant: KEY_RIGHT 
-     * {int} 
-     */
-    KEY_RIGHT: 39,
-
-    /** 
-     * Constant: KEY_DOWN 
-     * {int} 
-     */
-    KEY_DOWN: 40,
-
-    /** 
-     * Constant: KEY_DELETE 
-     * {int} 
-     */
-    KEY_DELETE: 46,
-
-
-    /**
-     * Method: element
-     * Cross browser event element detection.
-     * 
-     * Parameters:
-     * event - {Event} 
-     * 
-     * Returns:
-     * {DOMElement} The element that caused the event 
-     */
-    element: function(event) {
-        return event.target || event.srcElement;
-    },
-
-    /**
-     * Method: isSingleTouch
-     * Determine whether event was caused by a single touch
-     *
-     * Parameters:
-     * event - {Event}
-     *
-     * Returns:
-     * {Boolean}
-     */
-    isSingleTouch: function(event) {
-        return event.touches && event.touches.length == 1;
-    },
-
-    /**
-     * Method: isMultiTouch
-     * Determine whether event was caused by a multi touch
-     *
-     * Parameters:
-     * event - {Event}
-     *
-     * Returns:
-     * {Boolean}
-     */
-    isMultiTouch: function(event) {
-        return event.touches && event.touches.length > 1;
-    },
-
-    /**
-     * Method: isTouchEvent
-     * Determine whether the event was triggered by a touch
-     * 
-     * Parameters:
-     * evt - {Event}
-     * 
-     * Returns:
-     * {Boolean}
-     */
-    isTouchEvent: function(evt) {
-        return ("" + evt.type).indexOf("touch") === 0 || (
-                "pointerType" in evt && (
-                     evt.pointerType === evt.MSPOINTER_TYPE_TOUCH /*IE10 pointer*/ ||
-                     evt.pointerType === "touch" /*W3C pointer*/));
-    },
-
-    /**
-     * Method: isLeftClick
-     * Determine whether event was caused by a left click. 
-     *
-     * Parameters:
-     * event - {Event} 
-     * 
-     * Returns:
-     * {Boolean}
-     */
-    isLeftClick: function(event) {
-        return (((event.which) && (event.which == 1)) ||
-                ((event.button) && (event.button == 1)));
-    },
-
-    /**
-     * Method: isRightClick
-     * Determine whether event was caused by a right mouse click. 
-     *
-     * Parameters:
-     * event - {Event} 
-     * 
-     * Returns:
-     * {Boolean}
-     */
-     isRightClick: function(event) {
-        return (((event.which) && (event.which == 3)) ||
-                ((event.button) && (event.button == 2)));
-    },
-     
-    /**
-     * Method: stop
-     * Stops an event from propagating. 
-     *
-     * Parameters: 
-     * event - {Event} 
-     * allowDefault - {Boolean} If true, we stop the event chain but 
-     *     still allow the default browser behaviour (text selection,
-     *     radio-button clicking, etc).  Default is false.
-     */
-    stop: function(event, allowDefault) {
-        
-        if (!allowDefault) { 
-            OpenLayers.Event.preventDefault(event);
-        }
-                
-        if (event.stopPropagation) {
-            event.stopPropagation();
-        } else {
-            event.cancelBubble = true;
-        }
-    },
-
-    /**
-     * Method: preventDefault
-     * Cancels the event if it is cancelable, without stopping further
-     * propagation of the event.
-     *
-     * Parameters:
-     * event - {Event}
-     */
-    preventDefault: function(event) {
-        if (event.preventDefault) {
-            event.preventDefault();
-        } else {
-            event.returnValue = false;
-        }
-    },
-
-    /** 
-     * Method: findElement
-     * 
-     * Parameters:
-     * event - {Event} 
-     * tagName - {String} 
-     * 
-     * Returns:
-     * {DOMElement} The first node with the given tagName, starting from the
-     * node the event was triggered on and traversing the DOM upwards
-     */
-    findElement: function(event, tagName) {
-        var element = OpenLayers.Event.element(event);
-        while (element.parentNode && (!element.tagName ||
-              (element.tagName.toUpperCase() != tagName.toUpperCase()))){
-            element = element.parentNode;
-        }
-        return element;
-    },
-
-    /** 
-     * Method: observe
-     * 
-     * Parameters:
-     * elementParam - {DOMElement || String} 
-     * name - {String} 
-     * observer - {function} 
-     * useCapture - {Boolean} 
-     */
-    observe: function(elementParam, name, observer, useCapture) {
-        var element = OpenLayers.Util.getElement(elementParam);
-        useCapture = useCapture || false;
-
-        if (name == 'keypress' &&
-           (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
-           || element.attachEvent)) {
-            name = 'keydown';
-        }
-
-        //if observers cache has not yet been created, create it
-        if (!this.observers) {
-            this.observers = {};
-        }
-
-        //if not already assigned, make a new unique cache ID
-        if (!element._eventCacheID) {
-            var idPrefix = "eventCacheID_";
-            if (element.id) {
-                idPrefix = element.id + "_" + idPrefix;
-            }
-            element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix);
-        }
-
-        var cacheID = element._eventCacheID;
-
-        //if there is not yet a hash entry for this element, add one
-        if (!this.observers[cacheID]) {
-            this.observers[cacheID] = [];
-        }
-
-        //add a new observer to this element's list
-        this.observers[cacheID].push({
-            'element': element,
-            'name': name,
-            'observer': observer,
-            'useCapture': useCapture
-        });
-
-        //add the actual browser event listener
-        if (element.addEventListener) {
-            element.addEventListener(name, observer, useCapture);
-        } else if (element.attachEvent) {
-            element.attachEvent('on' + name, observer);
-        }
-    },
-
-    /** 
-     * Method: stopObservingElement
-     * Given the id of an element to stop observing, cycle through the 
-     *   element's cached observers, calling stopObserving on each one, 
-     *   skipping those entries which can no longer be removed.
-     * 
-     * parameters:
-     * elementParam - {DOMElement || String} 
-     */
-    stopObservingElement: function(elementParam) {
-        var element = OpenLayers.Util.getElement(elementParam);
-        var cacheID = element._eventCacheID;
-
-        this._removeElementObservers(OpenLayers.Event.observers[cacheID]);
-    },
-
-    /**
-     * Method: _removeElementObservers
-     *
-     * Parameters:
-     * elementObservers - {Array(Object)} Array of (element, name, 
-     *                                         observer, usecapture) objects, 
-     *                                         taken directly from hashtable
-     */
-    _removeElementObservers: function(elementObservers) {
-        if (elementObservers) {
-            for(var i = elementObservers.length-1; i >= 0; i--) {
-                var entry = elementObservers[i];
-                OpenLayers.Event.stopObserving.apply(this, [
-                    entry.element, entry.name, entry.observer, entry.useCapture
-                ]);
-            }
-        }
-    },
-
-    /**
-     * Method: stopObserving
-     * 
-     * Parameters:
-     * elementParam - {DOMElement || String} 
-     * name - {String} 
-     * observer - {function} 
-     * useCapture - {Boolean} 
-     *  
-     * Returns:
-     * {Boolean} Whether or not the event observer was removed
-     */
-    stopObserving: function(elementParam, name, observer, useCapture) {
-        useCapture = useCapture || false;
-    
-        var element = OpenLayers.Util.getElement(elementParam);
-        var cacheID = element._eventCacheID;
-
-        if (name == 'keypress') {
-            if ( navigator.appVersion.match(/Konqueror|Safari|KHTML/) || 
-                 element.detachEvent) {
-              name = 'keydown';
-            }
-        }
-
-        // find element's entry in this.observers cache and remove it
-        var foundEntry = false;
-        var elementObservers = OpenLayers.Event.observers[cacheID];
-        if (elementObservers) {
-    
-            // find the specific event type in the element's list
-            var i=0;
-            while(!foundEntry && i < elementObservers.length) {
-                var cacheEntry = elementObservers[i];
-    
-                if ((cacheEntry.name == name) &&
-                    (cacheEntry.observer == observer) &&
-                    (cacheEntry.useCapture == useCapture)) {
-    
-                    elementObservers.splice(i, 1);
-                    if (elementObservers.length == 0) {
-                        delete OpenLayers.Event.observers[cacheID];
-                    }
-                    foundEntry = true;
-                    break; 
-                }
-                i++;           
-            }
-        }
-    
-        //actually remove the event listener from browser
-        if (foundEntry) {
-            if (element.removeEventListener) {
-                element.removeEventListener(name, observer, useCapture);
-            } else if (element && element.detachEvent) {
-                element.detachEvent('on' + name, observer);
-            }
-        }
-        return foundEntry;
-    },
-    
-    /** 
-     * Method: unloadCache
-     * Cycle through all the element entries in the events cache and call
-     *   stopObservingElement on each. 
-     */
-    unloadCache: function() {
-        // check for OpenLayers.Event before checking for observers, because
-        // OpenLayers.Event may be undefined in IE if no map instance was
-        // created
-        if (OpenLayers.Event && OpenLayers.Event.observers) {
-            for (var cacheID in OpenLayers.Event.observers) {
-                var elementObservers = OpenLayers.Event.observers[cacheID];
-                OpenLayers.Event._removeElementObservers.apply(this, 
-                                                           [elementObservers]);
-            }
-            OpenLayers.Event.observers = false;
-        }
-    },
-
-    CLASS_NAME: "OpenLayers.Event"
-};
-
-/* prevent memory leaks in IE */
-OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false);
-
-/**
- * Class: OpenLayers.Events
- */
-OpenLayers.Events = OpenLayers.Class({
-
-    /** 
-     * Constant: BROWSER_EVENTS
-     * {Array(String)} supported events 
-     */
-    BROWSER_EVENTS: [
-        "mouseover", "mouseout",
-        "mousedown", "mouseup", "mousemove", 
-        "click", "dblclick", "rightclick", "dblrightclick",
-        "resize", "focus", "blur",
-        "touchstart", "touchmove", "touchend",
-        "keydown"
-    ],
-    
-    /**
-     * Constant: standard pointer model
-     * {string}
-     */
-    TOUCH_MODEL_POINTER: "pointer",
-
-    /**
-     * Constant: prefixed pointer model (IE10)
-     * {string}
-     */
-    TOUCH_MODEL_MSPOINTER: "MSPointer",
-
-    /**
-     * Constant: legacy touch model
-     * {string}
-     */
-    TOUCH_MODEL_TOUCH: "touch",
-
-    /** 
-     * Property: listeners 
-     * {Object} Hashtable of Array(Function): events listener functions  
-     */
-    listeners: null,
-
-    /** 
-     * Property: object 
-     * {Object}  the code object issuing application events 
-     */
-    object: null,
-
-    /** 
-     * Property: element 
-     * {DOMElement}  the DOM element receiving browser events 
-     */
-    element: null,
-
-    /** 
-     * Property: eventHandler 
-     * {Function}  bound event handler attached to elements 
-     */
-    eventHandler: null,
-
-    /** 
-     * APIProperty: fallThrough 
-     * {Boolean} 
-     */
-    fallThrough: null,
-
-    /** 
-     * APIProperty: includeXY
-     * {Boolean} Should the .xy property automatically be created for browser
-     *    mouse events? In general, this should be false. If it is true, then
-     *    mouse events will automatically generate a '.xy' property on the 
-     *    event object that is passed. (Prior to OpenLayers 2.7, this was true
-     *    by default.) Otherwise, you can call the getMousePosition on the
-     *    relevant events handler on the object available via the 'evt.object'
-     *    property of the evt object. So, for most events, you can call:
-     *    function named(evt) { 
-     *        this.xy = this.object.events.getMousePosition(evt) 
-     *    } 
-     *
-     *    This option typically defaults to false for performance reasons:
-     *    when creating an events object whose primary purpose is to manage
-     *    relatively positioned mouse events within a div, it may make
-     *    sense to set it to true.
-     *
-     *    This option is also used to control whether the events object caches
-     *    offsets. If this is false, it will not: the reason for this is that
-     *    it is only expected to be called many times if the includeXY property
-     *    is set to true. If you set this to true, you are expected to clear 
-     *    the offset cache manually (using this.clearMouseCache()) if:
-     *        the border of the element changes
-     *        the location of the element in the page changes
-    */
-    includeXY: false,      
-    
-    /**
-     * APIProperty: extensions
-     * {Object} Event extensions registered with this instance. Keys are
-     *     event types, values are {OpenLayers.Events.*} extension instances or
-     *     {Boolean} for events that an instantiated extension provides in
-     *     addition to the one it was created for.
-     *
-     * Extensions create an event in addition to browser events, which usually
-     * fires when a sequence of browser events is completed. Extensions are
-     * automatically instantiated when a listener is registered for an event
-     * provided by an extension.
-     *
-     * Extensions are created in the <OpenLayers.Events> namespace using
-     * <OpenLayers.Class>, and named after the event they provide.
-     * The constructor receives the target <OpenLayers.Events> instance as
-     * argument. Extensions that need to capture browser events before they
-     * propagate can register their listeners events using <register>, with
-     * {extension: true} as 4th argument.
-     *
-     * If an extension creates more than one event, an alias for each event
-     * type should be created and reference the same class. The constructor
-     * should set a reference in the target's extensions registry to itself.
-     *
-     * Below is a minimal extension that provides the "foostart" and "fooend"
-     * event types, which replace the native "click" event type if clicked on
-     * an element with the css class "foo":
-     *
-     * (code)
-     *   OpenLayers.Events.foostart = OpenLayers.Class({
-     *       initialize: function(target) {
-     *           this.target = target;
-     *           this.target.register("click", this, this.doStuff, {extension: true});
-     *           // only required if extension provides more than one event type
-     *           this.target.extensions["foostart"] = true;
-     *           this.target.extensions["fooend"] = true;
-     *       },
-     *       destroy: function() {
-     *           var target = this.target;
-     *           target.unregister("click", this, this.doStuff);
-     *           delete this.target;
-     *           // only required if extension provides more than one event type
-     *           delete target.extensions["foostart"];
-     *           delete target.extensions["fooend"];
-     *       },
-     *       doStuff: function(evt) {
-     *           var propagate = true;
-     *           if (OpenLayers.Event.element(evt).className === "foo") {
-     *               propagate = false;
-     *               var target = this.target;
-     *               target.triggerEvent("foostart");
-     *               window.setTimeout(function() {
-     *                   target.triggerEvent("fooend");
-     *               }, 1000);
-     *           }
-     *           return propagate;
-     *       }
-     *   });
-     *   // only required if extension provides more than one event type
-     *   OpenLayers.Events.fooend = OpenLayers.Events.foostart;
-     * (end)
-     * 
-     */
-    extensions: null,
-    
-    /**
-     * Property: extensionCount
-     * {Object} Keys are event types (like in <listeners>), values are the
-     *     number of extension listeners for each event type.
-     */
-    extensionCount: null,
-
-    /**
-     * Method: clearMouseListener
-     * A version of <clearMouseCache> that is bound to this instance so that
-     *     it can be used with <OpenLayers.Event.observe> and
-     *     <OpenLayers.Event.stopObserving>.
-     */
-    clearMouseListener: null,
-
-    /**
-     * Constructor: OpenLayers.Events
-     * Construct an OpenLayers.Events object.
-     *
-     * Parameters:
-     * object - {Object} The js object to which this Events object  is being added
-     * element - {DOMElement} A dom element to respond to browser events
-     * eventTypes - {Array(String)} Deprecated.  Array of custom application
-     *     events.  A listener may be registered for any named event, regardless
-     *     of the values provided here.
-     * fallThrough - {Boolean} Allow events to fall through after these have
-     *                         been handled?
-     * options - {Object} Options for the events object.
-     */
-    initialize: function (object, element, eventTypes, fallThrough, options) {
-        OpenLayers.Util.extend(this, options);
-        this.object     = object;
-        this.fallThrough = fallThrough;
-        this.listeners  = {};
-        this.extensions = {};
-        this.extensionCount = {};
-        this._pointerTouches = [];
-        
-        // if a dom element is specified, add a listeners list 
-        // for browser events on the element and register them
-        if (element != null) {
-            this.attachToElement(element);
-        }
-    },
-
-    /**
-     * APIMethod: destroy
-     */
-    destroy: function () {
-        for (var e in this.extensions) {
-            if (typeof this.extensions[e] !== "boolean") {
-                this.extensions[e].destroy();
-            }
-        }
-        this.extensions = null;
-        if (this.element) {
-            OpenLayers.Event.stopObservingElement(this.element);
-            if(this.element.hasScrollEvent) {
-                OpenLayers.Event.stopObserving(
-                    window, "scroll", this.clearMouseListener
-                );
-            }
-        }
-        this.element = null;
-
-        this.listeners = null;
-        this.object = null;
-        this.fallThrough = null;
-        this.eventHandler = null;
-    },
-
-    /**
-     * APIMethod: addEventType
-     * Deprecated.  Any event can be triggered without adding it first.
-     * 
-     * Parameters:
-     * eventName - {String}
-     */
-    addEventType: function(eventName) {
-    },
-
-    /**
-     * Method: attachToElement
-     *
-     * Parameters:
-     * element - {HTMLDOMElement} a DOM element to attach browser events to
-     */
-    attachToElement: function (element) {
-        if (this.element) {
-            OpenLayers.Event.stopObservingElement(this.element);
-        } else {
-            // keep a bound copy of handleBrowserEvent() so that we can
-            // pass the same function to both Event.observe() and .stopObserving()
-            this.eventHandler = OpenLayers.Function.bindAsEventListener(
-                this.handleBrowserEvent, this
-            );
-            
-            // to be used with observe and stopObserving
-            this.clearMouseListener = OpenLayers.Function.bind(
-                this.clearMouseCache, this
-            );
-        }
-        this.element = element;
-        var touchModel = this.getTouchModel();
-        var type;
-        for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) {
-            type = this.BROWSER_EVENTS[i];
-            // register the event cross-browser
-            OpenLayers.Event.observe(element, type, this.eventHandler
-            );
-            if ((touchModel === this.TOUCH_MODEL_POINTER ||
-                    touchModel === this.TOUCH_MODEL_MSPOINTER) &&
-                    type.indexOf('touch') === 0) {
-                this.addPointerTouchListener(element, type, this.eventHandler);
-            }
-        }
-        // disable dragstart in IE so that mousedown/move/up works normally
-        OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop);
-    },
-    
-    /**
-     * APIMethod: on
-     * Convenience method for registering listeners with a common scope.
-     *     Internally, this method calls <register> as shown in the examples
-     *     below.
-     *
-     * Example use:
-     * (code)
-     * // register a single listener for the "loadstart" event
-     * events.on({"loadstart": loadStartListener});
-     *
-     * // this is equivalent to the following
-     * events.register("loadstart", undefined, loadStartListener);
-     *
-     * // register multiple listeners to be called with the same `this` object
-     * events.on({
-     *     "loadstart": loadStartListener,
-     *     "loadend": loadEndListener,
-     *     scope: object
-     * });
-     *
-     * // this is equivalent to the following
-     * events.register("loadstart", object, loadStartListener);
-     * events.register("loadend", object, loadEndListener);
-     * (end)
-     *
-     * Parameters:
-     *  object - {Object}     
-     */
-    on: function(object) {
-        for(var type in object) {
-            if(type != "scope" && object.hasOwnProperty(type)) {
-                this.register(type, object.scope, object[type]);
-            }
-        }
-    },
-
-    /**
-     * APIMethod: register
-     * Register an event on the events object.
-     *
-     * When the event is triggered, the 'func' function will be called, in the
-     * context of 'obj'. Imagine we were to register an event, specifying an 
-     * OpenLayers.Bounds Object as 'obj'. When the event is triggered, the 
-     * context in the callback function will be our Bounds object. This means
-     * that within our callback function, we can access the properties and 
-     * methods of the Bounds object through the "this" variable. So our 
-     * callback could execute something like: 
-     * :    leftStr = "Left: " + this.left;
-     *   
-     *                   or
-     *  
-     * :    centerStr = "Center: " + this.getCenterLonLat();
-     *
-     * Parameters:
-     * type - {String} Name of the event to register
-     * obj - {Object} The object to bind the context to for the callback#.
-     *     If no object is specified, default is the Events's 'object' property.
-     * func - {Function} The callback function. If no callback is 
-     *     specified, this function does nothing.
-     * priority - {Boolean|Object} If true, adds the new listener to the
-     *     *front* of the events queue instead of to the end.
-     *
-     * Valid options for priority:
-     * extension - {Boolean} If true, then the event will be registered as
-     *     extension event. Extension events are handled before all other
-     *     events.
-     */
-    register: function (type, obj, func, priority) {
-        if (type in OpenLayers.Events && !this.extensions[type]) {
-            this.extensions[type] = new OpenLayers.Events[type](this);
-        }
-        if (func != null) {
-            if (obj == null)  {
-                obj = this.object;
-            }
-            var listeners = this.listeners[type];
-            if (!listeners) {
-                listeners = [];
-                this.listeners[type] = listeners;
-                this.extensionCount[type] = 0;
-            }
-            var listener = {obj: obj, func: func};
-            if (priority) {
-                listeners.splice(this.extensionCount[type], 0, listener);
-                if (typeof priority === "object" && priority.extension) {
-                    this.extensionCount[type]++;
-                }
-            } else {
-                listeners.push(listener);
-            }
-        }
-    },
-
-    /**
-     * APIMethod: registerPriority
-     * Same as register() but adds the new listener to the *front* of the
-     *     events queue instead of to the end.
-     *    
-     *     TODO: get rid of this in 3.0 - Decide whether listeners should be 
-     *     called in the order they were registered or in reverse order.
-     *
-     *
-     * Parameters:
-     * type - {String} Name of the event to register
-     * obj - {Object} The object to bind the context to for the callback#.
-     *                If no object is specified, default is the Events's 
-     *                'object' property.
-     * func - {Function} The callback function. If no callback is 
-     *                   specified, this function does nothing.
-     */
-    registerPriority: function (type, obj, func) {
-        this.register(type, obj, func, true);
-    },
-    
-    /**
-     * APIMethod: un
-     * Convenience method for unregistering listeners with a common scope.
-     *     Internally, this method calls <unregister> as shown in the examples
-     *     below.
-     *
-     * Example use:
-     * (code)
-     * // unregister a single listener for the "loadstart" event
-     * events.un({"loadstart": loadStartListener});
-     *
-     * // this is equivalent to the following
-     * events.unregister("loadstart", undefined, loadStartListener);
-     *
-     * // unregister multiple listeners with the same `this` object
-     * events.un({
-     *     "loadstart": loadStartListener,
-     *     "loadend": loadEndListener,
-     *     scope: object
-     * });
-     *
-     * // this is equivalent to the following
-     * events.unregister("loadstart", object, loadStartListener);
-     * events.unregister("loadend", object, loadEndListener);
-     * (end)
-     */
-    un: function(object) {
-        for(var type in object) {
-            if(type != "scope" && object.hasOwnProperty(type)) {
-                this.unregister(type, object.scope, object[type]);
-            }
-        }
-    },
-
-    /**
-     * APIMethod: unregister
-     *
-     * Parameters:
-     * type - {String} 
-     * obj - {Object} If none specified, defaults to this.object
-     * func - {Function} 
-     */
-    unregister: function (type, obj, func) {
-        if (obj == null)  {
-            obj = this.object;
-        }
-        var listeners = this.listeners[type];
-        if (listeners != null) {
-            for (var i=0, len=listeners.length; i<len; i++) {
-                if (listeners[i].obj == obj && listeners[i].func == func) {
-                    listeners.splice(i, 1);
-                    break;
-                }
-            }
-        }
-    },
-
-    /** 
-     * Method: remove
-     * Remove all listeners for a given event type. If type is not registered,
-     *     does nothing.
-     *
-     * Parameters:
-     * type - {String} 
-     */
-    remove: function(type) {
-        if (this.listeners[type] != null) {
-            this.listeners[type] = [];
-        }
-    },
-
-    /**
-     * APIMethod: triggerEvent
-     * Trigger a specified registered event.  
-     * 
-     * Parameters:
-     * type - {String} 
-     * evt - {Event || Object} will be passed to the listeners.
-     *
-     * Returns:
-     * {Boolean} The last listener return.  If a listener returns false, the
-     *     chain of listeners will stop getting called.
-     */
-    triggerEvent: function (type, evt) {
-        var listeners = this.listeners[type];
-
-        // fast path
-        if(!listeners || listeners.length == 0) {
-            return undefined;
-        }
-
-        // prep evt object with object & div references
-        if (evt == null) {
-            evt = {};
-        }
-        evt.object = this.object;
-        evt.element = this.element;
-        if(!evt.type) {
-            evt.type = type;
-        }
-    
-        // execute all callbacks registered for specified type
-        // get a clone of the listeners array to
-        // allow for splicing during callbacks
-        listeners = listeners.slice();
-        var continueChain;
-        for (var i=0, len=listeners.length; i<len; i++) {
-            var callback = listeners[i];
-            // bind the context to callback.obj
-            continueChain = callback.func.apply(callback.obj, [evt]);
-
-            if ((continueChain != undefined) && (continueChain == false)) {
-                // if callback returns false, execute no more callbacks.
-                break;
-            }
-        }
-        // don't fall through to other DOM elements
-        if (!this.fallThrough) {           
-            OpenLayers.Event.stop(evt, true);
-        }
-        return continueChain;
-    },
-
-    /**
-     * Method: handleBrowserEvent
-     * Basically just a wrapper to the triggerEvent() function, but takes 
-     *     care to set a property 'xy' on the event with the current mouse 
-     *     position.
-     *
-     * Parameters:
-     * evt - {Event} 
-     */
-    handleBrowserEvent: function (evt) {
-        var type = evt.type, listeners = this.listeners[type];
-        if(!listeners || listeners.length == 0) {
-            // noone's listening, bail out
-            return;
-        }
-        // add clientX & clientY to all events - corresponds to average x, y
-        var touches = evt.touches;
-        if (touches && touches[0]) {
-            var x = 0;
-            var y = 0;
-            var num = touches.length;
-            var touch;
-            for (var i=0; i<num; ++i) {
-                touch = this.getTouchClientXY(touches[i]);
-                x += touch.clientX;
-                y += touch.clientY;
-            }
-            evt.clientX = x / num;
-            evt.clientY = y / num;
-        }
-        if (this.includeXY) {
-            evt.xy = this.getMousePosition(evt);
-        } 
-        this.triggerEvent(type, evt);
-    },
-    
-    /**
-     * Method: getTouchClientXY
-     * WebKit has a few bugs for clientX/clientY. This method detects them
-     * and calculate the correct values.
-     *
-     * Parameters:
-     * evt - {Touch} a Touch object from a TouchEvent
-     * 
-     * Returns:
-     * {Object} An object with only clientX and clientY properties with the
-     * calculated values.
-     */
-    getTouchClientXY: function (evt) {
-        // olMochWin is to override window, used for testing
-        var win = window.olMockWin || window,
-            winPageX = win.pageXOffset,
-            winPageY = win.pageYOffset,
-            x = evt.clientX,
-            y = evt.clientY;
-        
-        if (evt.pageY === 0 && Math.floor(y) > Math.floor(evt.pageY) ||
-            evt.pageX === 0 && Math.floor(x) > Math.floor(evt.pageX)) {
-            // iOS4 include scroll offset in clientX/Y
-            x = x - winPageX;
-            y = y - winPageY;
-        } else if (y < (evt.pageY - winPageY) || x < (evt.pageX - winPageX) ) {
-            // Some Android browsers have totally bogus values for clientX/Y
-            // when scrolling/zooming a page
-            x = evt.pageX - winPageX;
-            y = evt.pageY - winPageY;
-        }
-        
-        evt.olClientX = x;
-        evt.olClientY = y;
-        
-        return {
-            clientX: x,
-            clientY: y
-        };
-    },
-    
-    /**
-     * APIMethod: clearMouseCache
-     * Clear cached data about the mouse position. This should be called any 
-     *     time the element that events are registered on changes position 
-     *     within the page.
-     */
-    clearMouseCache: function() { 
-        this.element.scrolls = null;
-        this.element.lefttop = null;
-        this.element.offsets = null;
-    },      
-
-    /**
-     * Method: getMousePosition
-     * 
-     * Parameters:
-     * evt - {Event} 
-     * 
-     * Returns:
-     * {<OpenLayers.Pixel>} The current xy coordinate of the mouse, adjusted
-     *                      for offsets
-     */
-    getMousePosition: function (evt) {
-        if (!this.includeXY) {
-            this.clearMouseCache();
-        } else if (!this.element.hasScrollEvent) {
-            OpenLayers.Event.observe(window, "scroll", this.clearMouseListener);
-            this.element.hasScrollEvent = true;
-        }
-        
-        if (!this.element.scrolls) {
-            var viewportElement = OpenLayers.Util.getViewportElement();
-            this.element.scrolls = [
-                window.pageXOffset || viewportElement.scrollLeft,
-                window.pageYOffset || viewportElement.scrollTop
-            ];
-        }
-
-        if (!this.element.lefttop) {
-            this.element.lefttop = [
-                (document.documentElement.clientLeft || 0),
-                (document.documentElement.clientTop  || 0)
-            ];
-        }
-        
-        if (!this.element.offsets) {
-            this.element.offsets = OpenLayers.Util.pagePosition(this.element);
-        }
-
-        return new OpenLayers.Pixel(
-            (evt.clientX + this.element.scrolls[0]) - this.element.offsets[0]
-                         - this.element.lefttop[0], 
-            (evt.clientY + this.element.scrolls[1]) - this.element.offsets[1]
-                         - this.element.lefttop[1]
-        ); 
-    },
-
-    /**
-     * Method: getTouchModel
-     * Get the touch model currently in use.
-     * 
-     * This is cached on OpenLayers.Events as _TOUCH_MODEL 
-     * 
-     * Returns:
-     * {string} The current touch model (TOUCH_MODEL_xxx), null if none
-     */
-    getTouchModel: function() {
-        if (!("_TOUCH_MODEL" in OpenLayers.Events)) {
-            OpenLayers.Events._TOUCH_MODEL =
-                    (window.PointerEvent && "pointer") ||
-                    (window.MSPointerEvent && "MSPointer") ||
-                    (("ontouchdown" in document) && "touch") ||
-                    null;
-        }
-        return OpenLayers.Events._TOUCH_MODEL;
-    },
-
-    /**
-     * Method: addPointerTouchListener
-     *
-     * Parameters:
-     * element - {DOMElement} The DOM element to register the listener on
-     * type - {String} The event type
-     * handler - {Function} the handler
-     */
-    addPointerTouchListener: function (element, type, handler) {
-        var eventHandler = this.eventHandler;
-        var touches = this._pointerTouches;
-
-        function pointerHandler(evt) {
-            handler(OpenLayers.Util.applyDefaults({
-                stopPropagation: function() {
-                    for (var i=touches.length-1; i>=0; --i) {
-                        touches[i].stopPropagation();
-                    }
-                },
-                preventDefault: function() {
-                    for (var i=touches.length-1; i>=0; --i) {
-                        touches[i].preventDefault();
-                    }
-                },
-                type: type
-            }, evt));
-        }
-
-        switch (type) {
-            case 'touchstart':
-                return this.addPointerTouchListenerStart(element, type, pointerHandler);
-            case 'touchend':
-                return this.addPointerTouchListenerEnd(element, type, pointerHandler);
-            case 'touchmove':
-                return this.addPointerTouchListenerMove(element, type, pointerHandler);
-            default:
-                throw 'Unknown touch event type';
-        }
-    },
-
-    /**
-     * Method: addPointerTouchListenerStart
-     *
-     * Parameters:
-     * element - {DOMElement} The DOM element to register the listener on
-     * type - {String} The event type
-     * handler - {Function} the handler
-     */
-    addPointerTouchListenerStart: function(element, type, handler) {
-        var touches = this._pointerTouches;
-
-        var cb = function(e) {
-
-            // pointer could be mouse or pen
-            if (!OpenLayers.Event.isTouchEvent(e)) {
-                return;
-            }
-
-            var alreadyInArray = false;
-            for (var i=0, ii=touches.length; i<ii; ++i) {
-                if (touches[i].pointerId == e.pointerId) {
-                    alreadyInArray = true;
-                    break;
-                }
-            }
-            if (!alreadyInArray) {
-                touches.push(e);
-            }
-
-            e.touches = touches.slice();
-            handler(e);
-        };
-
-        OpenLayers.Event.observe(element,
-                this.getTouchModel() === this.TOUCH_MODEL_MSPOINTER ?
-                        'MSPointerDown' : 'pointerdown',
-                cb);
-        
-        // the pointerId only needs to be removed from the _pointerTouches array
-        // when the pointer has left its element
-        var internalCb = function (e) {
-
-            // pointer could be mouse or pen
-            if (!OpenLayers.Event.isTouchEvent(e)) {
-               return;
-            }
-
-            var up = false;
-            for (var i = 0, ii = touches.length; i < ii; ++i) {
-                if (touches[i].pointerId == e.pointerId) {
-                    if (this.clientWidth != 0 && this.clientHeight != 0) {
-                        if ((Math.ceil(e.clientX) >= this.clientWidth || Math.ceil(e.clientY) >= this.clientHeight)) {
-                            touches.splice(i, 1);
-                        }
-                    }
-                    break;
-                }
-            }
-        };
-        OpenLayers.Event.observe(element,
-                this.getTouchModel() === this.TOUCH_MODEL_MSPOINTER ?
-                        'MSPointerOut' : 'pointerout',
-                internalCb);
-    },
-
-    /**
-     * Method: addPointerTouchListenerMove
-     *
-     * Parameters:
-     * element - {DOMElement} The DOM element to register the listener on
-     * type - {String} The event type
-     * handler - {Function} the handler
-     */
-    addPointerTouchListenerMove: function (element, type, handler) {
-        var touches = this._pointerTouches;
-        var cb = function(e) {
-
-            // pointer could be mouse or pen
-            if (!OpenLayers.Event.isTouchEvent(e)) {
-                return;
-            }
-
-            if (touches.length == 1 && touches[0].pageX == e.pageX &&
-                    touches[0].pageY == e.pageY) {
-                // don't trigger event when pointer has not moved
-                return;
-            }
-            for (var i=0, ii=touches.length; i<ii; ++i) {
-                if (touches[i].pointerId == e.pointerId) {
-                    touches[i] = e;
-                    break;
-                }
-            }
-
-            e.touches = touches.slice();
-            handler(e);
-        };
-
-        OpenLayers.Event.observe(element,
-                this.getTouchModel() === this.TOUCH_MODEL_MSPOINTER ?
-                        'MSPointerMove' : 'pointermove',
-                cb);
-    },
-
-    /**
-     * Method: addPointerTouchListenerEnd
-     *
-     * Parameters:
-     * element - {DOMElement} The DOM element to register the listener on
-     * type - {String} The event type
-     * handler - {Function} the handler
-     */
-    addPointerTouchListenerEnd: function (element, type, handler) {
-        var touches = this._pointerTouches;
-
-        var cb = function(e) {
-
-            // pointer could be mouse or pen
-            if (!OpenLayers.Event.isTouchEvent(e)) {
-               return;
-            }
-
-            for (var i=0, ii=touches.length; i<ii; ++i) {
-                if (touches[i].pointerId == e.pointerId) {
-                    touches.splice(i, 1);
-                    break;
-                }
-            }
-            
-            e.touches = touches.slice();
-            handler(e);
-        };
-
-        OpenLayers.Event.observe(element,
-                this.getTouchModel() === this.TOUCH_MODEL_MSPOINTER ?
-                        'MSPointerUp' : 'pointerup',
-                cb);
-    },
-
-    CLASS_NAME: "OpenLayers.Events"
-});
-/* ======================================================================
-    OpenLayers/Icon.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- */
-
-/**
- * Class: OpenLayers.Icon
- * 
- * The icon represents a graphical icon on the screen.  Typically used in
- * conjunction with a <OpenLayers.Marker> to represent markers on a screen.
- *
- * An icon has a url, size and position.  It also contains an offset which 
- * allows the center point to be represented correctly.  This can be
- * provided either as a fixed offset or a function provided to calculate
- * the desired offset. 
- * 
- */
-OpenLayers.Icon = OpenLayers.Class({
-    
-    /** 
-     * Property: url 
-     * {String}  image url
-     */
-    url: null,
-    
-    /** 
-     * Property: size 
-     * {<OpenLayers.Size>|Object} An OpenLayers.Size or
-     * an object with a 'w' and 'h' properties.
-     */
-    size: null,
-
-    /** 
-     * Property: offset 
-     * {<OpenLayers.Pixel>|Object} distance in pixels to offset the
-     * image when being rendered. An OpenLayers.Pixel or an object
-     * with a 'x' and 'y' properties.
-     */
-    offset: null,    
-    
-    /** 
-     * Property: calculateOffset 
-     * {Function} Function to calculate the offset (based on the size)
-     */
-    calculateOffset: null,    
-    
-    /** 
-     * Property: imageDiv 
-     * {DOMElement} 
-     */
-    imageDiv: null,
-
-    /** 
-     * Property: px 
-     * {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an object
-     * with a 'x' and 'y' properties.
-     */
-    px: null,
-    
-    /** 
-     * Constructor: OpenLayers.Icon
-     * Creates an icon, which is an image tag in a div.  
-     *
-     * url - {String} 
-     * size - {<OpenLayers.Size>|Object} An OpenLayers.Size or an
-     *                                   object with a 'w' and 'h'
-     *                                   properties.
-     * offset - {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an
-     *                                      object with a 'x' and 'y'
-     *                                      properties.
-     * calculateOffset - {Function} 
-     */
-    initialize: function(url, size, offset, calculateOffset) {
-        this.url = url;
-        this.size = size || {w: 20, h: 20};
-        this.offset = offset || {x: -(this.size.w/2), y: -(this.size.h/2)};
-        this.calculateOffset = calculateOffset;
-
-        var id = OpenLayers.Util.createUniqueID("OL_Icon_");
-        this.imageDiv = OpenLayers.Util.createAlphaImageDiv(id);
-    },
-    
-    /** 
-     * Method: destroy
-     * Nullify references and remove event listeners to prevent circular 
-     * references and memory leaks
-     */
-    destroy: function() {
-        // erase any drawn elements
-        this.erase();
-
-        OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild); 
-        this.imageDiv.innerHTML = "";
-        this.imageDiv = null;
-    },
-
-    /** 
-     * Method: clone
-     * 
-     * Returns:
-     * {<OpenLayers.Icon>} A fresh copy of the icon.
-     */
-    clone: function() {
-        return new OpenLayers.Icon(this.url, 
-                                   this.size, 
-                                   this.offset, 
-                                   this.calculateOffset);
-    },
-    
-    /**
-     * Method: setSize
-     * 
-     * Parameters:
-     * size - {<OpenLayers.Size>|Object} An OpenLayers.Size or
-     * an object with a 'w' and 'h' properties.
-     */
-    setSize: function(size) {
-        if (size != null) {
-            this.size = size;
-        }
-        this.draw();
-    },
-    
-    /**
-     * Method: setUrl
-     * 
-     * Parameters:
-     * url - {String} 
-     */
-    setUrl: function(url) {
-        if (url != null) {
-            this.url = url;
-        }
-        this.draw();
-    },
-
-    /** 
-     * Method: draw
-     * Move the div to the given pixel.
-     * 
-     * Parameters:
-     * px - {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an
-     *                                  object with a 'x' and 'y' properties.
-     * 
-     * Returns:
-     * {DOMElement} A new DOM Image of this icon set at the location passed-in
-     */
-    draw: function(px) {
-        OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, 
-                                            null, 
-                                            null, 
-                                            this.size, 
-                                            this.url, 
-                                            "absolute");
-        this.moveTo(px);
-        return this.imageDiv;
-    }, 
-
-    /** 
-     * Method: erase
-     * Erase the underlying image element.
-     */
-    erase: function() {
-        if (this.imageDiv != null && this.imageDiv.parentNode != null) {
-            OpenLayers.Element.remove(this.imageDiv);
-        }
-    }, 
-    
-    /** 
-     * Method: setOpacity
-     * Change the icon's opacity
-     *
-     * Parameters:
-     * opacity - {float} 
-     */
-    setOpacity: function(opacity) {
-        OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null, 
-                                            null, null, null, null, opacity);
-
-    },
-    
-    /**
-     * Method: moveTo
-     * move icon to passed in px.
-     *
-     * Parameters:
-     * px - {<OpenLayers.Pixel>|Object} the pixel position to move to.
-     * An OpenLayers.Pixel or an object with a 'x' and 'y' properties.
-     */
-    moveTo: function (px) {
-        //if no px passed in, use stored location
-        if (px != null) {
-            this.px = px;
-        }
-
-        if (this.imageDiv != null) {
-            if (this.px == null) {
-                this.display(false);
-            } else {
-                if (this.calculateOffset) {
-                    this.offset = this.calculateOffset(this.size);  
-                }
-                OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, {
-                    x: this.px.x + this.offset.x,
-                    y: this.px.y + this.offset.y
-                });
-            }
-        }
-    },
-    
-    /** 
-     * Method: display
-     * Hide or show the icon
-     *
-     * Parameters:
-     * display - {Boolean} 
-     */
-    display: function(display) {
-        this.imageDiv.style.display = (display) ? "" : "none"; 
-    },
-    
-
-    /**
-     * APIMethod: isDrawn
-     * 
-     * Returns:
-     * {Boolean} Whether or not the icon is drawn.
-     */
-    isDrawn: function() {
-        // nodeType 11 for ie, whose nodes *always* have a parentNode
-        // (of type document fragment)
-        var isDrawn = (this.imageDiv && this.imageDiv.parentNode && 
-                       (this.imageDiv.parentNode.nodeType != 11));    
-
-        return isDrawn;   
-    },
-
-    CLASS_NAME: "OpenLayers.Icon"
-});
-/* ======================================================================
-    OpenLayers/Marker.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- * @requires OpenLayers/Events.js
- * @requires OpenLayers/Icon.js
- */
-
-/**
- * Class: OpenLayers.Marker
- * Instances of OpenLayers.Marker are a combination of a 
- * <OpenLayers.LonLat> and an <OpenLayers.Icon>.  
- *
- * Markers are generally added to a special layer called
- * <OpenLayers.Layer.Markers>.
- *
- * Example:
- * (code)
- * var markers = new OpenLayers.Layer.Markers( "Markers" );
- * map.addLayer(markers);
- *
- * var size = new OpenLayers.Size(21,25);
- * var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
- * var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset);
- * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon));
- * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon.clone()));
- *
- * (end)
- *
- * Note that if you pass an icon into the Marker constructor, it will take
- * that icon and use it. This means that you should not share icons between
- * markers -- you use them once, but you should clone() for any additional
- * markers using that same icon.
- */
-OpenLayers.Marker = OpenLayers.Class({
-    
-    /** 
-     * Property: icon 
-     * {<OpenLayers.Icon>} The icon used by this marker.
-     */
-    icon: null,
-
-    /** 
-     * Property: lonlat 
-     * {<OpenLayers.LonLat>} location of object
-     */
-    lonlat: null,
-    
-    /** 
-     * Property: events 
-     * {<OpenLayers.Events>} the event handler.
-     */
-    events: null,
-    
-    /** 
-     * Property: map 
-     * {<OpenLayers.Map>} the map this marker is attached to
-     */
-    map: null,
-    
-    /** 
-     * Constructor: OpenLayers.Marker
-     *
-     * Parameters:
-     * lonlat - {<OpenLayers.LonLat>} the position of this marker
-     * icon - {<OpenLayers.Icon>}  the icon for this marker
-     */
-    initialize: function(lonlat, icon) {
-        this.lonlat = lonlat;
-        
-        var newIcon = (icon) ? icon : OpenLayers.Marker.defaultIcon();
-        if (this.icon == null) {
-            this.icon = newIcon;
-        } else {
-            this.icon.url = newIcon.url;
-            this.icon.size = newIcon.size;
-            this.icon.offset = newIcon.offset;
-            this.icon.calculateOffset = newIcon.calculateOffset;
-        }
-        this.events = new OpenLayers.Events(this, this.icon.imageDiv);
-    },
-    
-    /**
-     * APIMethod: destroy
-     * Destroy the marker. You must first remove the marker from any 
-     * layer which it has been added to, or you will get buggy behavior.
-     * (This can not be done within the marker since the marker does not
-     * know which layer it is attached to.)
-     */
-    destroy: function() {
-        // erase any drawn features
-        this.erase();
-
-        this.map = null;
-
-        this.events.destroy();
-        this.events = null;
-
-        if (this.icon != null) {
-            this.icon.destroy();
-            this.icon = null;
-        }
-    },
-    
-    /** 
-    * Method: draw
-    * Calls draw on the icon, and returns that output.
-    * 
-    * Parameters:
-    * px - {<OpenLayers.Pixel>}
-    * 
-    * Returns:
-    * {DOMElement} A new DOM Image with this marker's icon set at the 
-    * location passed-in
-    */
-    draw: function(px) {
-        return this.icon.draw(px);
-    }, 
-
-    /** 
-    * Method: erase
-    * Erases any drawn elements for this marker.
-    */
-    erase: function() {
-        if (this.icon != null) {
-            this.icon.erase();
-        }
-    }, 
-
-    /**
-    * Method: moveTo
-    * Move the marker to the new location.
-    *
-    * Parameters:
-    * px - {<OpenLayers.Pixel>|Object} the pixel position to move to.
-    * An OpenLayers.Pixel or an object with a 'x' and 'y' properties.
-    */
-    moveTo: function (px) {
-        if ((px != null) && (this.icon != null)) {
-            this.icon.moveTo(px);
-        }           
-        this.lonlat = this.map.getLonLatFromLayerPx(px);
-    },
-
-    /**
-     * APIMethod: isDrawn
-     * 
-     * Returns:
-     * {Boolean} Whether or not the marker is drawn.
-     */
-    isDrawn: function() {
-        var isDrawn = (this.icon && this.icon.isDrawn());
-        return isDrawn;   
-    },
-
-    /**
-     * Method: onScreen
-     *
-     * Returns:
-     * {Boolean} Whether or not the marker is currently visible on screen.
-     */
-    onScreen:function() {
-        
-        var onScreen = false;
-        if (this.map) {
-            var screenBounds = this.map.getExtent();
-            onScreen = screenBounds.containsLonLat(this.lonlat);
-        }    
-        return onScreen;
-    },
-    
-    /**
-     * Method: inflate
-     * Englarges the markers icon by the specified ratio.
-     *
-     * Parameters:
-     * inflate - {float} the ratio to enlarge the marker by (passing 2
-     *                   will double the size).
-     */
-    inflate: function(inflate) {
-        if (this.icon) {
-            this.icon.setSize({
-                w: this.icon.size.w * inflate,
-                h: this.icon.size.h * inflate
-            });
-        }        
-    },
-    
-    /** 
-     * Method: setOpacity
-     * Change the opacity of the marker by changin the opacity of 
-     *   its icon
-     * 
-     * Parameters:
-     * opacity - {float}  Specified as fraction (0.4, etc)
-     */
-    setOpacity: function(opacity) {
-        this.icon.setOpacity(opacity);
-    },
-
-    /**
-     * Method: setUrl
-     * Change URL of the Icon Image.
-     * 
-     * url - {String} 
-     */
-    setUrl: function(url) {
-        this.icon.setUrl(url);
-    },    
-
-    /** 
-     * Method: display
-     * Hide or show the icon
-     * 
-     * display - {Boolean} 
-     */
-    display: function(display) {
-        this.icon.display(display);
-    },
-
-    CLASS_NAME: "OpenLayers.Marker"
-});
-
-
-/**
- * Function: defaultIcon
- * Creates a default <OpenLayers.Icon>.
- * 
- * Returns:
- * {<OpenLayers.Icon>} A default OpenLayers.Icon to use for a marker
- */
-OpenLayers.Marker.defaultIcon = function() {
-    return new OpenLayers.Icon(OpenLayers.Util.getImageLocation("marker.png"),
-                               {w: 21, h: 25}, {x: -10.5, y: -25});
-};
-    
-
-/* ======================================================================
-    OpenLayers/Util/vendorPrefix.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/SingleFile.js
- */
-
-OpenLayers.Util = OpenLayers.Util || {};
-/**
- * Namespace: OpenLayers.Util.vendorPrefix
- * A collection of utility functions to detect vendor prefixed features
- */
-OpenLayers.Util.vendorPrefix = (function() {
-    "use strict";
-    
-    var VENDOR_PREFIXES = ["", "O", "ms", "Moz", "Webkit"],
-        divStyle = document.createElement("div").style,
-        cssCache = {},
-        jsCache = {};
-
-    
-    /**
-     * Function: domToCss
-     * Converts a upper camel case DOM style property name to a CSS property
-     *      i.e. transformOrigin -> transform-origin
-     *      or   WebkitTransformOrigin -> -webkit-transform-origin
-     *
-     * Parameters:
-     * prefixedDom - {String} The property to convert
-     *
-     * Returns:
-     * {String} The CSS property
-     */
-    function domToCss(prefixedDom) {
-        if (!prefixedDom) { return null; }
-        return prefixedDom.
-            replace(/([A-Z])/g, function(c) { return "-" + c.toLowerCase(); }).
-            replace(/^ms-/, "-ms-");
-    }
-
-    /**
-     * APIMethod: css
-     * Detect which property is used for a CSS property
-     *
-     * Parameters:
-     * property - {String} The standard (unprefixed) CSS property name
-     *
-     * Returns:
-     * {String} The standard CSS property, prefixed property or null if not
-     *          supported
-     */
-    function css(property) {
-        if (cssCache[property] === undefined) {
-            var domProperty = property.
-                replace(/(-[\s\S])/g, function(c) { return c.charAt(1).toUpperCase(); });
-            var prefixedDom = style(domProperty);
-            cssCache[property] = domToCss(prefixedDom);
-        }
-        return cssCache[property];
-    }
-
-    /**
-     * APIMethod: js
-     * Detect which property is used for a JS property/method
-     *
-     * Parameters:
-     * obj - {Object} The object to test on
-     * property - {String} The standard (unprefixed) JS property name
-     *
-     * Returns:
-     * {String} The standard JS property, prefixed property or null if not
-     *          supported
-     */
-    function js(obj, property) {
-        if (jsCache[property] === undefined) {
-            var tmpProp,
-                i = 0,
-                l = VENDOR_PREFIXES.length,
-                prefix,
-                isStyleObj = (typeof obj.cssText !== "undefined");
-
-            jsCache[property] = null;
-            for(; i<l; i++) {
-                prefix = VENDOR_PREFIXES[i];
-                if(prefix) {
-                    if (!isStyleObj) {
-                        // js prefix should be lower-case, while style
-                        // properties have upper case on first character
-                        prefix = prefix.toLowerCase();
-                    }
-                    tmpProp = prefix + property.charAt(0).toUpperCase() + property.slice(1);
-                } else {
-                    tmpProp = property;
-                }
-
-                if(obj[tmpProp] !== undefined) {
-                    jsCache[property] = tmpProp;
-                    break;
-                }
-            }
-        }
-        return jsCache[property];
-    }
-    
-    /**
-     * APIMethod: style
-     * Detect which property is used for a DOM style property
-     *
-     * Parameters:
-     * property - {String} The standard (unprefixed) style property name
-     *
-     * Returns:
-     * {String} The standard style property, prefixed property or null if not
-     *          supported
-     */
-    function style(property) {
-        return js(divStyle, property);
-    }
-    
-    return {
-        css:      css,
-        js:       js,
-        style:    style,
-        
-        // used for testing
-        cssCache:       cssCache,
-        jsCache:        jsCache
-    };
-}());
-/* ======================================================================
-    OpenLayers/Animation.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/SingleFile.js
- * @requires OpenLayers/Util/vendorPrefix.js
- */
-
-/**
- * Namespace: OpenLayers.Animation
- * A collection of utility functions for executing methods that repaint a 
- *     portion of the browser window.  These methods take advantage of the
- *     browser's scheduled repaints where requestAnimationFrame is available.
- */
-OpenLayers.Animation = (function(window) {
-    
-    /**
-     * Property: isNative
-     * {Boolean} true if a native requestAnimationFrame function is available
-     */
-    var requestAnimationFrame = OpenLayers.Util.vendorPrefix.js(window, "requestAnimationFrame");
-    var isNative = !!(requestAnimationFrame);
-    
-    /**
-     * Function: requestFrame
-     * Schedule a function to be called at the next available animation frame.
-     *     Uses the native method where available.  Where requestAnimationFrame is
-     *     not available, setTimeout will be called with a 16ms delay.
-     *
-     * Parameters:
-     * callback - {Function} The function to be called at the next animation frame.
-     * element - {DOMElement} Optional element that visually bounds the animation.
-     */
-    var requestFrame = (function() {
-        var request = window[requestAnimationFrame] ||
-            function(callback, element) {
-                window.setTimeout(callback, 16);
-            };
-        // bind to window to avoid illegal invocation of native function
-        return function(callback, element) {
-            request.apply(window, [callback, element]);
-        };
-    })();
-    
-    // private variables for animation loops
-    var counter = 0;
-    var loops = {};
-    
-    /**
-     * Function: start
-     * Executes a method with <requestFrame> in series for some 
-     *     duration.
-     *
-     * Parameters:
-     * callback - {Function} The function to be called at the next animation frame.
-     * duration - {Number} Optional duration for the loop.  If not provided, the
-     *     animation loop will execute indefinitely.
-     * element - {DOMElement} Optional element that visually bounds the animation.
-     *
-     * Returns:
-     * {Number} Identifier for the animation loop.  Used to stop animations with
-     *     <stop>.
-     */
-    function start(callback, duration, element) {
-        duration = duration > 0 ? duration : Number.POSITIVE_INFINITY;
-        var id = ++counter;
-        var start = +new Date;
-        loops[id] = function() {
-            if (loops[id] && +new Date - start <= duration) {
-                callback();
-                if (loops[id]) {
-                    requestFrame(loops[id], element);
-                }
-            } else {
-                delete loops[id];
-            }
-        };
-        requestFrame(loops[id], element);
-        return id;
-    }
-    
-    /**
-     * Function: stop
-     * Terminates an animation loop started with <start>.
-     *
-     * Parameters:
-     * id - {Number} Identifier returned from <start>.
-     */
-    function stop(id) {
-        delete loops[id];
-    }
-    
-    return {
-        isNative: isNative,
-        requestFrame: requestFrame,
-        start: start,
-        stop: stop
-    };
-    
-})(window);
-/* ======================================================================
-    OpenLayers/Tween.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- * @requires OpenLayers/Animation.js
- */
-
-/**
- * Namespace: OpenLayers.Tween
- */
-OpenLayers.Tween = OpenLayers.Class({
-    
-    /**
-     * APIProperty: easing
-     * {<OpenLayers.Easing>(Function)} Easing equation used for the animation
-     *     Defaultly set to OpenLayers.Easing.Expo.easeOut
-     */
-    easing: null,
-    
-    /**
-     * APIProperty: begin
-     * {Object} Values to start the animation with
-     */
-    begin: null,
-    
-    /**
-     * APIProperty: finish
-     * {Object} Values to finish the animation with
-     */
-    finish: null,
-    
-    /**
-     * APIProperty: duration
-     * {int} duration of the tween (number of steps)
-     */
-    duration: null,
-    
-    /**
-     * APIProperty: callbacks
-     * {Object} An object with start, eachStep and done properties whose values
-     *     are functions to be call during the animation. They are passed the
-     *     current computed value as argument.
-     */
-    callbacks: null,
-    
-    /**
-     * Property: time
-     * {int} Step counter
-     */
-    time: null,
-    
-    /**
-     * APIProperty: minFrameRate
-     * {Number} The minimum framerate for animations in frames per second. After
-     * each step, the time spent in the animation is compared to the calculated
-     * time at this frame rate. If the animation runs longer than the calculated
-     * time, the next step is skipped. Default is 30.
-     */
-    minFrameRate: null,
-
-    /**
-     * Property: startTime
-     * {Number} The timestamp of the first execution step. Used for skipping
-     * frames
-     */
-    startTime: null,
-    
-    /**
-     * Property: animationId
-     * {int} Loop id returned by OpenLayers.Animation.start
-     */
-    animationId: null,
-    
-    /**
-     * Property: playing
-     * {Boolean} Tells if the easing is currently playing
-     */
-    playing: false,
-    
-    /** 
-     * Constructor: OpenLayers.Tween
-     * Creates a Tween.
-     *
-     * Parameters:
-     * easing - {<OpenLayers.Easing>(Function)} easing function method to use
-     */ 
-    initialize: function(easing) {
-        this.easing = (easing) ? easing : OpenLayers.Easing.Expo.easeOut;
-    },
-    
-    /**
-     * APIMethod: start
-     * Plays the Tween, and calls the callback method on each step
-     * 
-     * Parameters:
-     * begin - {Object} values to start the animation with
-     * finish - {Object} values to finish the animation with
-     * duration - {int} duration of the tween (number of steps)
-     * options - {Object} hash of options (callbacks (start, eachStep, done),
-     *     minFrameRate)
-     */
-    start: function(begin, finish, duration, options) {
-        this.playing = true;
-        this.begin = begin;
-        this.finish = finish;
-        this.duration = duration;
-        this.callbacks = options.callbacks;
-        this.minFrameRate = options.minFrameRate || 30;
-        this.time = 0;
-        this.startTime = new Date().getTime();
-        OpenLayers.Animation.stop(this.animationId);
-        this.animationId = null;
-        if (this.callbacks && this.callbacks.start) {
-            this.callbacks.start.call(this, this.begin);
-        }
-        this.animationId = OpenLayers.Animation.start(
-            OpenLayers.Function.bind(this.play, this)
-        );
-    },
-    
-    /**
-     * APIMethod: stop
-     * Stops the Tween, and calls the done callback
-     *     Doesn't do anything if animation is already finished
-     */
-    stop: function() {
-        if (!this.playing) {
-            return;
-        }
-        
-        if (this.callbacks && this.callbacks.done) {
-            this.callbacks.done.call(this, this.finish);
-        }
-        OpenLayers.Animation.stop(this.animationId);
-        this.animationId = null;
-        this.playing = false;
-    },
-    
-    /**
-     * Method: play
-     * Calls the appropriate easing method
-     */
-    play: function() {
-        var value = {};
-        for (var i in this.begin) {
-            var b = this.begin[i];
-            var f = this.finish[i];
-            if (b == null || f == null || isNaN(b) || isNaN(f)) {
-                throw new TypeError('invalid value for Tween');
-            }
-
-            var c = f - b;
-            value[i] = this.easing.apply(this, [this.time, b, c, this.duration]);
-        }
-        this.time++;
-        
-        if (this.callbacks && this.callbacks.eachStep) {
-            // skip frames if frame rate drops below threshold
-            if ((new Date().getTime() - this.startTime) / this.time <= 1000 / this.minFrameRate) {
-                this.callbacks.eachStep.call(this, value);
-            }
-        }
-        
-        if (this.time > this.duration) {
-            this.stop();
-        }
-    },
-    
-    /**
-     * Create empty functions for all easing methods.
-     */
-    CLASS_NAME: "OpenLayers.Tween"
-});
-
-/**
- * Namespace: OpenLayers.Easing
- * 
- * Credits:
- *      Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>
- */
-OpenLayers.Easing = {
-    /**
-     * Create empty functions for all easing methods.
-     */
-    CLASS_NAME: "OpenLayers.Easing"
-};
-
-/**
- * Namespace: OpenLayers.Easing.Linear
- */
-OpenLayers.Easing.Linear = {
-    
-    /**
-     * Function: easeIn
-     * 
-     * Parameters:
-     * t - {Float} time
-     * b - {Float} beginning position
-     * c - {Float} total change
-     * d - {Float} duration of the transition
-     *
-     * Returns:
-     * {Float}
-     */
-    easeIn: function(t, b, c, d) {
-        return c*t/d + b;
-    },
-    
-    /**
-     * Function: easeOut
-     * 
-     * Parameters:
-     * t - {Float} time
-     * b - {Float} beginning position
-     * c - {Float} total change
-     * d - {Float} duration of the transition
-     *
-     * Returns:
-     * {Float}
-     */
-    easeOut: function(t, b, c, d) {
-        return c*t/d + b;
-    },
-    
-    /**
-     * Function: easeInOut
-     * 
-     * Parameters:
-     * t - {Float} time
-     * b - {Float} beginning position
-     * c - {Float} total change
-     * d - {Float} duration of the transition
-     *
-     * Returns:
-     * {Float}
-     */
-    easeInOut: function(t, b, c, d) {
-        return c*t/d + b;
-    },
-
-    CLASS_NAME: "OpenLayers.Easing.Linear"
-};
-
-/**
- * Namespace: OpenLayers.Easing.Expo
- */
-OpenLayers.Easing.Expo = {
-    
-    /**
-     * Function: easeIn
-     * 
-     * Parameters:
-     * t - {Float} time
-     * b - {Float} beginning position
-     * c - {Float} total change
-     * d - {Float} duration of the transition
-     *
-     * Returns:
-     * {Float}
-     */
-    easeIn: function(t, b, c, d) {
-        return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
-    },
-    
-    /**
-     * Function: easeOut
-     * 
-     * Parameters:
-     * t - {Float} time
-     * b - {Float} beginning position
-     * c - {Float} total change
-     * d - {Float} duration of the transition
-     *
-     * Returns:
-     * {Float}
-     */
-    easeOut: function(t, b, c, d) {
-        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
-    },
-    
-    /**
-     * Function: easeInOut
-     * 
-     * Parameters:
-     * t - {Float} time
-     * b - {Float} beginning position
-     * c - {Float} total change
-     * d - {Float} duration of the transition
-     *
-     * Returns:
-     * {Float}
-     */
-    easeInOut: function(t, b, c, d) {
-        if (t==0) return b;
-        if (t==d) return b+c;
-        if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
-        return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
-    },
-
-    CLASS_NAME: "OpenLayers.Easing.Expo"
-};
-
-/**
- * Namespace: OpenLayers.Easing.Quad
- */
-OpenLayers.Easing.Quad = {
-    
-    /**
-     * Function: easeIn
-     * 
-     * Parameters:
-     * t - {Float} time
-     * b - {Float} beginning position
-     * c - {Float} total change
-     * d - {Float} duration of the transition
-     *
-     * Returns:
-     * {Float}
-     */
-    easeIn: function(t, b, c, d) {
-        return c*(t/=d)*t + b;
-    },
-    
-    /**
-     * Function: easeOut
-     * 
-     * Parameters:
-     * t - {Float} time
-     * b - {Float} beginning position
-     * c - {Float} total change
-     * d - {Float} duration of the transition
-     *
-     * Returns:
-     * {Float}
-     */
-    easeOut: function(t, b, c, d) {
-        return -c *(t/=d)*(t-2) + b;
-    },
-    
-    /**
-     * Function: easeInOut
-     * 
-     * Parameters:
-     * t - {Float} time
-     * b - {Float} beginning position
-     * c - {Float} total change
-     * d - {Float} duration of the transition
-     *
-     * Returns:
-     * {Float}
-     */
-    easeInOut: function(t, b, c, d) {
-        if ((t/=d/2) < 1) return c/2*t*t + b;
-        return -c/2 * ((--t)*(t-2) - 1) + b;
-    },
-
-    CLASS_NAME: "OpenLayers.Easing.Quad"
-};
-/* ======================================================================
-    OpenLayers/Projection.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- * @requires OpenLayers/Util.js
- */
-
-/**
- * Namespace: OpenLayers.Projection
- * Methods for coordinate transforms between coordinate systems.  By default,
- *     OpenLayers ships with the ability to transform coordinates between
- *     geographic (EPSG:4326) and web or spherical mercator (EPSG:900913 et al.)
- *     coordinate reference systems.  See the <transform> method for details
- *     on usage.
- *
- * Additional transforms may be added by using the <proj4js at http://proj4js.org/>
- *     library.  If the proj4js library is included, the <transform> method 
- *     will work between any two coordinate reference systems with proj4js 
- *     definitions.
- *
- * If the proj4js library is not included, or if you wish to allow transforms
- *     between arbitrary coordinate reference systems, use the <addTransform>
- *     method to register a custom transform method.
- */
-OpenLayers.Projection = OpenLayers.Class({
-
-    /**
-     * Property: proj
-     * {Object} Proj4js.Proj instance.
-     */
-    proj: null,
-    
-    /**
-     * Property: projCode
-     * {String}
-     */
-    projCode: null,
-    
-    /**
-     * Property: titleRegEx
-     * {RegExp} regular expression to strip the title from a proj4js definition
-     */
-    titleRegEx: /\+title=[^\+]*/,
-
-    /**
-     * Constructor: OpenLayers.Projection
-     * This class offers several methods for interacting with a wrapped 
-     *     pro4js projection object. 
-     *
-     * Parameters:
-     * projCode - {String} A string identifying the Well Known Identifier for
-     *    the projection.
-     * options - {Object} An optional object to set additional properties
-     *     on the projection.
-     *
-     * Returns:
-     * {<OpenLayers.Projection>} A projection object.
-     */
-    initialize: function(projCode, options) {
-        OpenLayers.Util.extend(this, options);
-        this.projCode = projCode;
-        if (typeof Proj4js == "object") {
-            this.proj = new Proj4js.Proj(projCode);
-        }
-    },
-    
-    /**
-     * APIMethod: getCode
-     * Get the string SRS code.
-     *
-     * Returns:
-     * {String} The SRS code.
-     */
-    getCode: function() {
-        return this.proj ? this.proj.srsCode : this.projCode;
-    },
-   
-    /**
-     * APIMethod: getUnits
-     * Get the units string for the projection -- returns null if 
-     *     proj4js is not available.
-     *
-     * Returns:
-     * {String} The units abbreviation.
-     */
-    getUnits: function() {
-        return this.proj ? this.proj.units : null;
-    },
-
-    /**
-     * Method: toString
-     * Convert projection to string (getCode wrapper).
-     *
-     * Returns:
-     * {String} The projection code.
-     */
-    toString: function() {
-        return this.getCode();
-    },
-
-    /**
-     * Method: equals
-     * Test equality of two projection instances.  Determines equality based
-     *     solely on the projection code.
-     *
-     * Returns:
-     * {Boolean} The two projections are equivalent.
-     */
-    equals: function(projection) {
-        var p = projection, equals = false;
-        if (p) {
-            if (!(p instanceof OpenLayers.Projection)) {
-                p = new OpenLayers.Projection(p);
-            }
-            if ((typeof Proj4js == "object") && this.proj.defData && p.proj.defData) {
-                equals = this.proj.defData.replace(this.titleRegEx, "") ==
-                    p.proj.defData.replace(this.titleRegEx, "");
-            } else if (p.getCode) {
-                var source = this.getCode(), target = p.getCode();
-                equals = source == target ||
-                    !!OpenLayers.Projection.transforms[source] &&
-                    OpenLayers.Projection.transforms[source][target] ===
-                        OpenLayers.Projection.nullTransform;
-            }
-        }
-        return equals;   
-    },
-
-    /* Method: destroy
-     * Destroy projection object.
-     */
-    destroy: function() {
-        delete this.proj;
-        delete this.projCode;
-    },
-    
-    CLASS_NAME: "OpenLayers.Projection" 
-});     
-
-/**
- * Property: transforms
- * {Object} Transforms is an object, with from properties, each of which may
- * have a to property. This allows you to define projections without 
- * requiring support for proj4js to be included.
- *
- * This object has keys which correspond to a 'source' projection object.  The
- * keys should be strings, corresponding to the projection.getCode() value.
- * Each source projection object should have a set of destination projection
- * keys included in the object. 
- * 
- * Each value in the destination object should be a transformation function,
- * where the function is expected to be passed an object with a .x and a .y
- * property.  The function should return the object, with the .x and .y
- * transformed according to the transformation function.
- *
- * Note - Properties on this object should not be set directly.  To add a
- *     transform method to this object, use the <addTransform> method.  For an
- *     example of usage, see the OpenLayers.Layer.SphericalMercator file.
- */
-OpenLayers.Projection.transforms = {};
-
-/**
- * APIProperty: defaults
- * {Object} Defaults for the SRS codes known to OpenLayers (currently
- * EPSG:4326, CRS:84, urn:ogc:def:crs:EPSG:6.6:4326, EPSG:900913, EPSG:3857,
- * EPSG:102113, EPSG:102100 and OSGEO:41001). Keys are the SRS code, values are
- * units, maxExtent (the validity extent for the SRS in projected coordinates),
- * worldExtent (the world's extent in EPSG:4326) and yx (true if this SRS
- * is known to have a reverse axis order).
- */
-OpenLayers.Projection.defaults = {
-    "EPSG:4326": {
-        units: "degrees",
-        maxExtent: [-180, -90, 180, 90],
-        worldExtent: [-180, -90, 180, 90],
-        yx: true
-    },
-    "CRS:84": {
-        units: "degrees",
-        maxExtent: [-180, -90, 180, 90],
-        worldExtent: [-180, -90, 180, 90]
-    },
-    "EPSG:900913": {
-        units: "m",
-        maxExtent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34],
-        worldExtent: [-180, -89, 180, 89]
-    }
-};
-
-/**
- * APIMethod: addTransform
- * Set a custom transform method between two projections.  Use this method in
- *     cases where the proj4js lib is not available or where custom projections
- *     need to be handled.
- *
- * Parameters:
- * from - {String} The code for the source projection
- * to - {String} the code for the destination projection
- * method - {Function} A function that takes a point as an argument and
- *     transforms that point from the source to the destination projection
- *     in place.  The original point should be modified.
- */
-OpenLayers.Projection.addTransform = function(from, to, method) {
-    if (method === OpenLayers.Projection.nullTransform) {
-        var defaults = OpenLayers.Projection.defaults[from];
-        if (defaults && !OpenLayers.Projection.defaults[to]) {
-            OpenLayers.Projection.defaults[to] = defaults;
-        }
-    }
-    if(!OpenLayers.Projection.transforms[from]) {
-        OpenLayers.Projection.transforms[from] = {};
-    }
-    OpenLayers.Projection.transforms[from][to] = method;
-};
-
-/**
- * APIMethod: transform
- * Transform a point coordinate from one projection to another.  Note that
- *     the input point is transformed in place.
- * 
- * Parameters:
- * point - {<OpenLayers.Geometry.Point> | Object} An object with x and y
- *     properties representing coordinates in those dimensions.
- * source - {OpenLayers.Projection} Source map coordinate system
- * dest - {OpenLayers.Projection} Destination map coordinate system
- *
- * Returns:
- * point - {object} A transformed coordinate.  The original point is modified.
- */
-OpenLayers.Projection.transform = function(point, source, dest) {
-    if (source && dest) {
-        if (!(source instanceof OpenLayers.Projection)) {
-            source = new OpenLayers.Projection(source);
-        }
-        if (!(dest instanceof OpenLayers.Projection)) {
-            dest = new OpenLayers.Projection(dest);
-        }
-        if (source.proj && dest.proj) {
-            point = Proj4js.transform(source.proj, dest.proj, point);
-        } else {
-            var sourceCode = source.getCode();
-            var destCode = dest.getCode();
-            var transforms = OpenLayers.Projection.transforms;
-            if (transforms[sourceCode] && transforms[sourceCode][destCode]) {
-                transforms[sourceCode][destCode](point);
-            }
-        }
-    }
-    return point;
-};
-
-/**
- * APIFunction: nullTransform
- * A null transformation - useful for defining projection aliases when
- * proj4js is not available:
- *
- * (code)
- * OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:900913",
- *     OpenLayers.Projection.nullTransform);
- * OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:3857",
- *     OpenLayers.Projection.nullTransform);
- * (end)
- */
-OpenLayers.Projection.nullTransform = function(point) {
-    return point;
-};
-
-/**
- * Note: Transforms for web mercator <-> geographic
- * OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113, EPSG:102100 and 
- * OSGEO:41001. OpenLayers originally started referring to EPSG:900913 as web
- * mercator. The EPSG has declared EPSG:3857 to be web mercator.
- * ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as
- * equivalent.  See http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2009/11/20/ArcGIS-Online-moving-to-Google-_2F00_-Bing-tiling-scheme_3A00_-What-does-this-mean-for-you_3F00_.aspx#12084.
- * For geographic, OpenLayers recognizes EPSG:4326, CRS:84 and
- * urn:ogc:def:crs:EPSG:6.6:4326. OpenLayers also knows about the reverse axis
- * order for EPSG:4326. 
- */
-(function() {
-
-    var pole = 20037508.34;
-
-    function inverseMercator(xy) {
-        xy.x = 180 * xy.x / pole;
-        xy.y = 180 / Math.PI * (2 * Math.atan(Math.exp((xy.y / pole) * Math.PI)) - Math.PI / 2);
-        return xy;
-    }
-
-    function forwardMercator(xy) {
-        xy.x = xy.x * pole / 180;
-        var y = Math.log(Math.tan((90 + xy.y) * Math.PI / 360)) / Math.PI * pole;
-        xy.y = Math.max(-20037508.34, Math.min(y, 20037508.34));
-        return xy;
-    }
-
-    function map(base, codes) {
-        var add = OpenLayers.Projection.addTransform;
-        var same = OpenLayers.Projection.nullTransform;
-        var i, len, code, other, j;
-        for (i=0, len=codes.length; i<len; ++i) {
-            code = codes[i];
-            add(base, code, forwardMercator);
-            add(code, base, inverseMercator);
-            for (j=i+1; j<len; ++j) {
-                other = codes[j];
-                add(code, other, same);
-                add(other, code, same);
-            }
-        }
-    }
-    
-    // list of equivalent codes for web mercator
-    var mercator = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100", "OSGEO:41001"],
-        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.js
-   ====================================================================== */
-
-/* Copyright (c) 2006-2015 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the 2-clause BSD license.
- * See license.txt in the OpenLayers distribution or repository for the
- * full text of the license. */
-
-/**
- * @requires OpenLayers/BaseTypes/Class.js
- * @requires OpenLayers/Util.js
- * @requires OpenLayers/Util/vendorPrefix.js
- * @requires OpenLayers/Events.js
- * @requires OpenLayers/Tween.js
- * @requires OpenLayers/Projection.js
- */
-
-/**
- * Class: OpenLayers.Map
- * Instances of OpenLayers.Map are interactive maps embedded in a web page.
- * Create a new map with the <OpenLayers.Map> constructor.
- * 
- * On their own maps do not provide much functionality.  To extend a map
- * it's necessary to add controls (<OpenLayers.Control>) and 
- * layers (<OpenLayers.Layer>) to the map. 
- */
-OpenLayers.Map = OpenLayers.Class({
-    
-    /**
-     * Constant: Z_INDEX_BASE
-     * {Object} Base z-indexes for different classes of thing 
-     */
-    Z_INDEX_BASE: {
-        BaseLayer: 100,
-        Overlay: 325,
-        Feature: 725,
-        Popup: 750,
-        Control: 1000
-    },
-
-    /**
-     * APIProperty: events
-     * {<OpenLayers.Events>}
-     *
-     * Register a listener for a particular event with the following syntax:
-     * (code)
-     * map.events.register(type, obj, listener);
-     * (end)
-     *
-     * Listeners will be called with a reference to an event object.  The
-     *     properties of this event depends on exactly what happened.
-     *
-     * All event objects have at least the following properties:
-     * object - {Object} A reference to map.events.object.
-     * element - {DOMElement} A reference to map.events.element.
-     *
-     * Browser events have the following additional properties:
-     * xy - {<OpenLayers.Pixel>} The pixel location of the event (relative
-     *     to the the map viewport).
-     *
-     * Supported map event types:
-     * preaddlayer - triggered before a layer has been added.  The event
-     *     object will include a *layer* property that references the layer  
-     *     to be added. When a listener returns "false" the adding will be 
-     *     aborted.
-     * addlayer - triggered after a layer has been added.  The event object
-     *     will include a *layer* property that references the added layer.
-     * preremovelayer - triggered before a layer has been removed. The event
-     *     object will include a *layer* property that references the layer  
-     *     to be removed. When a listener returns "false" the removal will be 
-     *     aborted.
-     * removelayer - triggered after a layer has been removed.  The event
-     *     object will include a *layer* property that references the removed
-     *     layer.
-     * changelayer - triggered after a layer name change, order change,
-     *     opacity change, params change, visibility change (actual visibility,
-     *     not the layer's visibility property) or attribution change (due to
-     *     extent change). Listeners will receive an event object with *layer*
-     *     and *property* properties. The *layer* property will be a reference
-     *     to the changed layer. The *property* property will be a key to the
-     *     changed property (name, order, opacity, params, visibility or
-     *     attribution).
-     * movestart - triggered after the start of a drag, pan, or zoom. The event
-     *     object may include a *zoomChanged* property that tells whether the
-     *     zoom has changed.
-     * move - triggered after each drag, pan, or zoom
-     * moveend - triggered after a drag, pan, or zoom completes
-     * zoomstart - triggered when a zoom starts. Listeners receive an object
-     *     with *center* and *zoom* properties, for the target center and zoom
-     *     level.
-     * zoomend - triggered after a zoom completes
-     * mouseover - triggered after mouseover the map
-     * mouseout - triggered after mouseout the map
-     * mousemove - triggered after mousemove the map
-     * changebaselayer - triggered after the base layer changes
-     * updatesize - triggered after the <updateSize> method was executed
-     */
-
-    /**
-     * Property: id
-     * {String} Unique identifier for the map
-     */
-    id: null,
-    
-    /**
-     * Property: fractionalZoom
-     * {Boolean} For a base layer that supports it, allow the map resolution
-     *     to be set to a value between one of the values in the resolutions
-     *     array.  Default is false.
-     *
-     * When fractionalZoom is set to true, it is possible to zoom to
-     *     an arbitrary extent.  This requires a base layer from a source
-     *     that supports requests for arbitrary extents (i.e. not cached
-     *     tiles on a regular lattice).  This means that fractionalZoom
-     *     will not work with commercial layers (Google, Yahoo, VE), layers
-     *     using TileCache, or any other pre-cached data sources.
-     *
-     * If you are using fractionalZoom, then you should also use
-     *     <getResolutionForZoom> instead of layer.resolutions[zoom] as the
-     *     former works for non-integer zoom levels.
-     */
-    fractionalZoom: false,
-    
-    /**
-     * APIProperty: events
-     * {<OpenLayers.Events>} An events object that handles all 
-     *                       events on the map
-     */
-    events: null,
-    
-    /**
-     * APIProperty: allOverlays
-     * {Boolean} Allow the map to function with "overlays" only.  Defaults to
-     *     false.  If true, the lowest layer in the draw order will act as
-     *     the base layer.  In addition, if set to true, all layers will
-     *     have isBaseLayer set to false when they are added to the map.
-     *
-     * Note:
-     * If you set map.allOverlays to true, then you *cannot* use
-     *     map.setBaseLayer or layer.setIsBaseLayer.  With allOverlays true,
-     *     the lowest layer in the draw layer is the base layer.  So, to change
-     *     the base layer, use <setLayerIndex> or <raiseLayer> to set the layer
-     *     index to 0.
-     */
-    allOverlays: false,
-
-    /**
-     * APIProperty: div
-     * {DOMElement|String} The element that contains the map (or an id for
-     *     that element).  If the <OpenLayers.Map> constructor is called
-     *     with two arguments, this should be provided as the first argument.
-     *     Alternatively, the map constructor can be called with the options
-     *     object as the only argument.  In this case (one argument), a
-     *     div property may or may not be provided.  If the div property
-     *     is not provided, the map can be rendered to a container later
-     *     using the <render> method.
-     *     
-     * Note:
-     * If you are calling <render> after map construction, do not use
-     *     <maxResolution>  auto.  Instead, divide your <maxExtent> by your
-     *     maximum expected dimension.
-     */
-    div: null,
-    
-    /**
-     * Property: dragging
-     * {Boolean} The map is currently being dragged.
-     */
-    dragging: false,
-
-    /**
-     * Property: size
-     * {<OpenLayers.Size>} Size of the main div (this.div)
-     */
-    size: null,
-    
-    /**
-     * Property: viewPortDiv
-     * {HTMLDivElement} The element that represents the map viewport
-     */
-    viewPortDiv: null,
-
-    /**
-     * Property: layerContainerOrigin
-     * {<OpenLayers.LonLat>} The lonlat at which the later container was
-     *                       re-initialized (on-zoom)
-     */
-    layerContainerOrigin: null,
-
-    /**
-     * Property: layerContainerDiv
-     * {HTMLDivElement} The element that contains the layers.
-     */
-    layerContainerDiv: null,
-
-    /**
-     * APIProperty: layers
-     * {Array(<OpenLayers.Layer>)} Ordered list of layers in the map
-     */
-    layers: null,
-
-    /**
-     * APIProperty: controls
-     * {Array(<OpenLayers.Control>)} List of controls associated with the map.
-     *
-     * If not provided in the map options at construction, the map will
-     *     by default be given the following controls if present in the build:
-     *  - <OpenLayers.Control.Navigation> or <OpenLayers.Control.TouchNavigation>
-     *  - <OpenLayers.Control.Zoom> or <OpenLayers.Control.PanZoom>
-     *  - <OpenLayers.Control.ArgParser>
-     *  - <OpenLayers.Control.Attribution>
-     */
-    controls: null,
-
-    /**
-     * Property: popups
-     * {Array(<OpenLayers.Popup>)} List of popups associated with the map
-     */
-    popups: null,
-
-    /**
-     * APIProperty: baseLayer
-     * {<OpenLayers.Layer>} The currently selected base layer.  This determines
-     * min/max zoom level, projection, etc.
-     */
-    baseLayer: null,
-    
-    /**
-     * Property: center
-     * {<OpenLayers.LonLat>} The current center of the map
-     */
-    center: null,
-
-    /**
-     * Property: resolution
-     * {Float} The resolution of the map.
-     */
-    resolution: null,
-
-    /**
-     * Property: zoom
-     * {Integer} The current zoom level of the map
-     */
-    zoom: 0,    
-
-    /**
-     * Property: panRatio
-     * {Float} The ratio of the current extent within
-     *         which panning will tween.
-     */
-    panRatio: 1.5,    
-
-    /**
-     * APIProperty: options
-     * {Object} The options object passed to the class constructor. Read-only.
-     */
-    options: null,
-
-  // Options
-
-    /**
-     * APIProperty: tileSize
-     * {<OpenLayers.Size>} Set in the map options to override the default tile
-     *                     size for this map.
-     */
-    tileSize: null,
-
-    /**
-     * APIProperty: projection
-     * {String} Set in the map options to specify the default projection 
-     *          for layers added to this map. When using a projection other than EPSG:4326
-     *          (CRS:84, Geographic) or EPSG:3857 (EPSG:900913, Web Mercator),
-     *          also set maxExtent, maxResolution or resolutions.  Default is "EPSG:4326".
-     *          Note that the projection of the map is usually determined
-     *          by that of the current baseLayer (see <baseLayer> and <getProjectionObject>).
-     */
-    projection: "EPSG:4326",    
-        
-    /**
-     * APIProperty: units
-     * {String} The map units.  Possible values are 'degrees' (or 'dd'), 'm', 
-     *     'ft', 'km', 'mi', 'inches'.  Normally taken from the projection.
-     *     Only required if both map and layers do not define a projection,
-     *     or if they define a projection which does not define units
-     */
-    units: null,
-
-    /**
-     * APIProperty: resolutions
-     * {Array(Float)} A list of map resolutions (map units per pixel) in 
-     *     descending order.  If this is not set in the layer constructor, it 
-     *     will be set based on other resolution related properties 
-     *     (maxExtent, maxResolution, maxScale, etc.).
-     */
-    resolutions: null,
-
-    /**
-     * APIProperty: maxResolution
-     * {Float} Required if you are not displaying the whole world on a tile
-     * with the size specified in <tileSize>.
-     */
-    maxResolution: null,
-
-    /**
-     * APIProperty: minResolution
-     * {Float}
-     */
-    minResolution: null,
-
-    /**
-     * APIProperty: maxScale
-     * {Float}
-     */
-    maxScale: null,
-
-    /**
-     * APIProperty: minScale
-     * {Float}
-     */
-    minScale: null,
-
-    /**
-     * APIProperty: maxExtent
-     * {<OpenLayers.Bounds>|Array} If provided as an array, the array
-     *     should consist of four values (left, bottom, right, top).
-     *     The maximum extent for the map.
-     *     Default depends on projection; if this is one of those defined in OpenLayers.Projection.defaults
-     *     (EPSG:4326 or web mercator), maxExtent will be set to the value defined there;
-     *     else, defaults to null.
-     *     To restrict user panning and zooming of the map, use <restrictedExtent> instead.
-     *     The value for <maxExtent> will change calculations for tile URLs.
-     */
-    maxExtent: null,
-    
-    /**
-     * APIProperty: minExtent
-     * {<OpenLayers.Bounds>|Array} If provided as an array, the array
-     *     should consist of four values (left, bottom, right, top).
-     *     The minimum extent for the map.  Defaults to null.
-     */
-    minExtent: null,
-    
-    /**
-     * APIProperty: restrictedExtent
-     * {<OpenLayers.Bounds>|Array} If provided as an array, the array
-     *     should consist of four values (left, bottom, right, top).
-     *     Limit map navigation to this extent where possible.
-     *     If a non-null restrictedExtent is set, panning will be restricted
-     *     to the given bounds.  In addition, zooming to a resolution that
-     *     displays more than the restricted extent will center the map
-     *     on the restricted extent.  If you wish to limit the zoom level
-     *     or resolution, use maxResolution.
-     */
-    restrictedExtent: null,
-
-    /**
-     * APIProperty: numZoomLevels
-     * {Integer} Number of zoom levels for the map.  Defaults to 16.  Set a
-     *           different value in the map options if needed.
-     */
-    numZoomLevels: 16,
-
-    /**
-     * APIProperty: theme
-     * {String} Relative path to a CSS file from which to load theme styles.
-     *          Specify null in the map options (e.g. {theme: null}) if you 
-     *          want to get cascading style declarations - by putting links to 
-     *          stylesheets or style declarations directly in your page.
-     */
-    theme: null,
-    
-    /** 
-     * APIProperty: displayProjection
-     * {<OpenLayers.Projection>} Requires proj4js support for projections other
-     *     than EPSG:4326 or EPSG:900913/EPSG:3857. Projection used by
-     *     several controls to display data to user. If this property is set,
-     *     it will be set on any control which has a null displayProjection
-     *     property at the time the control is added to the map. 
-     */
-    displayProjection: null,
-
-    /**
-     * APIProperty: tileManager
-     * {<OpenLayers.TileManager>|Object} By default, and if the build contains
-     * TileManager.js, the map will use the TileManager to queue image requests
-     * and to cache tile image elements. To create a map without a TileManager
-     * configure the map with tileManager: null. To create a TileManager with
-     * non-default options, supply the options instead or alternatively supply
-     * an instance of {<OpenLayers.TileManager>}.
-     */
-
-    /**
-     * APIProperty: fallThrough
-     * {Boolean} Should OpenLayers allow events on the map to fall through to
-     *           other elements on the page, or should it swallow them? (#457)
-     *           Default is to swallow.
-     */
-    fallThrough: false,
-
-    /**
-     * APIProperty: autoUpdateSize
-     * {Boolean} Should OpenLayers automatically update the size of the map
-     * when the resize event is fired. Default is true.
-     */
-    autoUpdateSize: true,
-    
-    /**
-     * APIProperty: eventListeners
-     * {Object} If set as an option at construction, the eventListeners
-     *     object will be registered with <OpenLayers.Events.on>.  Object
-     *     structure must be a listeners object as shown in the example for
-     *     the events.on method.
-     */
-    eventListeners: null,
-
-    /**
-     * Property: panTween
-     * {<OpenLayers.Tween>} Animated panning tween object, see panTo()
-     */
-    panTween: null,
-
-    /**
-     * APIProperty: panMethod
-     * {Function} The Easing function to be used for tweening.  Default is
-     * OpenLayers.Easing.Expo.easeOut. Setting this to 'null' turns off
-     * animated panning.
-     */
-    panMethod: OpenLayers.Easing.Expo.easeOut,
-    
-    /**
-     * Property: panDuration
-     * {Integer} The number of steps to be passed to the
-     * OpenLayers.Tween.start() method when the map is
-     * panned.
-     * Default is 50.
-     */
-    panDuration: 50,
-    
-    /**
-     * Property: zoomTween
-     * {<OpenLayers.Tween>} Animated zooming tween object, see zoomTo()
-     */
-    zoomTween: null,
-
-    /**
-     * APIProperty: zoomMethod
-     * {Function} The Easing function to be used for tweening.  Default is
-     * OpenLayers.Easing.Quad.easeOut. Setting this to 'null' turns off
-     * animated zooming.
-     */
-    zoomMethod: OpenLayers.Easing.Quad.easeOut,
-    
-    /**
-     * Property: zoomDuration
-     * {Integer} The number of steps to be passed to the
-     * OpenLayers.Tween.start() method when the map is zoomed.
-     * Default is 20.
-     */
-    zoomDuration: 20,
-    
-    /**
-     * Property: paddingForPopups
-     * {<OpenLayers.Bounds>} Outside margin of the popup. Used to prevent 
-     *     the popup from getting too close to the map border.
-     */
-    paddingForPopups : null,
-    
-    /**
-     * Property: layerContainerOriginPx
-     * {Object} Cached object representing the layer container origin (in pixels).
-     */
-    layerContainerOriginPx: null,
-    
-    /**
-     * Property: minPx
-     * {Object} An object with a 'x' and 'y' values that is the lower
-     *     left of maxExtent in viewport pixel space.
-     *     Used to verify in moveByPx that the new location we're moving to
-     *     is valid. It is also used in the getLonLatFromViewPortPx function
-     *     of Layer.
-     */
-    minPx: null,
-    
-    /**
-     * Property: maxPx
-     * {Object} An object with a 'x' and 'y' values that is the top
-     *     right of maxExtent in viewport pixel space.
-     *     Used to verify in moveByPx that the new location we're moving to
-     *     is valid.
-     */
-    maxPx: null,
-    
-    /**
-     * Constructor: OpenLayers.Map
-     * Constructor for a new OpenLayers.Map instance.  There are two possible
-     *     ways to call the map constructor.  See the examples below.
-     *
-     * Parameters:
-     * div - {DOMElement|String}  The element or id of an element in your page
-     *     that will contain the map.  May be omitted if the <div> option is
-     *     provided or if you intend to call the <render> method later.
-     * options - {Object} Optional object with properties to tag onto the map.
-     *
-     * Valid options (in addition to the listed API properties):
-     * center - {<OpenLayers.LonLat>|Array} The default initial center of the map.
-     *     If provided as array, the first value is the x coordinate,
-     *     and the 2nd value is the y coordinate.
-     *     Only specify if <layers> is provided.
-     *     Note that if an ArgParser/Permalink control is present,
-     *     and the querystring contains coordinates, center will be set
-     *     by that, and this option will be ignored.
-     * zoom - {Number} The initial zoom level for the map. Only specify if
-     *     <layers> is provided.
-     *     Note that if an ArgParser/Permalink control is present,
-     *     and the querystring contains a zoom level, zoom will be set
-     *     by that, and this option will be ignored.
-     * 
-     * Examples:
-     * (code)
-     * // create a map with default options in an element with the id "map1"
-     * var map = new OpenLayers.Map("map1");
-     *
-     * // create a map with non-default options in an element with id "map2"
-     * var options = {
-     *     projection: "EPSG:3857",
-     *     maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000),
-     *     center: new OpenLayers.LonLat(-12356463.476333, 5621521.4854095)
-     * };
-     * var map = new OpenLayers.Map("map2", options);
-     *
-     * // map with non-default options - same as above but with a single argument,
-     * // a restricted extent, and using arrays for bounds and center
-     * var map = new OpenLayers.Map({
-     *     div: "map_id",
-     *     projection: "EPSG:3857",
-     *     maxExtent: [-18924313.432222, -15538711.094146, 18924313.432222, 15538711.094146],
-     *     restrictedExtent: [-13358338.893333, -9608371.5085962, 13358338.893333, 9608371.5085962],
-     *     center: [-12356463.476333, 5621521.4854095]
-     * });
-     *
-     * // create a map without a reference to a container - call render later
-     * var map = new OpenLayers.Map({
-     *     projection: "EPSG:3857",
-     *     maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000)
-     * });
-     * (end)
-     */    
-    initialize: function (div, options) {
-        
-        // If only one argument is provided, check if it is an object.
-        var isDOMElement = OpenLayers.Util.isElement(div);
-        if(arguments.length === 1 && typeof div === "object" && !isDOMElement) {
-            options = div;
-            div = options && options.div;
-        }
-
-        // Simple-type defaults are set in class definition. 
-        //  Now set complex-type defaults 
-        this.tileSize = new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH,
-                                            OpenLayers.Map.TILE_HEIGHT);
-        
-        this.paddingForPopups = new OpenLayers.Bounds(15, 15, 15, 15);
-
-        this.theme = OpenLayers._getScriptLocation() + 
-                             'theme/default/style.css'; 
-
-        // backup original options
-        this.options = OpenLayers.Util.extend({}, options);
-
-        // now override default options 
-        OpenLayers.Util.extend(this, options);
-        
-        var projCode = this.projection instanceof OpenLayers.Projection ?
-            this.projection.projCode : this.projection;
-        OpenLayers.Util.applyDefaults(this, OpenLayers.Projection.defaults[projCode]);
-        
-        // allow extents and center to be arrays
-        if (this.maxExtent && !(this.maxExtent instanceof OpenLayers.Bounds)) {
-            this.maxExtent = new OpenLayers.Bounds(this.maxExtent);
-        }
-        if (this.minExtent && !(this.minExtent instanceof OpenLayers.Bounds)) {
-            this.minExtent = new OpenLayers.Bounds(this.minExtent);
-        }
-        if (this.restrictedExtent && !(this.restrictedExtent instanceof OpenLayers.Bounds)) {
-            this.restrictedExtent = new OpenLayers.Bounds(this.restrictedExtent);
-        }
-        if (this.center && !(this.center instanceof OpenLayers.LonLat)) {
-            this.center = new OpenLayers.LonLat(this.center);
-        }
-
-        // initialize layers array
-        this.layers = [];
-
-        this.id = OpenLayers.Util.createUniqueID("OpenLayers.Map_");
-
-        this.div = OpenLayers.Util.getElement(div);
-        if(!this.div) {
-            this.div = document.createElement("div");
-            this.div.style.height = "1px";
-            this.div.style.width = "1px";
-        }
-        
-        OpenLayers.Element.addClass(this.div, 'olMap');
-
-        // the viewPortDiv is the outermost div we modify
-        var id = this.id + "_OpenLayers_ViewPort";
-        this.viewPortDiv = OpenLayers.Util.createDiv(id, null, null, null,
-                                                     "relative", null,
-                                                     "hidden");
-        this.viewPortDiv.style.width = "100%";
-        this.viewPortDiv.style.height = "100%";
-        this.viewPortDiv.className = "olMapViewport";
-        this.div.appendChild(this.viewPortDiv);
-
-        this.events = new OpenLayers.Events(
-            this, this.viewPortDiv, null, this.fallThrough, 
-            {includeXY: true}
-        );
-        
-        if (OpenLayers.TileManager && this.tileManager !== null) {
-            if (!(this.tileManager instanceof OpenLayers.TileManager)) {
-                this.tileManager = new OpenLayers.TileManager(this.tileManager);
-            }
-            this.tileManager.addMap(this);
-        }
-
-        // the layerContainerDiv is the one that holds all the layers
-        id = this.id + "_OpenLayers_Container";
-        this.layerContainerDiv = OpenLayers.Util.createDiv(id);
-        this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;
-        this.layerContainerOriginPx = {x: 0, y: 0};
-        this.applyTransform();
-        
-        this.viewPortDiv.appendChild(this.layerContainerDiv);
-
-        this.updateSize();
-        if(this.eventListeners instanceof Object) {
-            this.events.on(this.eventListeners);
-        }
-
-        if (this.autoUpdateSize === true) {
-            // updateSize on catching the window's resize
-            // Note that this is ok, as updateSize() does nothing if the 
-            // map's size has not actually changed.
-            this.updateSizeDestroy = OpenLayers.Function.bind(this.updateSize, 
-                this);
-            OpenLayers.Event.observe(window, 'resize',
-                            this.updateSizeDestroy);
-        }
-        
-        // only append link stylesheet if the theme property is set
-        if(this.theme) {
-            // check existing links for equivalent url
-            var addNode = true;
-            var nodes = document.getElementsByTagName('link');
-            for(var i=0, len=nodes.length; i<len; ++i) {
-                if(OpenLayers.Util.isEquivalentUrl(nodes.item(i).href,
-                                                   this.theme)) {
-                    addNode = false;
-                    break;
-                }
-            }
-            // only add a new node if one with an equivalent url hasn't already
-            // been added
-            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) { // default controls
-            this.controls = [];
-            if (OpenLayers.Control != null) { // running full or lite?
-                // Navigation or TouchNavigation depending on what is in build
-                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);
-        
-
-        // always call map.destroy()
-        OpenLayers.Event.observe(window, 'unload', this.unloadDestroy);
-        
-        // add any initial layers
-        if (options && options.layers) {
-            /** 
-             * If you have set options.center, the map center property will be
-             * set at this point.  However, since setCenter has not been called,
-             * addLayers gets confused.  So we delete the map center in this 
-             * case.  Because the check below uses options.center, it will
-             * be properly set below.
-             */
-            delete this.center;
-            delete this.zoom;
-            this.addLayers(options.layers);
-            // set center (and optionally zoom)
-            if (options.center && !this.getCenter()) {
-                // zoom can be undefined here
-                this.setCenter(options.center, options.zoom);
-            }
-        }
-
-        if (this.panMethod) {
-            this.panTween = new OpenLayers.Tween(this.panMethod);
-        }
-        if (this.zoomMethod && this.applyTransform.transform) {
-            this.zoomTween = new OpenLayers.Tween(this.zoomMethod);
-        }
-    },
-
-    /** 
-     * APIMethod: getViewport
-     * Get the DOMElement representing the view port.
-     *
-     * Returns:
-     * {DOMElement}
-     */
-    getViewport: function() {
-        return this.viewPortDiv;
-    },
-    
-    /**
-     * APIMethod: render
-     * Render the map to a specified container.
-     * 
-     * Parameters:
-     * div - {String|DOMElement} The container that the map should be rendered
-     *     to. If different than the current container, the map viewport
-     *     will be moved from the current to the new container.
-     */
-    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();
-    },
-
-    /**
-     * Method: unloadDestroy
-     * Function that is called to destroy the map on page unload. stored here
-     *     so that if map is manually destroyed, we can unregister this.
-     */
-    unloadDestroy: null,
-    
-    /**
-     * Method: updateSizeDestroy
-     * When the map is destroyed, we need to stop listening to updateSize
-     *    events: this method stores the function we need to unregister in 
-     *    non-IE browsers.
-     */
-    updateSizeDestroy: null,
-
-    /**
-     * APIMethod: destroy
-     * Destroy this map.
-     *    Note that if you are using an application which removes a container
-     *    of the map from the DOM, you need to ensure that you destroy the
-     *    map *before* this happens; otherwise, the page unload handler
-     *    will fail because the DOM elements that map.destroy() wants
-     *    to clean up will be gone. (See 
-     *    http://trac.osgeo.org/openlayers/ticket/2277 for more information).
-     *    This will apply to GeoExt and also to other applications which
-     *    modify the DOM of the container of the OpenLayers Map.
-     */
-    destroy:function() {
-        // if unloadDestroy is null, we've already been destroyed
-        if (!this.unloadDestroy) {
-            return false;
-        }
-        
-        // make sure panning doesn't continue after destruction
-        if(this.panTween) {
-            this.panTween.stop();
-            this.panTween = null;
-        }
-        // make sure zooming doesn't continue after destruction
-        if(this.zoomTween) {
-            this.zoomTween.stop();
-            this.zoomTween = null;
-        }
-
-        // map has been destroyed. dont do it again!
-        OpenLayers.Event.stopObserving(window, 'unload', this.unloadDestroy);
-        this.unloadDestroy = null;
-
-        if (this.updateSizeDestroy) {
-            OpenLayers.Event.stopObserving(window, 'resize', 
-                                           this.updateSizeDestroy);
-        }
-        
-        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) {
-                //pass 'false' to destroy so that map wont try to set a new 
-                // baselayer after each baselayer is removed
-                this.layers[i].destroy(false);
-            } 
-            this.layers = null;
-        }
-        if (this.viewPortDiv && this.viewPortDiv.parentNode) {
-            this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);
-        }
-        this.viewPortDiv = null;
-        
-        if (this.tileManager) {
-            this.tileManager.removeMap(this);
-            this.tileManager = null;
-        }
-
-        if(this.eventListeners) {
-            this.events.un(this.eventListeners);
-            this.eventListeners = null;
-        }
-        this.events.destroy();
-        this.events = null;
-
-        this.options = null;
-    },
-
-    /**
-     * APIMethod: setOptions
-     * Change the map options
-     *
-     * Parameters:
-     * options - {Object} Hashtable of options to tag to the map
-     */
-    setOptions: function(options) {
-        var updatePxExtent = this.minPx &&
-            options.restrictedExtent != this.restrictedExtent;
-        OpenLayers.Util.extend(this, options);
-        // force recalculation of minPx and maxPx
-        updatePxExtent && this.moveTo(this.getCachedCenter(), this.zoom, {
-            forceZoomChange: true
-        });
-    },
-
-    /**
-     * APIMethod: getTileSize
-     * Get the tile size for the map
-     *
-     * Returns:
-     * {<OpenLayers.Size>}
-     */
-     getTileSize: function() {
-         return this.tileSize;
-     },
-
-
-    /**
-     * APIMethod: getBy
-     * Get a list of objects given a property and a match item.
-     *
-     * Parameters:
-     * array - {String} A property on the map whose value is an array.
-     * property - {String} A property on each item of the given array.
-     * match - {String | Object} A string to match.  Can also be a regular
-     *     expression literal or object.  In addition, it can be any object
-     *     with a method named test.  For reqular expressions or other, if
-     *     match.test(map[array][i][property]) evaluates to true, the item will
-     *     be included in the array returned.  If no items are found, an empty
-     *     array is returned.
-     *
-     * Returns:
-     * {Array} An array of items where the given property matches the given
-     *     criteria.
-     */
-    getBy: function(array, property, match) {
-        var test = (typeof match.test == "function");
-        var found = OpenLayers.Array.filter(this[array], function(item) {
-            return item[property] == match || (test && match.test(item[property]));
-        });
-        return found;
-    },
-
-    /**
-     * APIMethod: getLayersBy
-     * Get a list of layers with properties matching the given criteria.
-     *
-     * Parameters:
-     * property - {String} A layer property to be matched.
-     * match - {String | Object} A string to match.  Can also be a regular
-     *     expression literal or object.  In addition, it can be any object
-     *     with a method named test.  For reqular expressions or other, if
-     *     match.test(layer[property]) evaluates to true, the layer will be
-     *     included in the array returned.  If no layers are found, an empty
-     *     array is returned.
-     *
-     * Returns:
-     * {Array(<OpenLayers.Layer>)} A list of layers matching the given criteria.
-     *     An empty array is returned if no matches are found.
-     */
-    getLayersBy: function(property, match) {
-        return this.getBy("layers", property, match);
-    },
-
-    /**
-     * APIMethod: getLayersByName
-     * Get a list of layers with names matching the given name.
-     *
-     * Parameters:
-     * match - {String | Object} A layer name.  The name can also be a regular
-     *     expression literal or object.  In addition, it can be any object
-     *     with a method named test.  For reqular expressions or other, if
-     *     name.test(layer.name) evaluates to true, the layer will be included
-     *     in the list of layers returned.  If no layers are found, an empty
-     *     array is returned.
-     *
-     * Returns:
-     * {Array(<OpenLayers.Layer>)} A list of layers matching the given name.
-     *     An empty array is returned if no matches are found.
-     */
-    getLayersByName: function(match) {
-        return this.getLayersBy("name", match);
-    },
-
-    /**
-     * APIMethod: getLayersByClass
-     * Get a list of layers of a given class (CLASS_NAME).
-     *
-     * Parameters:
-     * match - {String | Object} A layer class name.  The match can also be a
-     *     regular expression literal or object.  In addition, it can be any
-     *     object with a method named test.  For reqular expressions or other,
-     *     if type.test(layer.CLASS_NAME) evaluates to true, the layer will
-     *     be included in the list of layers returned.  If no layers are
-     *     found, an empty array is returned.
-     *
-     * Returns:
-     * {Array(<OpenLayers.Layer>)} A list of layers matching the given class.
-     *     An empty array is returned if no matches are found.
-     */
-    getLayersByClass: function(match) {
-        return this.getLayersBy("CLASS_NAME", match);
-    },
-
-    /**
-     * APIMethod: getControlsBy
-     * Get a list of controls with properties matching the given criteria.
-     *
-     * Parameters:
-     * property - {String} A control property to be matched.
-     * match - {String | Object} A string to match.  Can also be a regular
-     *     expression literal or object.  In addition, it can be any object
-     *     with a method named test.  For reqular expressions or other, if
-     *     match.test(layer[property]) evaluates to true, the layer will be
-     *     included in the array returned.  If no layers are found, an empty
-     *     array is returned.
-     *
-     * Returns:
-     * {Array(<OpenLayers.Control>)} A list of controls matching the given
-     *     criteria.  An empty array is returned if no matches are found.
-     */
-    getControlsBy: function(property, match) {
-        return this.getBy("controls", property, match);
-    },
-
-    /**
-     * APIMethod: getControlsByClass
-     * Get a list of controls of a given class (CLASS_NAME).
-     *
-     * Parameters:
-     * match - {String | Object} A control class name.  The match can also be a
-     *     regular expression literal or object.  In addition, it can be any
-     *     object with a method named test.  For reqular expressions or other,
-     *     if type.test(control.CLASS_NAME) evaluates to true, the control will
-     *     be included in the list of controls returned.  If no controls are
-     *     found, an empty array is returned.
-     *
-     * Returns:
-     * {Array(<OpenLayers.Control>)} A list of controls matching the given class.
-     *     An empty array is returned if no matches are found.
-     */
-    getControlsByClass: function(match) {
-        return this.getControlsBy("CLASS_NAME", match);
-    },
-
-  /********************************************************/
-  /*                                                      */
-  /*                  Layer Functions                     */
-  /*                                                      */
-  /*     The following functions deal with adding and     */
-  /*        removing Layers to and from the Map           */
-  /*                                                      */
-  /********************************************************/         
-
-    /**
-     * APIMethod: getLayer
-     * Get a layer based on its id
-     *
-     * Parameters:
-     * id - {String} A layer id
-     *
-     * Returns:
-     * {<OpenLayers.Layer>} The Layer with the corresponding id from the map's 
-     *                      layer collection, or null if not found.
-     */
-    getLayer: function(id) {
-        var foundLayer = null;
-        for (var i=0, len=this.layers.length; i<len; i++) {
-            var layer = this.layers[i];
-            if (layer.id == id) {
-                foundLayer = layer;
-                break;
-            }
-        }
-        return foundLayer;
-    },
-
-    /**
-    * Method: setLayerZIndex
-    * 
-    * Parameters:
-    * layer - {<OpenLayers.Layer>} 
-    * zIdx - {int} 
-    */    
-    setLayerZIndex: function (layer, zIdx) {
-        layer.setZIndex(
-            this.Z_INDEX_BASE[layer.isBaseLayer ? 'BaseLayer' : 'Overlay']
-            + zIdx * 5 );
-    },
-
-    /**
-     * Method: resetLayersZIndex
-     * Reset each layer's z-index based on layer's array index
-     */
-    resetLayersZIndex: function() {
-        for (var i=0, len=this.layers.length; i<len; i++) {
-            var layer = this.layers[i];
-            this.setLayerZIndex(layer, i);
-        }
-    },
-
-    /**
-    * APIMethod: addLayer
-    *
-    * Parameters:
-    * layer - {<OpenLayers.Layer>} 
-    *
-    * Returns:
-    * {Boolean} True if the layer has been added to the map.
-    */    
-    addLayer: function (layer) {
-        for(var i = 0, len = this.layers.length; i < len; i++) {
-            if (this.layers[i] == layer) {
-                return false;
-            }
-        }
-        if (this.events.triggerEvent("preaddlayer", {layer: layer}) === false) {
-            return false;
-        }
-        if(this.allOverlays) {
-            layer.isBaseLayer = false;
-        }
-        
-        layer.div.className = "olLayerDiv";
-        layer.div.style.overflow = "";
-        this.setLayerZIndex(layer, this.layers.length);
-
-        if (layer.isFixed) {
-            this.viewPortDiv.appendChild(layer.div);
-        } else {
-            this.layerContainerDiv.appendChild(layer.div);
-        }
-        this.layers.push(layer);
-        layer.setMap(this);
-
-        if (layer.isBaseLayer || (this.allOverlays && !this.baseLayer))  {
-            if (this.baseLayer == null) {
-                // set the first baselaye we add as the baselayer
-                this.setBaseLayer(layer);
-            } else {
-                layer.setVisibility(false);
-            }
-        } else {
-            layer.redraw();
-        }
-
-        this.events.triggerEvent("addlayer", {layer: layer});
-        layer.events.triggerEvent("added", {map: this, layer: layer});
-        layer.afterAdd();
-
-        return true;
-    },
-
-    /**
-    * APIMethod: addLayers 
-    *
-    * Parameters:
-    * layers - {Array(<OpenLayers.Layer>)} 
-    */    
-    addLayers: function (layers) {
-        for (var i=0, len=layers.length; i<len; i++) {
-            this.addLayer(layers[i]);
-        }
-    },
-
-    /** 
-     * APIMethod: removeLayer
-     * Removes a layer from the map by removing its visual element (the 
-     *   layer.div property), then removing it from the map's internal list 
-     *   of layers, setting the layer's map property to null. 
-     * 
-     *   a "removelayer" event is triggered.
-     * 
-     *   very worthy of mention is that simply removing a layer from a map
-     *   will not cause the removal of any popups which may have been created
-     *   by the layer. this is due to the fact that it was decided at some
-     *   point that popups would not belong to layers. thus there is no way 
-     *   for us to know here to which layer the popup belongs.
-     *    
-     *     A simple solution to this is simply to call destroy() on the layer.
-     *     the default OpenLayers.Layer class's destroy() function
-     *     automatically takes care to remove itself from whatever map it has
-     *     been attached to. 
-     * 
-     *     The correct solution is for the layer itself to register an 
-     *     event-handler on "removelayer" and when it is called, if it 
-     *     recognizes itself as the layer being removed, then it cycles through
-     *     its own personal list of popups, removing them from the map.
-     * 
-     * Parameters:
-     * layer - {<OpenLayers.Layer>} 
-     * setNewBaseLayer - {Boolean} Default is true
-     */
-    removeLayer: function(layer, setNewBaseLayer) {
-        if (this.events.triggerEvent("preremovelayer", {layer: layer}) === false) {
-            return;
-        }
-        if (setNewBaseLayer == null) {
-            setNewBaseLayer = true;
-        }
-
-        if (layer.isFixed) {
-            this.viewPortDiv.removeChild(layer.div);
-        } else {
-            this.layerContainerDiv.removeChild(layer.div);
-        }
-        OpenLayers.Util.removeItem(this.layers, layer);
-        layer.removeMap(this);
-        layer.map = null;
-
-        // if we removed the base layer, need to set a new one
-        if(this.baseLayer == layer) {
-            this.baseLayer = null;
-            if(setNewBaseLayer) {
-                for(var i=0, len=this.layers.length; i<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});
-    },
-
-    /**
-     * APIMethod: getNumLayers
-     * 
-     * Returns:
-     * {Int} The number of layers attached to the map.
-     */
-    getNumLayers: function () {
-        return this.layers.length;
-    },
-
-    /** 
-     * APIMethod: getLayerIndex
-     *
-     * Parameters:
-     * layer - {<OpenLayers.Layer>}
-     *
-     * Returns:
-     * {Integer} The current (zero-based) index of the given layer in the map's
-     *           layer stack. Returns -1 if the layer isn't on the map.
-     */
-    getLayerIndex: function (layer) {
-        return OpenLayers.Util.indexOf(this.layers, layer);
-    },
-    
-    /** 
-     * APIMethod: setLayerIndex
-     * Move the given layer to the specified (zero-based) index in the layer
-     *     list, changing its z-index in the map display. Use
-     *     map.getLayerIndex() to find out the current index of a layer. Note
-     *     that this cannot (or at least should not) be effectively used to
-     *     raise base layers above overlays.
-     *
-     * Parameters:
-     * layer - {<OpenLayers.Layer>} 
-     * idx - {int} 
-     */
-    setLayerIndex: function (layer, idx) {
-        var base = this.getLayerIndex(layer);
-        if (idx < 0) {
-            idx = 0;
-        } else if (idx > this.layers.length) {
-            idx = this.layers.length;
-        }
-        if (base != idx) {
-            this.layers.splice(base, 1);
-            this.layers.splice(idx, 0, layer);
-            for (var i=0, len=this.layers.length; i<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]);
-                }
-            }
-        }
-    },
-
-    /** 
-     * APIMethod: raiseLayer
-     * Change the index of the given layer by delta. If delta is positive, 
-     *     the layer is moved up the map's layer stack; if delta is negative,
-     *     the layer is moved down.  Again, note that this cannot (or at least
-     *     should not) be effectively used to raise base layers above overlays.
-     *
-     * Parameters:
-     * layer - {<OpenLayers.Layer>} 
-     * delta - {int} 
-     */
-    raiseLayer: function (layer, delta) {
-        var idx = this.getLayerIndex(layer) + delta;
-        this.setLayerIndex(layer, idx);
-    },
-    
-    /** 
-     * APIMethod: setBaseLayer
-     * Allows user to specify one of the currently-loaded layers as the Map's
-     *     new base layer.
-     * 
-     * Parameters:
-     * newBaseLayer - {<OpenLayers.Layer>}
-     */
-    setBaseLayer: function(newBaseLayer) {
-        
-        if (newBaseLayer != this.baseLayer) {
-          
-            // ensure newBaseLayer is already loaded
-            if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) {
-
-                // preserve center and scale when changing base layers
-                var center = this.getCachedCenter();
-                var oldResolution = this.getResolution();
-                var newResolution = OpenLayers.Util.getResolutionFromScale(
-                    this.getScale(), newBaseLayer.units
-                );
-
-                // make the old base layer invisible 
-                if (this.baseLayer != null && !this.allOverlays) {
-                    this.baseLayer.setVisibility(false);
-                }
-
-                // set new baselayer
-                this.baseLayer = newBaseLayer;
-                
-                if(!this.allOverlays || this.baseLayer.visibility) {
-                    this.baseLayer.setVisibility(true);
-                    // Layer may previously have been visible but not in range.
-                    // In this case we need to redraw it to make it visible.
-                    if (this.baseLayer.inRange === false) {
-                        this.baseLayer.redraw();
-                    }
-                }
-
-                // recenter the map
-                if (center != null) {
-                    // new zoom level derived from old scale
-                    var newZoom = this.getZoomForResolution(
-                        newResolution || this.resolution, true
-                    );
-                    // zoom and force zoom change
-                    this.setCenter(center, newZoom, false, oldResolution != newResolution);
-                }
-
-                this.events.triggerEvent("changebaselayer", {
-                    layer: this.baseLayer
-                });
-            }        
-        }
-    },
-
-
-  /********************************************************/
-  /*                                                      */
-  /*                 Control Functions                    */
-  /*                                                      */
-  /*     The following functions deal with adding and     */
-  /*        removing Controls to and from the Map         */
-  /*                                                      */
-  /********************************************************/         
-
-    /**
-     * APIMethod: addControl
-     * Add the passed over control to the map. Optionally 
-     *     position the control at the given pixel.
-     * 
-     * Parameters:
-     * control - {<OpenLayers.Control>}
-     * px - {<OpenLayers.Pixel>}
-     */    
-    addControl: function (control, px) {
-        this.controls.push(control);
-        this.addControlToMap(control, px);
-    },
-    
-    /**
-     * APIMethod: addControls
-     * Add all of the passed over controls to the map. 
-     *     You can pass over an optional second array
-     *     with pixel-objects to position the controls.
-     *     The indices of the two arrays should match and
-     *     you can add null as pixel for those controls 
-     *     you want to be autopositioned.   
-     *     
-     * Parameters:
-     * controls - {Array(<OpenLayers.Control>)}
-     * pixels - {Array(<OpenLayers.Pixel>)}
-     */    
-    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 );
-        }
-    },
-
-    /**
-     * Method: addControlToMap
-     * 
-     * Parameters:
-     * 
-     * control - {<OpenLayers.Control>}
-     * px - {<OpenLayers.Pixel>}
-     */    
-    addControlToMap: function (control, px) {
-        // If a control doesn't have a div at this point, it belongs in the
-        // viewport.
-        control.outsideViewport = (control.div != null);
-        
-        // If the map has a displayProjection, and the control doesn't, set 
-        // the display projection.
-        if (this.displayProjection && !control.displayProjection) {
-            control.displayProjection = this.displayProjection;
-        }    
-        
-        control.setMap(this);
-        var div = control.draw(px);
-        if (div) {
-            if(!control.outsideViewport) {
-                div.style.zIndex = this.Z_INDEX_BASE['Control'] +
-                                    this.controls.length;
-                this.viewPortDiv.appendChild( div );
-            }
-        }
-        if(control.autoActivate) {
-            control.activate();
-        }
-    },
-    
-    /**
-     * APIMethod: getControl
-     * 
-     * Parameters:
-     * id - {String} ID of the control to return.
-     * 
-     * Returns:
-     * {<OpenLayers.Control>} The control from the map's list of controls 
-     *                        which has a matching 'id'. If none found, 
-     *                        returns null.
-     */    
-    getControl: function (id) {
-        var returnControl = null;
-        for(var i=0, len=this.controls.length; i<len; i++) {
-            var control = this.controls[i];
-            if (control.id == id) {
-                returnControl = control;
-                break;
-            }
-        }
-        return returnControl;
-    },
-    
-    /** 
-     * APIMethod: removeControl
-     * Remove a control from the map. Removes the control both from the map 
-     *     object's internal array of controls, as well as from the map's 
-     *     viewPort (assuming the control was not added outsideViewport)
-     * 
-     * Parameters:
-     * control - {<OpenLayers.Control>} The control to remove.
-     */    
-    removeControl: function (control) {
-        //make sure control is non-null and actually part of our map
-        if ( (control) && (control == this.getControl(control.id)) ) {
-            if (control.div && (control.div.parentNode == this.viewPortDiv)) {
-                this.viewPortDiv.removeChild(control.div);
-            }
-            OpenLayers.Util.removeItem(this.controls, control);
-        }
-    },
-
-  /********************************************************/
-  /*                                                      */
-  /*                  Popup Functions                     */
-  /*                                                      */
-  /*     The following functions deal with adding and     */
-  /*        removing Popups to and from the Map           */
-  /*                                                      */
-  /********************************************************/         
-
-    /** 
-     * APIMethod: addPopup
-     * 
-     * Parameters:
-     * popup - {<OpenLayers.Popup>}
-     * exclusive - {Boolean} If true, closes all other popups first
-     */
-    addPopup: function(popup, exclusive) {
-
-        if (exclusive) {
-            //remove all other popups from screen
-            for (var i = this.popups.length - 1; i >= 0; --i) {
-                this.removePopup(this.popups[i]);
-            }
-        }
-
-        popup.map = this;
-        this.popups.push(popup);
-        var popupDiv = popup.draw();
-        if (popupDiv) {
-            popupDiv.style.zIndex = this.Z_INDEX_BASE['Popup'] +
-                                    this.popups.length;
-            this.layerContainerDiv.appendChild(popupDiv);
-        }
-    },
-    
-    /** 
-    * APIMethod: removePopup
-    * 
-    * Parameters:
-    * popup - {<OpenLayers.Popup>}
-    */
-    removePopup: function(popup) {
-        OpenLayers.Util.removeItem(this.popups, popup);
-        if (popup.div) {
-            try { this.layerContainerDiv.removeChild(popup.div); }
-            catch (e) { } // Popups sometimes apparently get disconnected
-                      // from the layerContainerDiv, and cause complaints.
-        }
-        popup.map = null;
-    },
-
-  /********************************************************/
-  /*                                                      */
-  /*              Container Div Functions                 */
-  /*                                                      */
-  /*   The following functions deal with the access to    */
-  /*    and maintenance of the size of the container div  */
-  /*                                                      */
-  /********************************************************/     
-
-    /**
-     * APIMethod: getSize
-     * 
-     * Returns:
-     * {<OpenLayers.Size>} An <OpenLayers.Size> object that represents the 
-     *                     size, in pixels, of the div into which OpenLayers 
-     *                     has been loaded. 
-     *                     Note - A clone() of this locally cached variable is
-     *                     returned, so as not to allow users to modify it.
-     */
-    getSize: function () {
-        var size = null;
-        if (this.size != null) {
-            size = this.size.clone();
-        }
-        return size;
-    },
-
-    /**
-     * APIMethod: updateSize
-     * This function should be called by any external code which dynamically
-     *     changes the size of the map div (because mozilla wont let us catch 
-     *     the "onresize" for an element)
-     */
-    updateSize: function() {
-        // the div might have moved on the page, also
-        var newSize = this.getCurrentSize();
-        if (newSize && !isNaN(newSize.h) && !isNaN(newSize.w)) {
-            this.events.clearMouseCache();
-            var oldSize = this.getSize();
-            if (oldSize == null) {
-                this.size = oldSize = newSize;
-            }
-            if (!newSize.equals(oldSize)) {
-                
-                // store the new size
-                this.size = newSize;
-    
-                //notify layers of mapresize
-                for(var i=0, len=this.layers.length; i<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);
-                }
-    
-            }
-        }
-        this.events.triggerEvent("updatesize");
-    },
-    
-    /**
-     * Method: getCurrentSize
-     * 
-     * Returns:
-     * {<OpenLayers.Size>} A new <OpenLayers.Size> object with the dimensions 
-     *                     of the map div
-     */
-    getCurrentSize: function() {
-
-        var size = new OpenLayers.Size(this.div.clientWidth, 
-                                       this.div.clientHeight);
-
-        if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) {
-            size.w = this.div.offsetWidth;
-            size.h = this.div.offsetHeight;
-        }
-        if (size.w == 0 && size.h == 0 || isNaN(size.w) && isNaN(size.h)) {
-            size.w = parseInt(this.div.style.width);
-            size.h = parseInt(this.div.style.height);
-        }
-        return size;
-    },
-
-    /** 
-     * Method: calculateBounds
-     * 
-     * Parameters:
-     * center - {<OpenLayers.LonLat>} Default is this.getCenter()
-     * resolution - {float} Default is this.getResolution() 
-     * 
-     * Returns:
-     * {<OpenLayers.Bounds>} A bounds based on resolution, center, and 
-     *                       current mapsize.
-     */
-    calculateBounds: function(center, resolution) {
-
-        var extent = null;
-        
-        if (center == null) {
-            center = this.getCachedCenter();
-        }                
-        if (resolution == null) {
-            resolution = this.getResolution();
-        }
-    
-        if ((center != null) && (resolution != null)) {
-            var halfWDeg = (this.size.w * resolution) / 2;
-            var halfHDeg = (this.size.h * resolution) / 2;
-        
-            extent = new OpenLayers.Bounds(center.lon - halfWDeg,
-                                           center.lat - halfHDeg,
-                                           center.lon + halfWDeg,
-                                           center.lat + halfHDeg);
-        }
-
-        return extent;
-    },
-
-
-  /********************************************************/
-  /*                                                      */
-  /*            Zoom, Center, Pan Functions               */
-  /*                                                      */
-  /*    The following functions handle the validation,    */
-  /*   getting and setting of the Zoom Level and Center   */
-  /*       as well as the panning of the Map              */
-  /*                                                      */
-  /********************************************************/
-    /**
-     * APIMethod: getCenter
-     * 
-     * Returns:
-     * {<OpenLayers.LonLat>}
-     */
-    getCenter: function () {
-        var center = null;
-        var cachedCenter = this.getCachedCenter();
-        if (cachedCenter) {
-            center = cachedCenter.clone();
-        }
-        return center;
-    },
-
-    /**
-     * Method: getCachedCenter
-     *
-     * Returns:
-     * {<OpenLayers.LonLat>}
-     */
-    getCachedCenter: function() {
-        if (!this.center && this.size) {
-            this.center = this.getLonLatFromViewPortPx({
-                x: this.size.w / 2,
-                y: this.size.h / 2
-            });
-        }
-        return this.center;
-    },
-
-    /**
-     * APIMethod: getZoom
-     * 
-     * Returns:
-     * {Integer}
-     */
-    getZoom: function () {
-        return this.zoom;
-    },
-    
-    /** 
-     * APIMethod: pan
-     * Allows user to pan by a value of screen pixels
-     * 
-     * Parameters:
-     * dx - {Integer}
-     * dy - {Integer}
-     * options - {Object} Options to configure panning:
-     *  - *animate* {Boolean} Use panTo instead of setCenter. Default is true.
-     *  - *dragging* {Boolean} Call setCenter with dragging true.  Default is
-     *    false.
-     */
-    pan: function(dx, dy, options) {
-        options = OpenLayers.Util.applyDefaults(options, {
-            animate: true,
-            dragging: false
-        });
-        if (options.dragging) {
-            if (dx != 0 || dy != 0) {
-                this.moveByPx(dx, dy);
-            }
-        } else {
-            // getCenter
-            var centerPx = this.getViewPortPxFromLonLat(this.getCachedCenter());
-
-            // adjust
-            var newCenterPx = centerPx.add(dx, dy);
-
-            if (this.dragging || !newCenterPx.equals(centerPx)) {
-                var newCenterLonLat = this.getLonLatFromViewPortPx(newCenterPx);
-                if (options.animate) {
-                    this.panTo(newCenterLonLat);
-                } else {
-                    this.moveTo(newCenterLonLat);
-                    if(this.dragging) {
-                        this.dragging = false;
-                        this.events.triggerEvent("moveend");
-                    }
-                }    
-            }
-        }        
-
-   },
-   
-   /** 
-     * APIMethod: panTo
-     * Allows user to pan to a new lonlat.
-     * If the new lonlat is in the current extent the map will slide smoothly
-     * 
-     * Parameters:
-     * lonlat - {<OpenLayers.LonLat>}
-     */
-    panTo: function(lonlat) {
-        if (this.panTween && this.getExtent().scale(this.panRatio).containsLonLat(lonlat)) {
-            var center = this.getCachedCenter();
-
-            // center will not change, don't do nothing
-            if (lonlat.equals(center)) {
-                return;
-            }
-
-            var from = this.getPixelFromLonLat(center);
-            var to = this.getPixelFromLonLat(lonlat);
-            var vector = { x: to.x - from.x, y: to.y - from.y };
-            var last = { x: 0, y: 0 };
-
-            this.panTween.start( { x: 0, y: 0 }, vector, this.panDuration, {
-                callbacks: {
-                    eachStep: OpenLayers.Function.bind(function(px) {
-                        var x = px.x - last.x,
-                            y = px.y - last.y;
-                        this.moveByPx(x, y);
-                        last.x = Math.round(px.x);
-                        last.y = Math.round(px.y);
-                    }, this),
-                    done: OpenLayers.Function.bind(function(px) {
-                        this.moveTo(lonlat);
-                        this.dragging = false;
-                        this.events.triggerEvent("moveend");
-                    }, this)
-                }
-            });
-        } else {
-            this.setCenter(lonlat);
-        }
-    },
-
-    /**
-     * APIMethod: setCenter
-     * Set the map center (and optionally, the zoom level).
-     * 
-     * Parameters:
-     * lonlat - {<OpenLayers.LonLat>|Array} The new center location.
-     *     If provided as array, the first value is the x coordinate,
-     *     and the 2nd value is the y coordinate.
-     * zoom - {Integer} Optional zoom level.
-     * dragging - {Boolean} Specifies whether or not to trigger 
-     *                      movestart/end events
-     * forceZoomChange - {Boolean} Specifies whether or not to trigger zoom 
-     *                             change events (needed on baseLayer change)
-     *
-     * TBD: reconsider forceZoomChange in 3.0
-     */
-    setCenter: function(lonlat, zoom, dragging, forceZoomChange) {
-        if (this.panTween) {
-            this.panTween.stop();
-        }
-        if (this.zoomTween) {
-            this.zoomTween.stop();
-        }            
-        this.moveTo(lonlat, zoom, {
-            'dragging': dragging,
-            'forceZoomChange': forceZoomChange
-        });
-    },
-    
-    /** 
-     * Method: moveByPx
-     * Drag the map by pixels.
-     *
-     * Parameters:
-     * dx - {Number}
-     * dy - {Number}
-     */
-    moveByPx: function(dx, dy) {
-        var hw = this.size.w / 2;
-        var hh = this.size.h / 2;
-        var x = hw + dx;
-        var y = hh + dy;
-        var wrapDateLine = this.baseLayer.wrapDateLine;
-        var xRestriction = 0;
-        var yRestriction = 0;
-        if (this.restrictedExtent) {
-            xRestriction = hw;
-            yRestriction = hh;
-            // wrapping the date line makes no sense for restricted extents
-            wrapDateLine = false;
-        }
-        dx = wrapDateLine ||
-                    x <= this.maxPx.x - xRestriction &&
-                    x >= this.minPx.x + xRestriction ? Math.round(dx) : 0;
-        dy = y <= this.maxPx.y - yRestriction &&
-                    y >= this.minPx.y + yRestriction ? Math.round(dy) : 0;
-        if (dx || dy) {
-            if (!this.dragging) {
-                this.dragging = true;
-                this.events.triggerEvent("movestart");
-            }
-            this.center = null;
-            if (dx) {
-                this.layerContainerOriginPx.x -= dx;
-                this.minPx.x -= dx;
-                this.maxPx.x -= dx;
-            }
-            if (dy) {
-                this.layerContainerOriginPx.y -= dy;
-                this.minPx.y -= dy;
-                this.maxPx.y -= dy;
-            }
-            this.applyTransform();
-            var layer, i, len;
-            for (i=0, len=this.layers.length; i<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");
-        }
-    },
-    
-    /**
-     * Method: adjustZoom
-     *
-     * Parameters:
-     * zoom - {Number} The zoom level to adjust
-     *
-     * Returns:
-     * {Integer} Adjusted zoom level that shows a map not wider than its
-     * <baseLayer>'s maxExtent.
-     */
-    adjustZoom: function(zoom) {
-        if (this.baseLayer && this.baseLayer.wrapDateLine) {
-            var resolution, resolutions = this.baseLayer.resolutions,
-                maxResolution = this.getMaxExtent().getWidth() / this.size.w;
-            if (this.getResolutionForZoom(zoom) > maxResolution) {
-                if (this.fractionalZoom) {
-                    zoom = this.getZoomForResolution(maxResolution);
-                } else {
-                    for (var i=zoom|0, ii=resolutions.length; i<ii; ++i) {
-                        if (resolutions[i] <= maxResolution) {
-                            zoom = i;
-                            break;
-                        }
-                    }
-                } 
-            }
-        }
-        return zoom;
-    },
-    
-    /**
-     * APIMethod: getMinZoom
-     * Returns the minimum zoom level for the current map view. If the base
-     * layer is configured with <wrapDateLine> set to true, this will be the
-     * first zoom level that shows no more than one world width in the current
-     * map viewport. Components that rely on this value (e.g. zoom sliders)
-     * should also listen to the map's "updatesize" event and call this method
-     * in the "updatesize" listener.
-     *
-     * Returns:
-     * {Number} Minimum zoom level that shows a map not wider than its
-     * <baseLayer>'s maxExtent. This is an Integer value, unless the map is
-     * configured with <fractionalZoom> set to true.
-     */
-    getMinZoom: function() {
-        return this.adjustZoom(0);
-    },
-
-    /**
-     * Method: moveTo
-     *
-     * Parameters:
-     * lonlat - {<OpenLayers.LonLat>}
-     * zoom - {Integer}
-     * options - {Object}
-     */
-    moveTo: function(lonlat, zoom, options) {
-        if (lonlat != null && !(lonlat instanceof OpenLayers.LonLat)) {
-            lonlat = new OpenLayers.LonLat(lonlat);
-        }
-        if (!options) { 
-            options = {};
-        }
-        if (zoom != null) {
-            zoom = parseFloat(zoom);
-            if (!this.fractionalZoom) {
-                zoom = Math.round(zoom);
-            }
-        }
-        var requestedZoom = zoom;
-        zoom = this.adjustZoom(zoom);
-        if (zoom !== requestedZoom) {
-            // zoom was adjusted, so keep old lonlat to avoid panning
-            lonlat = this.getCenter();
-        }
-        // dragging is false by default
-        var dragging = options.dragging || this.dragging;
-        // forceZoomChange is false by default
-        var forceZoomChange = options.forceZoomChange;
-
-        if (!this.getCachedCenter() && !this.isValidLonLat(lonlat)) {
-            lonlat = this.maxExtent.getCenterLonLat();
-            this.center = lonlat.clone();
-        }
-
-        if(this.restrictedExtent != null) {
-            // In 3.0, decide if we want to change interpretation of maxExtent.
-            if(lonlat == null) { 
-                lonlat = this.center; 
-            }
-            if(zoom == null) { 
-                zoom = this.getZoom(); 
-            }
-            var resolution = this.getResolutionForZoom(zoom);
-            var extent = this.calculateBounds(lonlat, resolution); 
-            if(!this.restrictedExtent.containsBounds(extent)) {
-                var maxCenter = this.restrictedExtent.getCenterLonLat(); 
-                if(extent.getWidth() > this.restrictedExtent.getWidth()) { 
-                    lonlat = new OpenLayers.LonLat(maxCenter.lon, lonlat.lat); 
-                } else if(extent.left < this.restrictedExtent.left) {
-                    lonlat = lonlat.add(this.restrictedExtent.left -
-                                        extent.left, 0); 
-                } else if(extent.right > this.restrictedExtent.right) { 
-                    lonlat = lonlat.add(this.restrictedExtent.right -
-                                        extent.right, 0); 
-                } 
-                if(extent.getHeight() > this.restrictedExtent.getHeight()) { 
-                    lonlat = new OpenLayers.LonLat(lonlat.lon, maxCenter.lat); 
-                } else if(extent.bottom < this.restrictedExtent.bottom) { 
-                    lonlat = lonlat.add(0, this.restrictedExtent.bottom -
-                                        extent.bottom); 
-                } 
-                else if(extent.top > this.restrictedExtent.top) { 
-                    lonlat = lonlat.add(0, this.restrictedExtent.top -
-                                        extent.top); 
-                } 
-            }
-        }
-        
-        var zoomChanged = forceZoomChange || (
-                            (this.isValidZoomLevel(zoom)) && 
-                            (zoom != this.getZoom()) );
-
-        var centerChanged = (this.isValidLonLat(lonlat)) && 
-                            (!lonlat.equals(this.center));
-
-        // if neither center nor zoom will change, no need to do anything
-        if (zoomChanged || centerChanged || dragging) {
-            dragging || this.events.triggerEvent("movestart", {
-                zoomChanged: zoomChanged
-            });
-
-            if (centerChanged) {
-                if (!zoomChanged && this.center) { 
-                    // if zoom hasn't changed, just slide layerContainer
-                    //  (must be done before setting this.center to new value)
-                    this.centerLayerContainer(lonlat);
-                }
-                this.center = lonlat.clone();
-            }
-
-            var res = zoomChanged ?
-                this.getResolutionForZoom(zoom) : this.getResolution();
-            // (re)set the layerContainerDiv's location
-            if (zoomChanged || this.layerContainerOrigin == null) {
-                this.layerContainerOrigin = this.getCachedCenter();
-                this.layerContainerOriginPx.x = 0;
-                this.layerContainerOriginPx.y = 0;
-                this.applyTransform();
-                var maxExtent = this.getMaxExtent({restricted: true});
-                var maxExtentCenter = maxExtent.getCenterLonLat();
-                var lonDelta = this.center.lon - maxExtentCenter.lon;
-                var latDelta = maxExtentCenter.lat - this.center.lat;
-                var extentWidth = Math.round(maxExtent.getWidth() / res);
-                var extentHeight = Math.round(maxExtent.getHeight() / res);
-                this.minPx = {
-                    x: (this.size.w - extentWidth) / 2 - lonDelta / res,
-                    y: (this.size.h - extentHeight) / 2 - latDelta / res
-                };
-                this.maxPx = {
-                    x: this.minPx.x + Math.round(maxExtent.getWidth() / res),
-                    y: this.minPx.y + Math.round(maxExtent.getHeight() / res)
-                };
-            }
-
-            if (zoomChanged) {
-                this.zoom = zoom;
-                this.resolution = res;
-            }    
-            
-            var bounds = this.getExtent();
-            
-            //send the move call to the baselayer and all the overlays    
-
-            if(this.baseLayer.visibility) {
-                this.baseLayer.moveTo(bounds, zoomChanged, options.dragging);
-                options.dragging || this.baseLayer.events.triggerEvent(
-                    "moveend", {zoomChanged: zoomChanged}
-                );
-            }
-            
-            bounds = this.baseLayer.getExtent();
-            
-            for (var i=this.layers.length-1; i>=0; --i) {
-                var layer = this.layers[i];
-                if (layer !== this.baseLayer && !layer.isBaseLayer) {
-                    var inRange = layer.calculateInRange();
-                    if (layer.inRange != inRange) {
-                        // the inRange property has changed. If the layer is
-                        // no longer in range, we turn it off right away. If
-                        // the layer is no longer out of range, the moveTo
-                        // call below will turn on the layer.
-                        layer.inRange = inRange;
-                        if (!inRange) {
-                            layer.display(false);
-                        }
-                        this.events.triggerEvent("changelayer", {
-                            layer: layer, property: "visibility"
-                        });
-                    }
-                    if (inRange && layer.visibility) {
-                        layer.moveTo(bounds, zoomChanged, options.dragging);
-                        options.dragging || layer.events.triggerEvent(
-                            "moveend", {zoomChanged: zoomChanged}
-                        );
-                    }
-                }                
-            }
-            
-            this.events.triggerEvent("move");
-            dragging || this.events.triggerEvent("moveend");
-
-            if (zoomChanged) {
-                //redraw popups
-                for (var i=0, len=this.popups.length; i<len; i++) {
-                    this.popups[i].updatePosition();
-                }
-                this.events.triggerEvent("zoomend");
-            }
-        }
-    },
-
-    /** 
-     * Method: centerLayerContainer
-     * This function takes care to recenter the layerContainerDiv.
-     * 
-     * Parameters:
-     * lonlat - {<OpenLayers.LonLat>}
-     */
-    centerLayerContainer: function (lonlat) {
-        var originPx = this.getViewPortPxFromLonLat(this.layerContainerOrigin);
-        var newPx = this.getViewPortPxFromLonLat(lonlat);
-
-        if ((originPx != null) && (newPx != null)) {
-            var oldLeft = this.layerContainerOriginPx.x;
-            var oldTop = this.layerContainerOriginPx.y;
-            var newLeft = Math.round(originPx.x - newPx.x);
-            var newTop = Math.round(originPx.y - newPx.y);
-            this.applyTransform(
-                (this.layerContainerOriginPx.x = newLeft),
-                (this.layerContainerOriginPx.y = newTop));
-            var dx = oldLeft - newLeft;
-            var dy = oldTop - newTop;
-            this.minPx.x -= dx;
-            this.maxPx.x -= dx;
-            this.minPx.y -= dy;
-            this.maxPx.y -= dy;
-        }        
-    },
-
-    /**
-     * Method: isValidZoomLevel
-     * 
-     * Parameters:
-     * zoomLevel - {Integer}
-     * 
-     * Returns:
-     * {Boolean} Whether or not the zoom level passed in is non-null and 
-     *           within the min/max range of zoom levels.
-     */
-    isValidZoomLevel: function(zoomLevel) {
-        return ( (zoomLevel != null) &&
-                 (zoomLevel >= 0) && 
-                 (zoomLevel < this.getNumZoomLevels()) );
-    },
-    
-    /**
-     * Method: isValidLonLat
-     * 
-     * Parameters:
-     * lonlat - {<OpenLayers.LonLat>}
-     * 
-     * Returns:
-     * {Boolean} Whether or not the lonlat passed in is non-null and within
-     *           the maxExtent bounds
-     */
-    isValidLonLat: function(lonlat) {
-        var valid = false;
-        if (lonlat != null) {
-            var maxExtent = this.getMaxExtent();
-            var worldBounds = this.baseLayer.wrapDateLine && maxExtent;
-            valid = maxExtent.containsLonLat(lonlat, {worldBounds: worldBounds});
-        }
-        return valid;
-    },
-
-  /********************************************************/
-  /*                                                      */
-  /*                 Layer Options                        */
-  /*                                                      */
-  /*    Accessor functions to Layer Options parameters    */
-  /*                                                      */
-  /********************************************************/
-    
-    /**
-     * APIMethod: getProjection
-     * This method returns a string representing the projection. In 
-     *     the case of projection support, this will be the srsCode which
-     *     is loaded -- otherwise it will simply be the string value that
-     *     was passed to the projection at startup.
-     *
-     * FIXME: In 3.0, we will remove getProjectionObject, and instead
-     *     return a Projection object from this function. 
-     * 
-     * Returns:
-     * {String} The Projection string from the base layer or null. 
-     */
-    getProjection: function() {
-        var projection = this.getProjectionObject();
-        return projection ? projection.getCode() : null;
-    },
-    
-    /**
-     * APIMethod: getProjectionObject
-     * Returns the projection obect from the baselayer.
-     *
-     * Returns:
-     * {<OpenLayers.Projection>} The Projection of the base layer.
-     */
-    getProjectionObject: function() {
-        var projection = null;
-        if (this.baseLayer != null) {
-            projection = this.baseLayer.projection;
-        }
-        return projection;
-    },
-    
-    /**
-     * APIMethod: getMaxResolution
-     * 
-     * Returns:
-     * {String} The Map's Maximum Resolution
-     */
-    getMaxResolution: function() {
-        var maxResolution = null;
-        if (this.baseLayer != null) {
-            maxResolution = this.baseLayer.maxResolution;
-        }
-        return maxResolution;
-    },
-        
-    /**
-     * APIMethod: getMaxExtent
-     *
-     * Parameters:
-     * options - {Object} 
-     * 
-     * Allowed Options:
-     * restricted - {Boolean} If true, returns restricted extent (if it is 
-     *     available.)
-     *
-     * Returns:
-     * {<OpenLayers.Bounds>} The maxExtent property as set on the current 
-     *     baselayer, unless the 'restricted' option is set, in which case
-     *     the 'restrictedExtent' option from the map is returned (if it
-     *     is set).
-     */
-    getMaxExtent: function (options) {
-        var maxExtent = null;
-        if(options && options.restricted && this.restrictedExtent){
-            maxExtent = this.restrictedExtent;
-        } else if (this.baseLayer != null) {
-            maxExtent = this.baseLayer.maxExtent;
-        }        
-        return maxExtent;
-    },
-    
-    /**
-     * APIMethod: getNumZoomLevels
-     * 
-     * Returns:
-     * {Integer} The total number of zoom levels that can be displayed by the 
-     *           current baseLayer.
-     */
-    getNumZoomLevels: function() {
-        var numZoomLevels = null;
-        if (this.baseLayer != null) {
-            numZoomLevels = this.baseLayer.numZoomLevels;
-        }
-        return numZoomLevels;
-    },
-
-  /********************************************************/
-  /*                                                      */
-  /*                 Baselayer Functions                  */
-  /*                                                      */
-  /*    The following functions, all publicly exposed     */
-  /*       in the API?, are all merely wrappers to the    */
-  /*       the same calls on whatever layer is set as     */
-  /*                the current base layer                */
-  /*                                                      */
-  /********************************************************/
-
-    /**
-     * APIMethod: getExtent
-     * 
-     * Returns:
-     * {<OpenLayers.Bounds>} A Bounds object which represents the lon/lat 
-     *                       bounds of the current viewPort. 
-     *                       If no baselayer is set, returns null.
-     */
-    getExtent: