Files
openlayers/lib/OpenLayers/Util.js
crschmidt b75fd8ee2c Change This back, undoing r374.
git-svn-id: http://svn.openlayers.org/trunk/openlayers@377 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
2006-05-25 23:39:48 +00:00

841 lines
20 KiB
JavaScript

/**
* @class
*/
OpenLayers.Util = new Object();
/**
* @class This class represents a screen coordinate, in x and y coordinates
*/
OpenLayers.Pixel = Class.create();
OpenLayers.Pixel.prototype = {
/** @type float */
x: 0.0,
/** @type float */
y: 0.0,
/**
* @constructor
*
* @param {float} x
* @param {float} y
*/
initialize: function(x, y) {
this.x = x;
this.y = y;
},
/**
* @return string representation of Pixel. ex: "x=200.4,y=242.2"
* @type str
*/
toString:function() {
return ("x=" + this.x + ",y=" + this.y);
},
/**
* @type OpenLayers.Pixel
*/
copyOf:function() {
return new OpenLayers.Pixel(this.x, this.y);
},
/**
* @param {OpenLayers.Pixel} px
*
* @return whether or not the point passed in as parameter is equal to this
* @type bool
*/
equals:function(px) {
return ((this.x == px.x) && (this.y == px.y));
},
/**
* @param {int} x
* @param {int} y
*
* @return a new Pixel with this pixel's x&y augmented by the
* values passed in.
* @type OpenLayers.Pixel
*/
add:function(x, y) {
return new OpenLayers.Pixel(this.x + x, this.y + y);
},
/** @final @type str */
CLASS_NAME: "OpenLayers.Pixel"
};
/**
* @class This class represents a width and height pair
*/
OpenLayers.Size = Class.create();
OpenLayers.Size.prototype = {
/** @type float */
w: 0.0,
/** @type float */
h: 0.0,
/**
* @constructor
*
* @param {float} w
* @param {float} h
*/
initialize: function(w, h) {
this.w = w;
this.h = h;
},
/**
* @return String representation of OpenLayers.Size object.
* (ex. <i>"w=55,h=66"</i>)
* @type String
*/
toString:function() {
return ("w=" + this.w + ",h=" + this.h);
},
/**
* @return New OpenLayers.Size object with the same w and h values
* @type OpenLayers.Size
*/
copyOf:function() {
return new OpenLayers.Size(this.w, this.h);
},
/**
* @param {OpenLayers.Size} sz
* @returns Boolean value indicating whether the passed-in OpenLayers.Size
* object has the same w and h components as this
*
* @type bool
*/
equals:function(sz) {
return ((this.w == sz.w) && (this.h == sz.h));
},
/** @final @type String */
CLASS_NAME: "OpenLayers.Size"
};
/**
* @class This class represents a longitude and latitude pair
*/
OpenLayers.LonLat = Class.create();
OpenLayers.LonLat.prototype = {
/** @type float */
lon: 0.0,
/** @type float */
lat: 0.0,
/**
* @constructor
*
* @param {float} lon
* @param {float} lat
*/
initialize: function(lon, lat) {
this.lon = lon;
this.lat = lat;
},
/**
* @return String representation of OpenLayers.LonLat object.
* (ex. <i>"lon=5,lat=42"</i>)
* @type String
*/
toString:function() {
return ("lon=" + this.lon + ",lat=" + this.lat);
},
/**
* @return Shortened String representation of OpenLayers.LonLat object.
* (ex. <i>"5, 42"</i>)
* @type String
*/
toShortString:function() {
return (this.lon + ", " + this.lat);
},
/**
* @return New OpenLayers.LonLat object with the same lon and lat values
* @type OpenLayers.LonLat
*/
copyOf:function() {
return new OpenLayers.LonLat(this.lon, this.lat);
},
/**
* @param {float} lon
* @param {float} lat
*
* @return A new OpenLayers.LonLat object with the lon and lat passed-in
* added to this's.
* @type OpenLayers.Pixel
*/
add:function(lon, lat) {
return new OpenLayers.LonLat(this.lon + lon, this.lat + lat);
},
/**
* @param {OpenLayers.LonLat} ll
* @returns Boolean value indicating whether the passed-in OpenLayers.LonLat
* object has the same lon and lat components as this
*
* @type bool
*/
equals:function(ll) {
return ((this.lon == ll.lon) && (this.lat == ll.lat));
},
/** @final @type String */
CLASS_NAME: "OpenLayers.LonLat"
};
/** Alternative constructor that builds a new OpenLayers.LonLat from a
* parameter string
*
* @constructor
*
* @param {String} str Comma-separated Lon,Lat coordinate string.
* (ex. <i>"5,40"</i>)
*
* @returns New OpenLayers.LonLat object built from the passed-in String.
* @type OpenLayers.LonLat
*/
OpenLayers.LonLat.fromString = function(str) {
var pair = str.split(",");
return new OpenLayers.LonLat(parseFloat(pair[0]),
parseFloat(pair[1]));
};
/**
* @class This class represents a bounding box.
* Data stored as left, bottom, right, top floats
*/
OpenLayers.Bounds = Class.create();
OpenLayers.Bounds.prototype = {
/** @type float */
left: 0.0,
/** @type float */
bottom: 0.0,
/** @type float */
right: 0.0,
/** @type float */
top: 0.0,
/**
* @constructor
*
* @param {float} left
* @param {float} bottom
* @param {float} right
* @param {float} top
*
*/
initialize: function(left, bottom, right, top) {
this.left = left;
this.bottom = bottom;
this.right = right;
this.top = top;
},
/**
* @returns A fresh copy of the bounds
* @type OpenLayers.Bounds
*/
copyOf:function() {
return new OpenLayers.Bounds(this.left, this.bottom,
this.right, this.top);
},
/**
* @return String representation of OpenLayers.Bounds object.
* (ex.<i>"left-bottom=(5,42) right-top=(10,45)"</i>)
* @type String
*/
toString:function(){
return ( "left-bottom=(" + this.left + "," + this.bottom + ")"
+ " right-top=(" + this.right + "," + this.top + ")" );
},
/**
* @return Simple String representation of OpenLayers.Bounds object.
* (ex. <i>"5,42,10,45"</i>)
* @type String
*/
toBBOX:function() {
return (this.left + "," + this.bottom + ","
+ this.right + "," + this.top);
},
/**
* @returns The width of the bounds
* @type float
*/
getWidth:function() {
return (this.right - this.left);
},
/**
* @returns The height of the bounds
* @type float
*/
getHeight:function() {
return (this.top - this.bottom);
},
/**
* @returns An OpenLayers.Size which represents the size of the box
* @type OpenLayers.Size
*/
getSize:function() {
return new OpenLayers.Size(this.getWidth(), this.getHeight());
},
/**
* @returns An OpenLayers.Pixel which represents the center of the bounds
* @type OpenLayers.Pixel
*/
getCenterPixel:function() {
return new OpenLayers.Pixel(this.left + (this.getWidth() / 2),
this.bottom + (this.getHeight() / 2));
},
/**
* @returns An OpenLayers.LonLat which represents the center of the bounds
* @type OpenLayers.LonLat
*/
getCenterLonLat:function() {
return new OpenLayers.LonLat(this.left + (this.getWidth() / 2),
this.bottom + (this.getHeight() / 2));
},
/**
* @param {float} x
* @param {float} y
*
* @returns A new OpenLayers.Bounds whose coordinates are the same as this,
* but shifted by the passed-in x and y values
* @type OpenLayers.Bounds
*/
add:function(x, y){
return new OpenLayers.Box(this.left + x, this.bottom + y,
this.right + x, this.top + y);
},
/**
* @param {float} x
* @param {float} y
* @param {Boolean} inclusive Whether or not to include the border.
* Default is true
*
* @return Whether or not the passed-in coordinates are within this bounds
* @type Boolean
*/
contains:function(x, y, inclusive) {
//set default
if (inclusive == null) {
inclusive = true;
}
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;
},
/**
* @param {OpenLayers.Bounds} bounds
* @param {Boolean} partial If true, only part of passed-in
* OpenLayers.Bounds needs be within this bounds.
* If false, the entire passed-in bounds must be
* within. Default is false
* @param {Boolean} inclusive Whether or not to include the border.
* Default is true
*
* @return Whether or not the passed-in OpenLayers.Bounds object is
* contained within this bounds.
* @type Boolean
*/
containsBounds:function(bounds, partial, inclusive) {
//set defaults
if (partial == null) {
partial = false;
}
if (inclusive == null) {
inclusive = true;
}
var inLeft;
var inTop;
var inRight;
var inBottom;
if (inclusive) {
inLeft = (bounds.left >= this.left) && (bounds.left <= this.right);
inTop = (bounds.top >= this.bottom) && (bounds.top <= this.top);
inRight= (bounds.right >= this.left) && (bounds.right <= this.right);
inBottom = (bounds.bottom >= this.bottom) && (bounds.bottom <= this.top);
} else {
inLeft = (bounds.left > this.left) && (bounds.left < this.right);
inTop = (bounds.top > this.bottom) && (bounds.top < this.top);
inRight= (bounds.right > this.left) && (bounds.right < this.right);
inBottom = (bounds.bottom > this.bottom) && (bounds.bottom < this.top);
}
return (partial) ? (inTop || inBottom) && (inLeft || inRight )
: (inTop && inLeft && inBottom && inRight);
},
/**
* @param {OpenLayers.LonLat} lonlat
*
* @returns The quadrant ("br" "tr" "tl" "bl") of the bounds in which
* the coordinate lies.
* @type String
*/
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;
},
/** @final @type String */
CLASS_NAME: "OpenLayers.Bounds"
};
/** Alternative constructor that builds a new OpenLayers.Bounds from a
* parameter string
*
* @constructor
*
* @param {String} str Comma-separated bounds string. (ex. <i>"5,42,10,45"</i>)
*
* @returns New OpenLayers.Bounds object built from the passed-in String.
* @type OpenLayers.Bounds
*/
OpenLayers.Bounds.fromString = function(str) {
var bounds = str.split(",");
return new OpenLayers.Bounds(parseFloat(bounds[0]),
parseFloat(bounds[1]),
parseFloat(bounds[2]),
parseFloat(bounds[3]));
};
/**
* @param {String} quadrant
*
* @returns 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.
* @type String
*/
OpenLayers.Bounds.oppositeQuadrant = function(quadrant) {
var opp = "";
opp += (quadrant.charAt(0) == 't') ? 'b' : 't';
opp += (quadrant.charAt(1) == 'l') ? 'r' : 'l';
return opp;
};
// Some other helpful things
/**
* @param {String} sStart
*
* @returns Whether or not this string starts with the string passed in.
* @type Boolean
*/
String.prototype.startsWith = function(sStart){
return (this.substr(0,sStart.length) == sStart);
};
/**
* @returns A trimmed version of the string - all leading and
* trailing spaces removed
* @type String
*/
String.prototype.trim = function() {
var b = 0;
while(this.substr(b,1) == " ") {
b++;
}
var e = this.length - 1;
while(this.substr(e,1) == " ") {
e--;
}
return this.substring(b, e+1);
};
/** Remove an object from an array. Iterates through the array
* to find the item, then removes it.
*
* @param {Object} item
*
* @returns A reference to the array
* @type Array
*/
Array.prototype.remove = function(item) {
for(var i=0; i < this.length; i++) {
if(this[i] == item) {
this.splice(i,1);
//break;more than once??
}
}
return this;
}
/**
* @returns A fresh copy of the array
* @type Array
*/
Array.prototype.copyOf = function() {
var copy = new Array();
for (var i = 0; i < this.length; i++) {
copy[i] = this[i];
}
return copy;
};
/**
* @param {Object} item
*/
Array.prototype.prepend = function(item) {
this.splice(0, 0, item);
};
/**
* @param {Object} item
*/
Array.prototype.append = function(item){
this[this.length] = item;
};
/**
*/
Array.prototype.clear = function() {
this.length = 0;
};
/**
* @param {Object} element
*
* @returns The first index of the element in the array if found. Else returns -1
* @type int
*/
Array.prototype.indexOf = function(element) {
var index = -1;
for(var i=0; i < this.length; i++) {
if (this[i] == element) {
index = i;
break;
}
}
return index;
}
/**
* zIndex is NOT set
*
* @param {String} id - HTML ID of new element, if empty something is made up
* @param {OpenLayers.Pixel} px - x,y point if missing 0,0 is used
* @param {OpenLayers.Size} sz - size else size of parent is used
* @param {String} overflow - behavior of clipped/overflow content
* @param {String} img - background image url
* @param {String} position - relative or absolute?
*
* @returns A DOM Div created with the specified attributes.
* @type DOMElement
*/
OpenLayers.Util.createDiv = function(id, px, sz, overflow, img, position) {
var x,y,w,h;
if (px) {
x = px.x;
y = px.y;
} else {
x = y = 0;
}
if (!position) {
position = "absolute";
}
if (!id) {
id = "OpenLayersDiv" + (Math.random() * 10000 % 10000);
}
var dom = document.createElement('div');
dom.id = id;
if (overflow) {
dom.style.overflow = overflow;
}
if (sz) {
dom.style.width = sz.w + "px";
dom.style.height = sz.h + "px";
}
dom.style.position = position;
dom.style.top = y;
dom.style.left = x;
dom.style.padding = "0";
dom.style.margin = "0";
dom.style.cursor = "inherit";
if (img) {
dom.style.backgroundImage = 'url(' + img + ')';
}
return dom;
};
/**
* @param {String} img - src URL
* @param {OpenLayers.Size} sz
* @param {OpenLayers.Pixel} xy
* @param {String} position
* @param {String} id
* @param {int} border
*
* @returns A DOM Image created with the specified attributes.
* @type DOMElement
*/
OpenLayers.Util.createImage = function(img, sz, xy, position, id, border) {
image = document.createElement("img");
if (id) {
image.id = id;
image.style.alt = id;
}
if (xy) {
image.style.left = xy.x;
image.style.top = xy.y;
}
if (sz) {
image.style.width = sz.w;
image.style.height = sz.h;
}
if (position) {
image.style.position = position;
} else {
image.style.position = "relative";
}
if (border) {
image.style.border = border + "px solid";
} else {
image.style.border = 0;
}
image.style.cursor = "inherit";
if (img) {
image.src = img;
}
image.galleryImg = "no";
return image;
};
/**
* @param {String} imgURL
* @param {OpenLayers.Size} sz
* @param {OpenLayers.Pixel} px
* @param {String} position
* @param {String} id
* @param {int} border
*
* @returns A DOM Div created with a DOM Image inside it. If the hack is
* needed for transparency in IE, it is added.
* @type DOMElement
*/
OpenLayers.Util.createAlphaImageDiv = function(imgURL, sz, px, position,
id, border) {
var div = OpenLayers.Util.createDiv(id, px, sz);
var img = OpenLayers.Util.createImage(imgURL, sz, null, "relative",
id + "_innerImage", border);
div.appendChild(img);
var arVersion = navigator.appVersion.split("MSIE");
var version = parseFloat(arVersion[1]);
var alphaHack = ( (document.body.filters) &&
(version >= 5.5) && (version < 7) );
if (alphaHack) {
div.style.display = "inline-block";
div.style.filter = "progid:DXImageTransform.Microsoft" +
".AlphaImageLoader(src='" + imgURL + "')";
img.style.filter = "progid:DXImageTransform.Microsoft" +
".Alpha(opacity=0)";
}
return div;
};
/**
* @param {Object} params
*
* @returns a concatenation of the properties of an object in
* http parameter notation.
* (ex. <i>"key1=value1&key2=value2&key3=value3"</i>)
* @type String
*/
OpenLayers.Util.getParameterString = function(params) {
paramsArray = new Array();
for (var key in params) {
var value = params[key];
//skip functions
if (typeof value == 'function') continue;
paramsArray.push(key + "=" + value);
}
return paramsArray.join("&");
};
/**
* @returns The fully formatted image location string
* @type String
*/
OpenLayers.Util.getImagesLocation = function() {
return OpenLayers._getScriptLocation() + "img/";
};
/** Takes a hash and copies any keys that don't exist from
* another hash, by analogy with Object.extend() from
* Prototype.js.
*
* @param {Object} to
* @param {Object} from
*
* @type Object
*/
OpenLayers.Util.applyDefaults = function (to, from) {
for (var key in from) {
if (to[key] == null) {
to[key] = from[key];
}
}
return to;
};
/** These could/should be made namespace aware?
*
* @param {} p
* @param {str} tagName
*
* @return {Array}
*/
OpenLayers.Util.getNodes=function(p, tagName) {
var nodes = Try.these(
function () {
return OpenLayers.Util._getNodes(p.documentElement.childNodes,
tagName);
},
function () {
return OpenLayers.Util._getNodes(p.childNodes, tagName);
}
);
return nodes;
};
/**
* @param {Array} nodes
* @param {str} tagName
*
* @return {Array}
*/
OpenLayers.Util._getNodes=function(nodes, tagName) {
var retArray = new Array();
for (var i=0;i<nodes.length;i++) {
if (nodes[i].nodeName==tagName) {
retArray.push(nodes[i]);
}
}
return retArray;
};
/**
* @param {} parent
* @param {str} item
* @param {int} index
*
* @return {str}
*/
OpenLayers.Util.getTagText = function (parent, item, index) {
var result = OpenLayers.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 "";
}
};
/**
* @param {Event} evt
* @param {HTMLDivElement} div
*
* @return {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);
};