Files
openlayers/lib/OpenLayers/Util.js
crschmidt 92f5a7d749 Reversing the order we set opacity changes the behavior when using VE, but
nothing else. This fixes the fact that you can't use client side opacity 
while including the Virtual Earth javascript. Thanks for the spot from
Jeff Yutzler. Includes a manual test. (Closes #1175)   


git-svn-id: http://svn.openlayers.org/trunk/openlayers@5326 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
2007-12-02 20:46:15 +00:00

1325 lines
38 KiB
JavaScript

/* Copyright (c) 2006-2007 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* Namespace: Util
*/
OpenLayers.Util = {};
/**
* Function: getElement
* This is the old $() from prototype
*/
OpenLayers.Util.getElement = function() {
var elements = [];
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string') {
element = document.getElementById(element);
}
if (arguments.length == 1) {
return element;
}
elements.push(element);
}
return elements;
};
/**
* Maintain $() from prototype
*/
if ($ == null) {
var $ = OpenLayers.Util.getElement;
}
/**
* 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.extend = function(destination, source) {
if(destination && source) {
for(var property in source) {
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.
*/
if(source.hasOwnProperty && source.hasOwnProperty('toString')) {
destination.toString = source.toString;
}
}
return destination;
};
/**
* Function: removeItem
* Remove an object from an array. Iterates through the array
* to find the item, then removes it.
*
* Parameters:
* array - {Array}
* item - {Object}
*
* Return
* {Array} A reference to the array
*/
OpenLayers.Util.removeItem = function(array, item) {
for(var i=0; i < array.length; i++) {
if(array[i] == item) {
array.splice(i,1);
//break;more than once??
}
}
return array;
};
/**
* Function: clearArray
* *Deprecated*. This function will disappear in 3.0.
* Please use "array.length = 0" instead.
*
* Parameters:
* array - {Array}
*/
OpenLayers.Util.clearArray = function(array) {
var msg = "OpenLayers.Util.clearArray() is Deprecated." +
" Please use 'array.length = 0' instead.";
OpenLayers.Console.warn(msg);
array.length = 0;
};
/**
* Function: indexOf
* Seems to exist already in FF, but not in MOZ.
*
* Parameters:
* array - {Array}
* obj - {Object}
*
* Returns:
* {Integer} The index at, which the object was found in the array.
* If not found, returns -1.v
*/
OpenLayers.Util.indexOf = function(array, obj) {
for(var i=0; i < array.length; i++) {
if (array[i] == obj) {
return i;
}
}
return -1;
};
/**
* 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:
* id - {String} The element id attribute to set.
* px - {<OpenLayers.Pixel>} The left and top style position.
* sz - {<OpenLayers.Size>} The width and height style attributes.
* 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;
}
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 (opacity) {
element.style.filter = 'alpha(opacity=' + (opacity * 100) + ')';
element.style.opacity = 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.d
*
* Note: zIndex is NOT set
*
* Parameters:
* id - {String} An identifier for this element. If no id is
* passed an identifier will be created
* automatically.
* px - {<OpenLayers.Pixel>} The element left and top position.
* sz - {<OpenLayers.Size>} The element width and height.
* 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>} The left and top positions.
* sz - {<OpenLayers.Size>} The style.width and style.height values.
* 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.
* delayDisplay - {Boolean} If true waits until the image has been
* loaded.
* opacity - {Float} Fractional value (0.0 - 1.0)
*
* 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";
OpenLayers.Event.observe(image, "load",
OpenLayers.Function.bind(OpenLayers.Util.onImageLoad, image));
OpenLayers.Event.observe(image, "error",
OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError, image));
}
//set special properties
image.style.alt = id;
image.galleryImg = "no";
if (imgURL) {
image.src = imgURL;
}
return image;
};
/**
* Function: setOpacity
* Deprecated.
* This function has been deprecated. Instead, please use
* OpenLayers.Util.modifyDOMElement()
* or
* OpenLayers.Util.modifyAlphaImageDiv()
*
* Set the opacity of a DOM Element
* Note that for this function to work in IE, elements must "have layout"
* according to:
* http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/haslayout.asp
*
* Parameters:
* element - {DOMElement} Set the opacity on this DOM element
* opacity - {Float} Opacity value (0.0 - 1.0)
*/
OpenLayers.Util.setOpacity = function(element, opacity) {
OpenLayers.Util.modifyDOMElement(element, null, null, null,
null, null, null, opacity);
};
/**
* Function: onImageLoad
*/
OpenLayers.Util.onImageLoad = function() {
// The complex check here is to solve issues described in #480.
// Every time a map view changes, it increments the 'viewRequestID'
// property. As the requests for the images for the new map view are sent
// out, they are tagged with this unique viewRequestID.
//
// If an image has no viewRequestID property set, we display it regardless,
// but if it does have a viewRequestID property, we check that it matches
// the viewRequestID set on the map.
//
// If the viewRequestID on the map has changed, that means that the user
// has changed the map view since this specific request was sent out, and
// therefore this tile does not need to be displayed (so we do not execute
// this code that turns its display on).
//
if (!this.viewRequestID ||
(this.map && this.viewRequestID == this.map.viewRequestID)) {
this.style.backgroundColor = null;
this.style.display = "";
}
};
/**
* Property: onImageLoadErrorColor
* {String} The color tiles with load errors will turn.
* Default is "pink"
*/
OpenLayers.Util.onImageLoadErrorColor = "pink";
/**
* 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;
/**
* Function: onImageLoadError
*/
OpenLayers.Util.onImageLoadError = function() {
this._attempts = (this._attempts) ? (this._attempts + 1) : 1;
if(this._attempts <= OpenLayers.IMAGE_RELOAD_ATTEMPTS) {
this.src = this.src;
} else {
this.style.backgroundColor = OpenLayers.Util.onImageLoadErrorColor;
}
this.style.display = "";
};
/**
* 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 alpha has is necessary and possible, false otherwise.
*/
OpenLayers.Util.alphaHack = function() {
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) {
}
return ( filter &&
(version >= 5.5) && (version < 7) );
};
/**
* Function: modifyAlphaImageDiv
*
* div - {DOMElement} Div containing Alpha-adjusted Image
* id - {String}
* px - {<OpenLayers.Pixel>}
* sz - {<OpenLayers.Size>}
* 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);
var img = div.childNodes[0];
if (imgURL) {
img.src = imgURL;
}
OpenLayers.Util.modifyDOMElement(img, div.id + "_innerImage", null, sz,
"relative", border);
if (opacity) {
div.style.opacity = opacity;
div.style.filter = 'alpha(opacity=' + (opacity * 100) + ')';
}
if (OpenLayers.Util.alphaHack()) {
div.style.display = "inline-block";
if (sizing == null) {
sizing = "scale";
}
div.style.filter = "progid:DXImageTransform.Microsoft" +
".AlphaImageLoader(src='" + img.src + "', " +
"sizingMethod='" + sizing + "')";
if (div.style.opacity) {
div.style.filter += " alpha(opacity=" + div.style.opacity * 100 + ")";
}
img.style.filter = "progid:DXImageTransform.Microsoft" +
".Alpha(opacity=0)";
}
};
/**
* Function: createAlphaImageDiv
*
* id - {String}
* px - {<OpenLayers.Pixel>}
* sz - {<OpenLayers.Size>}
* imgURL - {String}
* position - {String}
* border - {String}
* sizing {String} 'crop', 'scale', or 'image'. Default is "scale"
* delayDisplay{Boolean}
*
* 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, false);
div.appendChild(img);
if (delayDisplay) {
img.style.display = "none";
OpenLayers.Event.observe(img, "load",
OpenLayers.Function.bind(OpenLayers.Util.onImageLoad, div));
OpenLayers.Event.observe(img, "error",
OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError, div));
}
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) {
for (var key in from) {
if (to[key] === undefined ||
(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(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 = [];
for (var itemIndex=0; itemIndex<value.length; itemIndex++) {
encodedItemArray.push(encodeURIComponent(value[itemIndex]));
}
encodedValue = encodedItemArray.join(",");
}
else {
/* value is a string; simply encode */
encodedValue = encodeURIComponent(value);
}
paramsArray.push(encodeURIComponent(key) + "=" + encodedValue);
}
}
return paramsArray.join("&");
};
/**
* Property: ImgPath
* {String} Default is ''.
*/
OpenLayers.ImgPath = '';
/**
* Function: getImagesLocation
*
* Returns:
* {String} The fully formatted image location string
*/
OpenLayers.Util.getImagesLocation = function() {
return OpenLayers.ImgPath || (OpenLayers._getScriptLocation() + "img/");
};
/**
* 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; i < arguments.length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) {}
}
return returnValue;
};
/**
* Function: getNodes
*
* These could/should be made namespace aware?
*
* Parameters:
* p - {}
* tagName - {String}
*
* Returns:
* {Array}
*/
OpenLayers.Util.getNodes=function(p, tagName) {
var nodes = OpenLayers.Util.Try(
function () {
return OpenLayers.Util._getNodes(p.documentElement.childNodes,
tagName);
},
function () {
return OpenLayers.Util._getNodes(p.childNodes, tagName);
}
);
return nodes;
};
/**
* Function: _getNodes
*
* Parameters:
* nodes - {Array}
* tagName - {String}
*
* Returns:
* {Array}
*/
OpenLayers.Util._getNodes=function(nodes, tagName) {
var retArray = [];
for (var i=0;i<nodes.length;i++) {
if (nodes[i].nodeName==tagName) {
retArray.push(nodes[i]);
}
}
return retArray;
};
/**
* Function: getTagText
*
* Parameters:
* parent - {}
* item - {String}
* index - {Integer}
*
* Returns:
* {String}
*/
OpenLayers.Util.getTagText = function (parent, item, index) {
var result = OpenLayers.Util.getNodes(parent, item);
if (result && (result.length > 0))
{
if (!index) {
index=0;
}
if (result[index].childNodes.length > 1) {
return result.childNodes[1].nodeValue;
}
else if (result[index].childNodes.length == 1) {
return result[index].firstChild.nodeValue;
}
} else {
return "";
}
};
/**
* 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);
};
/**
* Function: rad
*
* Parameters:
* x - {Float}
*
* Returns:
* {Float}
*/
OpenLayers.Util.rad = function(x) {return x*Math.PI/180;};
/**
* Function: distVincenty
*
* Parameters:
* p1 - {Float}
* p2 - {Float}
*
* Returns:
* {Float}
*/
OpenLayers.Util.distVincenty=function(p1, p2) {
var a = 6378137, b = 6356752.3142, f = 1/298.257223563;
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;
};
/**
* 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 null, query string is taken from page location.
*
* Returns:
* {Object} An object of key/value pairs from the query string.
*/
OpenLayers.Util.getParameters = function(url) {
// if no url specified, take it from the location bar
url = url || window.location.href;
if (url == null) {
url = window.location.href;
}
//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; i < pairs.length; ++i) {
var keyValue = pairs[i].split('=');
if (keyValue[0]) {
var key = decodeURIComponent(keyValue[0]);
var value = keyValue[1] || ''; //empty string if no value
//decode individual values
value = value.split(",");
for(var j=0; j < value.length; j++) {
value[j] = decodeURIComponent(value[j]);
}
//if there's only one value, do not return as array
if (value.length == 1) {
value = value[0];
}
parameters[key] = value;
}
}
return parameters;
};
/**
* Function: getArgs
* Deprecated - Will be removed in 3.0.
* Please use instead OpenLayers.Util.getParameters
*
* Parameters:
* url - {String} Optional url used to extract the query string.
* If null, query string is taken from page location.
*
* Returns:
* {Object} An object of key/value pairs from the query string.
*/
OpenLayers.Util.getArgs = function(url) {
var err = "The getArgs() function is deprecated and will be removed " +
"with the 3.0 version of OpenLayers. Please instead use " +
"OpenLayers.Util.getParameters().";
OpenLayers.Console.warn(err);
return OpenLayers.Util.getParameters(url);
};
/**
* Property: lastSeqID
* {Integer} The ever-incrementing count variable.
* Used for generating unique ids.
*/
OpenLayers.Util.lastSeqID = 0;
/**
* Function: createUniqueID
*
* Parameters:
* prefix {String} String to prefix unique id.
* If null, default is "id_"
*
* Returns:
* {String} A unique id string, built on the passed in prefix
*/
OpenLayers.Util.createUniqueID = function(prefix) {
if (prefix == null) {
prefix = "id_";
}
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
*/
OpenLayers.INCHES_PER_UNIT = {
'inches': 1.0,
'ft': 12.0,
'mi': 63360.0,
'm': 39.3701,
'km': 39370.1,
'dd': 4374754,
'yd': 36
};
OpenLayers.INCHES_PER_UNIT["in"]= OpenLayers.INCHES_PER_UNIT.inches;
OpenLayers.INCHES_PER_UNIT["degrees"] = OpenLayers.INCHES_PER_UNIT.dd;
OpenLayers.INCHES_PER_UNIT["nmi"] = 1852 * OpenLayers.INCHES_PER_UNIT.m;
/**
* Constant: DOTS_PER_INCH
* {Integer} 72 (A sensible default)
*/
OpenLayers.DOTS_PER_INCH = 72;
/**
* Function: normalzeScale
*
* 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.
*/
OpenLayers.Util.getResolutionFromScale = function (scale, units) {
if (units == null) {
units = "degrees";
}
var normScale = OpenLayers.Util.normalizeScale(scale);
var 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: safeStopPropagation
* Deprecated.
*
* This function has been deprecated. Please use directly
* OpenLayers.Event.stop() passing 'true' as the 2nd
* argument (preventDefault)
*
* Safely stop the propagation of an event *without* preventing
* the default browser action from occurring.
*
* Parameter:
* evt - {Event}
*/
OpenLayers.Util.safeStopPropagation = function(evt) {
OpenLayers.Event.stop(evt, true);
};
/**
* Function: pagePositon
* Calculates the position of an element on the page.
*
* Parameters:
* forElement - {DOMElement}
*
* Returns:
* {Array} two item array, L value then T value.
*/
OpenLayers.Util.pagePosition = function(forElement) {
var valueT = 0, valueL = 0;
var element = forElement;
var child = forElement;
while(element) {
if(element == document.body) {
// FIXME: IE, when passed 'window' as the forElement, treats it as
// equal to document.body, but window.style fails, so getStyle
// fails, so we are paranoid and check this here. This check should
// probably move into element.getStyle in 2.6.
if(child && child.style &&
OpenLayers.Element.getStyle(child, 'position') == 'absolute') {
break;
}
}
valueT += element.offsetTop || 0;
valueL += element.offsetLeft || 0;
child = element;
try {
// wrapping this in a try/catch because IE chokes on the offsetParent
element = element.offsetParent;
} catch(e) {
OpenLayers.Console.error(
"OpenLayers.Util.pagePosition failed: element with id " +
element.id + " may be misplaced."
);
break;
}
}
element = forElement;
while(element) {
valueT -= element.scrollTop || 0;
valueL -= element.scrollLeft || 0;
element = element.parentNode;
}
return [valueL, valueT];
};
/**
* 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
});
var urlObj1 = OpenLayers.Util.createUrlObject(url1, options);
var urlObj2 = OpenLayers.Util.createUrlObject(url2, options);
//compare all keys (host, port, etc)
for(var key in urlObj1) {
if (options.test) {
alert(key + "\n1:" + urlObj1[key] + "\n2:" + urlObj2[key]);
}
var val1 = urlObj1[key];
var val2 = urlObj2[key];
switch(key) {
case "args":
//do nothing, they'll be treated below
break;
case "host":
case "port":
case "protocol":
if ((val1 == "") || (val2 == "")) {
//these will be blank for relative urls, so no need to
// compare them here -- call break.
//
break;
}
// otherwise continue with default compare
//
default:
if ( (key != "args") && (urlObj1[key] != urlObj2[key]) ) {
return false;
}
break;
}
}
// 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. Can be one of:
* ignoreCase: lowercase url,
* ignorePort80: don't include explicit port if port is 80,
* ignoreHash: Don't include part of url after the hash (#).
*
* 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 || {};
var urlObject = {};
if (options.ignoreCase) {
url = url.toLowerCase();
}
var a = document.createElement('a');
a.href = url;
//host (without port)
urlObject.host = a.host;
var port = a.port;
if (port.length <= 0) {
var newHostLength = urlObject.host.length - (port.length);
urlObject.host = urlObject.host.substring(0, newHostLength);
}
//protocol
urlObject.protocol = a.protocol;
//port
urlObject.port = ((port == "80") && (options.ignorePort80)) ? "" : port;
//hash
urlObject.hash = (options.ignoreHash) ? "" : 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);
//pathname (this part allows for relative <-> absolute comparison)
if ( ((urlObject.protocol == "file:") && (url.indexOf("file:") != -1)) ||
((urlObject.protocol != "file:") && (urlObject.host != "")) ) {
urlObject.pathname = a.pathname;
//Test to see if the pathname includes the arguments (Opera)
var qIndex = urlObject.pathname.indexOf("?");
if (qIndex != -1) {
urlObject.pathname = urlObject.pathname.substring(0, qIndex);
}
} else {
var relStr = OpenLayers.Util.removeTail(url);
var backs = 0;
do {
var index = relStr.indexOf("../");
if (index == 0) {
backs++;
relStr = relStr.substr(3);
} else if (index >= 0) {
var prevChunk = relStr.substr(0,index - 1);
var slash = prevChunk.indexOf("/");
prevChunk = (slash != -1) ? prevChunk.substr(0, slash +1)
: "";
var postChunk = relStr.substr(index + 3);
relStr = prevChunk + postChunk;
}
} while(index != -1)
var windowAnchor = document.createElement("a");
var windowUrl = window.location.href;
if (options.ignoreCase) {
windowUrl = windowUrl.toLowerCase();
}
windowAnchor.href = windowUrl;
//set protocol of window
urlObject.protocol = windowAnchor.protocol;
var splitter = (windowAnchor.pathname.indexOf("/") != -1) ? "/" : "\\";
var dirs = windowAnchor.pathname.split(splitter);
dirs.pop(); //remove filename
while ((backs > 0) && (dirs.length > 0)) {
dirs.pop();
backs--;
}
relStr = dirs.join("/") + "/"+ relStr;
urlObject.pathname = relStr;
}
if ((urlObject.protocol == "file:") || (urlObject.protocol == "")) {
urlObject.host = "localhost";
}
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;
};
/**
* 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() {
var browserName = "";
var ua = navigator.userAgent.toLowerCase();
if ( ua.indexOf( "opera" ) != -1 ) {
browserName = "opera";
} else if ( ua.indexOf( "msie" ) != -1 ) {
browserName = "msie";
} else if ( ua.indexOf( "safari" ) != -1 ) {
browserName = "safari";
} else if ( ua.indexOf( "mozilla" ) != -1 ) {
if ( ua.indexOf( "firefox" ) != -1 ) {
browserName = "firefox";
} else {
browserName = "mozilla";
}
}
return browserName;
};