that was
│ │ │ │ │ + * supplied to the `round` method.
│ │ │ │ │ + *
│ │ │ │ │ + * @param {int} newOpacity The new opacity to use (0-1).
│ │ │ │ │ */
│ │ │ │ │ - initialize: function(easing) {
│ │ │ │ │ - this.easing = (easing) ? easing : OpenLayers.Easing.Expo.easeOut;
│ │ │ │ │ - },
│ │ │ │ │ + changeOpacity: function(theDiv, newOpacity) {
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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);
│ │ │ │ │ + var mozillaOpacity = newOpacity;
│ │ │ │ │ + var ieOpacity = 'alpha(opacity=' + newOpacity * 100 + ')';
│ │ │ │ │ +
│ │ │ │ │ + theDiv.style.opacity = mozillaOpacity;
│ │ │ │ │ + theDiv.style.filter = ieOpacity;
│ │ │ │ │ +
│ │ │ │ │ + var spanElements = theDiv.parentNode.getElementsByTagName("span");
│ │ │ │ │ +
│ │ │ │ │ + for (var currIdx = 0; currIdx < spanElements.length; currIdx++) {
│ │ │ │ │ + spanElements[currIdx].style.opacity = mozillaOpacity;
│ │ │ │ │ + spanElements[currIdx].style.filter = ieOpacity;
│ │ │ │ │ }
│ │ │ │ │ - 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
│ │ │ │ │ + /** this function takes care of redoing the rico cornering
│ │ │ │ │ + *
│ │ │ │ │ + * you can't just call updateRicoCorners() again and pass it a
│ │ │ │ │ + * new options string. you have to first remove the divs that
│ │ │ │ │ + * rico puts on top and below the content div.
│ │ │ │ │ + *
│ │ │ │ │ + * @param {DOM} theDiv - A child of the outer
that was
│ │ │ │ │ + * supplied to the `round` method.
│ │ │ │ │ + *
│ │ │ │ │ + * @param {Object} options - list of options
│ │ │ │ │ */
│ │ │ │ │ - stop: function() {
│ │ │ │ │ - if (!this.playing) {
│ │ │ │ │ - return;
│ │ │ │ │ - }
│ │ │ │ │ + reRound: function(theDiv, options) {
│ │ │ │ │
│ │ │ │ │ - if (this.callbacks && this.callbacks.done) {
│ │ │ │ │ - this.callbacks.done.call(this, this.finish);
│ │ │ │ │ + var topRico = theDiv.parentNode.childNodes[0];
│ │ │ │ │ + //theDiv would be theDiv.parentNode.childNodes[1]
│ │ │ │ │ + var bottomRico = theDiv.parentNode.childNodes[2];
│ │ │ │ │ +
│ │ │ │ │ + theDiv.parentNode.removeChild(topRico);
│ │ │ │ │ + theDiv.parentNode.removeChild(bottomRico);
│ │ │ │ │ +
│ │ │ │ │ + this.round(theDiv.parentNode, options);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + _roundCornersImpl: function(e, color, bgColor) {
│ │ │ │ │ + if (this.options.border) {
│ │ │ │ │ + this._renderBorder(e, bgColor);
│ │ │ │ │ + }
│ │ │ │ │ + if (this._isTopRounded()) {
│ │ │ │ │ + this._roundTopCorners(e, color, bgColor);
│ │ │ │ │ + }
│ │ │ │ │ + if (this._isBottomRounded()) {
│ │ │ │ │ + this._roundBottomCorners(e, color, bgColor);
│ │ │ │ │ }
│ │ │ │ │ - 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');
│ │ │ │ │ - }
│ │ │ │ │ + _renderBorder: function(el, bgColor) {
│ │ │ │ │ + var borderValue = "1px solid " + this._borderColor(bgColor);
│ │ │ │ │ + var borderL = "border-left: " + borderValue;
│ │ │ │ │ + var borderR = "border-right: " + borderValue;
│ │ │ │ │ + var style = "style='" + borderL + ";" + borderR + "'";
│ │ │ │ │ + el.innerHTML = "
" + el.innerHTML + "
";
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - var c = f - b;
│ │ │ │ │ - value[i] = this.easing.apply(this, [this.time, b, c, this.duration]);
│ │ │ │ │ + _roundTopCorners: function(el, color, bgColor) {
│ │ │ │ │ + var corner = this._createCorner(bgColor);
│ │ │ │ │ + for (var i = 0; i < this.options.numSlices; i++) {
│ │ │ │ │ + corner.appendChild(this._createCornerSlice(color, bgColor, i, "top"));
│ │ │ │ │ }
│ │ │ │ │ - this.time++;
│ │ │ │ │ + el.style.paddingTop = 0;
│ │ │ │ │ + el.insertBefore(corner, el.firstChild);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - 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);
│ │ │ │ │ - }
│ │ │ │ │ + _roundBottomCorners: function(el, color, bgColor) {
│ │ │ │ │ + var corner = this._createCorner(bgColor);
│ │ │ │ │ + for (var i = (this.options.numSlices - 1); i >= 0; i--) {
│ │ │ │ │ + corner.appendChild(this._createCornerSlice(color, bgColor, i, "bottom"));
│ │ │ │ │ }
│ │ │ │ │ + el.style.paddingBottom = 0;
│ │ │ │ │ + el.appendChild(corner);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - if (this.time > this.duration) {
│ │ │ │ │ - this.stop();
│ │ │ │ │ - }
│ │ │ │ │ + _createCorner: function(bgColor) {
│ │ │ │ │ + var corner = document.createElement("div");
│ │ │ │ │ + corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor);
│ │ │ │ │ + return corner;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Create empty functions for all easing methods.
│ │ │ │ │ - */
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Tween"
│ │ │ │ │ -});
│ │ │ │ │ + _createCornerSlice: function(color, bgColor, n, position) {
│ │ │ │ │ + var slice = document.createElement("span");
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * Namespace: OpenLayers.Easing
│ │ │ │ │ - *
│ │ │ │ │ - * Credits:
│ │ │ │ │ - * Easing Equations by Robert Penner,
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Easing = {
│ │ │ │ │ - /**
│ │ │ │ │ - * Create empty functions for all easing methods.
│ │ │ │ │ - */
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Easing"
│ │ │ │ │ -};
│ │ │ │ │ + var inStyle = slice.style;
│ │ │ │ │ + inStyle.backgroundColor = color;
│ │ │ │ │ + inStyle.display = "block";
│ │ │ │ │ + inStyle.height = "1px";
│ │ │ │ │ + inStyle.overflow = "hidden";
│ │ │ │ │ + inStyle.fontSize = "1px";
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * Namespace: OpenLayers.Easing.Linear
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Easing.Linear = {
│ │ │ │ │ + var borderColor = this._borderColor(color, bgColor);
│ │ │ │ │ + if (this.options.border && n == 0) {
│ │ │ │ │ + inStyle.borderTopStyle = "solid";
│ │ │ │ │ + inStyle.borderTopWidth = "1px";
│ │ │ │ │ + inStyle.borderLeftWidth = "0px";
│ │ │ │ │ + inStyle.borderRightWidth = "0px";
│ │ │ │ │ + inStyle.borderBottomWidth = "0px";
│ │ │ │ │ + inStyle.height = "0px"; // assumes css compliant box model
│ │ │ │ │ + inStyle.borderColor = borderColor;
│ │ │ │ │ + } else if (borderColor) {
│ │ │ │ │ + inStyle.borderColor = borderColor;
│ │ │ │ │ + inStyle.borderStyle = "solid";
│ │ │ │ │ + inStyle.borderWidth = "0px 1px";
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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;
│ │ │ │ │ + if (!this.options.compact && (n == (this.options.numSlices - 1))) {
│ │ │ │ │ + inStyle.height = "2px";
│ │ │ │ │ + }
│ │ │ │ │ + this._setMargin(slice, n, position);
│ │ │ │ │ + this._setBorder(slice, n, position);
│ │ │ │ │ + return slice;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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;
│ │ │ │ │ - },
│ │ │ │ │ + _setOptions: function(options) {
│ │ │ │ │ + this.options = {
│ │ │ │ │ + corners: "all",
│ │ │ │ │ + color: "fromElement",
│ │ │ │ │ + bgColor: "fromParent",
│ │ │ │ │ + blend: true,
│ │ │ │ │ + border: false,
│ │ │ │ │ + compact: false
│ │ │ │ │ + };
│ │ │ │ │ + OpenLayers.Util.extend(this.options, options || {});
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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;
│ │ │ │ │ + this.options.numSlices = this.options.compact ? 2 : 4;
│ │ │ │ │ + if (this._isTransparent()) {
│ │ │ │ │ + this.options.blend = false;
│ │ │ │ │ + }
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Easing.Linear"
│ │ │ │ │ -};
│ │ │ │ │ + _whichSideTop: function() {
│ │ │ │ │ + if (this._hasString(this.options.corners, "all", "top")) {
│ │ │ │ │ + return "";
│ │ │ │ │ + }
│ │ │ │ │ + if (this.options.corners.indexOf("tl") >= 0 && this.options.corners.indexOf("tr") >= 0) {
│ │ │ │ │ + return "";
│ │ │ │ │ + }
│ │ │ │ │ + if (this.options.corners.indexOf("tl") >= 0) {
│ │ │ │ │ + return "left";
│ │ │ │ │ + } else if (this.options.corners.indexOf("tr") >= 0) {
│ │ │ │ │ + return "right";
│ │ │ │ │ + }
│ │ │ │ │ + return "";
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * Namespace: OpenLayers.Easing.Expo
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Easing.Expo = {
│ │ │ │ │ + _whichSideBottom: function() {
│ │ │ │ │ + if (this._hasString(this.options.corners, "all", "bottom")) {
│ │ │ │ │ + return "";
│ │ │ │ │ + }
│ │ │ │ │ + if (this.options.corners.indexOf("bl") >= 0 && this.options.corners.indexOf("br") >= 0) {
│ │ │ │ │ + return "";
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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;
│ │ │ │ │ + if (this.options.corners.indexOf("bl") >= 0) {
│ │ │ │ │ + return "left";
│ │ │ │ │ + } else if (this.options.corners.indexOf("br") >= 0) {
│ │ │ │ │ + return "right";
│ │ │ │ │ + }
│ │ │ │ │ + return "";
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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;
│ │ │ │ │ + _borderColor: function(color, bgColor) {
│ │ │ │ │ + if (color == "transparent") {
│ │ │ │ │ + return bgColor;
│ │ │ │ │ + } else if (this.options.border) {
│ │ │ │ │ + return this.options.border;
│ │ │ │ │ + } else if (this.options.blend) {
│ │ │ │ │ + return this._blend(bgColor, color);
│ │ │ │ │ + } else {
│ │ │ │ │ + return "";
│ │ │ │ │ + }
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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"
│ │ │ │ │ -};
│ │ │ │ │ + _setMargin: function(el, n, corners) {
│ │ │ │ │ + var marginSize = this._marginSize(n);
│ │ │ │ │ + var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * Namespace: OpenLayers.Easing.Quad
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Easing.Quad = {
│ │ │ │ │ + if (whichSide == "left") {
│ │ │ │ │ + el.style.marginLeft = marginSize + "px";
│ │ │ │ │ + el.style.marginRight = "0px";
│ │ │ │ │ + } else if (whichSide == "right") {
│ │ │ │ │ + el.style.marginRight = marginSize + "px";
│ │ │ │ │ + el.style.marginLeft = "0px";
│ │ │ │ │ + } else {
│ │ │ │ │ + el.style.marginLeft = marginSize + "px";
│ │ │ │ │ + el.style.marginRight = marginSize + "px";
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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;
│ │ │ │ │ + _setBorder: function(el, n, corners) {
│ │ │ │ │ + var borderSize = this._borderSize(n);
│ │ │ │ │ + var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
│ │ │ │ │ + if (whichSide == "left") {
│ │ │ │ │ + el.style.borderLeftWidth = borderSize + "px";
│ │ │ │ │ + el.style.borderRightWidth = "0px";
│ │ │ │ │ + } else if (whichSide == "right") {
│ │ │ │ │ + el.style.borderRightWidth = borderSize + "px";
│ │ │ │ │ + el.style.borderLeftWidth = "0px";
│ │ │ │ │ + } else {
│ │ │ │ │ + el.style.borderLeftWidth = borderSize + "px";
│ │ │ │ │ + el.style.borderRightWidth = borderSize + "px";
│ │ │ │ │ + }
│ │ │ │ │ + if (this.options.border != false) {
│ │ │ │ │ + el.style.borderLeftWidth = borderSize + "px";
│ │ │ │ │ + el.style.borderRightWidth = borderSize + "px";
│ │ │ │ │ + }
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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;
│ │ │ │ │ + _marginSize: function(n) {
│ │ │ │ │ + if (this._isTransparent()) {
│ │ │ │ │ + return 0;
│ │ │ │ │ + }
│ │ │ │ │ + var marginSizes = [5, 3, 2, 1];
│ │ │ │ │ + var blendedMarginSizes = [3, 2, 1, 0];
│ │ │ │ │ + var compactMarginSizes = [2, 1];
│ │ │ │ │ + var smBlendedMarginSizes = [1, 0];
│ │ │ │ │ +
│ │ │ │ │ + if (this.options.compact && this.options.blend) {
│ │ │ │ │ + return smBlendedMarginSizes[n];
│ │ │ │ │ + } else if (this.options.compact) {
│ │ │ │ │ + return compactMarginSizes[n];
│ │ │ │ │ + } else if (this.options.blend) {
│ │ │ │ │ + return blendedMarginSizes[n];
│ │ │ │ │ + } else {
│ │ │ │ │ + return marginSizes[n];
│ │ │ │ │ + }
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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;
│ │ │ │ │ + _borderSize: function(n) {
│ │ │ │ │ + var transparentBorderSizes = [5, 3, 2, 1];
│ │ │ │ │ + var blendedBorderSizes = [2, 1, 1, 1];
│ │ │ │ │ + var compactBorderSizes = [1, 0];
│ │ │ │ │ + var actualBorderSizes = [0, 2, 0, 0];
│ │ │ │ │ +
│ │ │ │ │ + if (this.options.compact && (this.options.blend || this._isTransparent())) {
│ │ │ │ │ + return 1;
│ │ │ │ │ + } else if (this.options.compact) {
│ │ │ │ │ + return compactBorderSizes[n];
│ │ │ │ │ + } else if (this.options.blend) {
│ │ │ │ │ + return blendedBorderSizes[n];
│ │ │ │ │ + } else if (this.options.border) {
│ │ │ │ │ + return actualBorderSizes[n];
│ │ │ │ │ + } else if (this._isTransparent()) {
│ │ │ │ │ + return transparentBorderSizes[n];
│ │ │ │ │ + }
│ │ │ │ │ + return 0;
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Easing.Quad"
│ │ │ │ │ + _hasString: function(str) {
│ │ │ │ │ + for (var i = 1; i < arguments.length; i++)
│ │ │ │ │ + if (str.indexOf(arguments[i]) >= 0) {
│ │ │ │ │ + return true;
│ │ │ │ │ + } return false;
│ │ │ │ │ + },
│ │ │ │ │ + _blend: function(c1, c2) {
│ │ │ │ │ + var cc1 = OpenLayers.Rico.Color.createFromHex(c1);
│ │ │ │ │ + cc1.blend(OpenLayers.Rico.Color.createFromHex(c2));
│ │ │ │ │ + return cc1;
│ │ │ │ │ + },
│ │ │ │ │ + _background: function(el) {
│ │ │ │ │ + try {
│ │ │ │ │ + return OpenLayers.Rico.Color.createColorFromBackground(el).asHex();
│ │ │ │ │ + } catch (err) {
│ │ │ │ │ + return "#ffffff";
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ + _isTransparent: function() {
│ │ │ │ │ + return this.options.color == "transparent";
│ │ │ │ │ + },
│ │ │ │ │ + _isTopRounded: function() {
│ │ │ │ │ + return this._hasString(this.options.corners, "all", "top", "tl", "tr");
│ │ │ │ │ + },
│ │ │ │ │ + _isBottomRounded: function() {
│ │ │ │ │ + return this._hasString(this.options.corners, "all", "bottom", "bl", "br");
│ │ │ │ │ + },
│ │ │ │ │ + _hasSingleTextChild: function(el) {
│ │ │ │ │ + return el.childNodes.length == 1 && el.childNodes[0].nodeType == 3;
│ │ │ │ │ + }
│ │ │ │ │ };
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ OpenLayers/Events.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ @@ -6402,876 +6259,4976 @@
│ │ │ │ │
│ │ │ │ │ OpenLayers.Event.observe(element, 'MSPointerUp', cb);
│ │ │ │ │ },
│ │ │ │ │
│ │ │ │ │ CLASS_NAME: "OpenLayers.Events"
│ │ │ │ │ });
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/Projection.js
│ │ │ │ │ + OpenLayers/Request/XMLHttpRequest.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ - * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ - * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ - * full text of the license. */
│ │ │ │ │ +// XMLHttpRequest.js Copyright (C) 2010 Sergey Ilinsky (http://www.ilinsky.com)
│ │ │ │ │ +//
│ │ │ │ │ +// Licensed under the Apache License, Version 2.0 (the "License");
│ │ │ │ │ +// you may not use this file except in compliance with the License.
│ │ │ │ │ +// You may obtain a copy of the License at
│ │ │ │ │ +//
│ │ │ │ │ +// http://www.apache.org/licenses/LICENSE-2.0
│ │ │ │ │ +//
│ │ │ │ │ +// Unless required by applicable law or agreed to in writing, software
│ │ │ │ │ +// distributed under the License is distributed on an "AS IS" BASIS,
│ │ │ │ │ +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
│ │ │ │ │ +// See the License for the specific language governing permissions and
│ │ │ │ │ +// limitations under the License.
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ - * @requires OpenLayers/Util.js
│ │ │ │ │ + * @requires OpenLayers/Request.js
│ │ │ │ │ */
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * Namespace: OpenLayers.Projection
│ │ │ │ │ - * Methods for coordinate transforms between coordinate systems. By default,
│ │ │ │ │ - * OpenLayers ships with the ability to transform coordinates between
│ │ │ │ │ - * geographic (EPSG:4326) and web or spherical mercator (EPSG:900913 et al.)
│ │ │ │ │ - * coordinate reference systems. See the
method for details
│ │ │ │ │ - * on usage.
│ │ │ │ │ - *
│ │ │ │ │ - * Additional transforms may be added by using the
│ │ │ │ │ - * library. If the proj4js library is included, the method
│ │ │ │ │ - * will work between any two coordinate reference systems with proj4js
│ │ │ │ │ - * definitions.
│ │ │ │ │ - *
│ │ │ │ │ - * If the proj4js library is not included, or if you wish to allow transforms
│ │ │ │ │ - * between arbitrary coordinate reference systems, use the
│ │ │ │ │ - * method to register a custom transform method.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Projection = OpenLayers.Class({
│ │ │ │ │ +(function() {
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: proj
│ │ │ │ │ - * {Object} Proj4js.Proj instance.
│ │ │ │ │ - */
│ │ │ │ │ - proj: null,
│ │ │ │ │ + // Save reference to earlier defined object implementation (if any)
│ │ │ │ │ + var oXMLHttpRequest = window.XMLHttpRequest;
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: projCode
│ │ │ │ │ - * {String}
│ │ │ │ │ - */
│ │ │ │ │ - projCode: null,
│ │ │ │ │ + // Define on browser type
│ │ │ │ │ + var bGecko = !!window.controllers,
│ │ │ │ │ + bIE = window.document.all && !window.opera,
│ │ │ │ │ + bIE7 = bIE && window.navigator.userAgent.match(/MSIE 7.0/);
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: titleRegEx
│ │ │ │ │ - * {RegExp} regular expression to strip the title from a proj4js definition
│ │ │ │ │ - */
│ │ │ │ │ - titleRegEx: /\+title=[^\+]*/,
│ │ │ │ │ + // Enables "XMLHttpRequest()" call next to "new XMLHttpReques()"
│ │ │ │ │ + function fXMLHttpRequest() {
│ │ │ │ │ + this._object = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
│ │ │ │ │ + this._listeners = [];
│ │ │ │ │ + };
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Constructor: OpenLayers.Projection
│ │ │ │ │ - * This class offers several methods for interacting with a wrapped
│ │ │ │ │ - * pro4js projection object.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * projCode - {String} A string identifying the Well Known Identifier for
│ │ │ │ │ - * the projection.
│ │ │ │ │ - * options - {Object} An optional object to set additional properties
│ │ │ │ │ - * on the projection.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {} A projection object.
│ │ │ │ │ - */
│ │ │ │ │ - initialize: function(projCode, options) {
│ │ │ │ │ - OpenLayers.Util.extend(this, options);
│ │ │ │ │ - this.projCode = projCode;
│ │ │ │ │ - if (typeof Proj4js == "object") {
│ │ │ │ │ - this.proj = new Proj4js.Proj(projCode);
│ │ │ │ │ + // Constructor
│ │ │ │ │ + function cXMLHttpRequest() {
│ │ │ │ │ + return new fXMLHttpRequest;
│ │ │ │ │ + };
│ │ │ │ │ + cXMLHttpRequest.prototype = fXMLHttpRequest.prototype;
│ │ │ │ │ +
│ │ │ │ │ + // BUGFIX: Firefox with Firebug installed would break pages if not executed
│ │ │ │ │ + if (bGecko && oXMLHttpRequest.wrapped)
│ │ │ │ │ + cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped;
│ │ │ │ │ +
│ │ │ │ │ + // Constants
│ │ │ │ │ + cXMLHttpRequest.UNSENT = 0;
│ │ │ │ │ + cXMLHttpRequest.OPENED = 1;
│ │ │ │ │ + cXMLHttpRequest.HEADERS_RECEIVED = 2;
│ │ │ │ │ + cXMLHttpRequest.LOADING = 3;
│ │ │ │ │ + cXMLHttpRequest.DONE = 4;
│ │ │ │ │ +
│ │ │ │ │ + // Public Properties
│ │ │ │ │ + cXMLHttpRequest.prototype.readyState = cXMLHttpRequest.UNSENT;
│ │ │ │ │ + cXMLHttpRequest.prototype.responseText = '';
│ │ │ │ │ + cXMLHttpRequest.prototype.responseXML = null;
│ │ │ │ │ + cXMLHttpRequest.prototype.status = 0;
│ │ │ │ │ + cXMLHttpRequest.prototype.statusText = '';
│ │ │ │ │ +
│ │ │ │ │ + // Priority proposal
│ │ │ │ │ + cXMLHttpRequest.prototype.priority = "NORMAL";
│ │ │ │ │ +
│ │ │ │ │ + // Instance-level Events Handlers
│ │ │ │ │ + cXMLHttpRequest.prototype.onreadystatechange = null;
│ │ │ │ │ +
│ │ │ │ │ + // Class-level Events Handlers
│ │ │ │ │ + cXMLHttpRequest.onreadystatechange = null;
│ │ │ │ │ + cXMLHttpRequest.onopen = null;
│ │ │ │ │ + cXMLHttpRequest.onsend = null;
│ │ │ │ │ + cXMLHttpRequest.onabort = null;
│ │ │ │ │ +
│ │ │ │ │ + // Public Methods
│ │ │ │ │ + cXMLHttpRequest.prototype.open = function(sMethod, sUrl, bAsync, sUser, sPassword) {
│ │ │ │ │ + // Delete headers, required when object is reused
│ │ │ │ │ + delete this._headers;
│ │ │ │ │ +
│ │ │ │ │ + // When bAsync parameter value is omitted, use true as default
│ │ │ │ │ + if (arguments.length < 3)
│ │ │ │ │ + bAsync = true;
│ │ │ │ │ +
│ │ │ │ │ + // Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests
│ │ │ │ │ + this._async = bAsync;
│ │ │ │ │ +
│ │ │ │ │ + // Set the onreadystatechange handler
│ │ │ │ │ + var oRequest = this,
│ │ │ │ │ + nState = this.readyState,
│ │ │ │ │ + fOnUnload;
│ │ │ │ │ +
│ │ │ │ │ + // BUGFIX: IE - memory leak on page unload (inter-page leak)
│ │ │ │ │ + if (bIE && bAsync) {
│ │ │ │ │ + fOnUnload = function() {
│ │ │ │ │ + if (nState != cXMLHttpRequest.DONE) {
│ │ │ │ │ + fCleanTransport(oRequest);
│ │ │ │ │ + // Safe to abort here since onreadystatechange handler removed
│ │ │ │ │ + oRequest.abort();
│ │ │ │ │ + }
│ │ │ │ │ + };
│ │ │ │ │ + window.attachEvent("onunload", fOnUnload);
│ │ │ │ │ }
│ │ │ │ │ - },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIMethod: getCode
│ │ │ │ │ - * Get the string SRS code.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {String} The SRS code.
│ │ │ │ │ - */
│ │ │ │ │ - getCode: function() {
│ │ │ │ │ - return this.proj ? this.proj.srsCode : this.projCode;
│ │ │ │ │ - },
│ │ │ │ │ + // Add method sniffer
│ │ │ │ │ + if (cXMLHttpRequest.onopen)
│ │ │ │ │ + cXMLHttpRequest.onopen.apply(this, arguments);
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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;
│ │ │ │ │ - },
│ │ │ │ │ + if (arguments.length > 4)
│ │ │ │ │ + this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
│ │ │ │ │ + else
│ │ │ │ │ + if (arguments.length > 3)
│ │ │ │ │ + this._object.open(sMethod, sUrl, bAsync, sUser);
│ │ │ │ │ + else
│ │ │ │ │ + this._object.open(sMethod, sUrl, bAsync);
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: toString
│ │ │ │ │ - * Convert projection to string (getCode wrapper).
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {String} The projection code.
│ │ │ │ │ - */
│ │ │ │ │ - toString: function() {
│ │ │ │ │ - return this.getCode();
│ │ │ │ │ - },
│ │ │ │ │ + this.readyState = cXMLHttpRequest.OPENED;
│ │ │ │ │ + fReadyStateChange(this);
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Method: equals
│ │ │ │ │ - * Test equality of two projection instances. Determines equality based
│ │ │ │ │ - * soley on the projection code.
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * {Boolean} The two projections are equivalent.
│ │ │ │ │ - */
│ │ │ │ │ - equals: function(projection) {
│ │ │ │ │ - var p = projection,
│ │ │ │ │ - equals = false;
│ │ │ │ │ - if (p) {
│ │ │ │ │ - if (!(p instanceof OpenLayers.Projection)) {
│ │ │ │ │ - p = new OpenLayers.Projection(p);
│ │ │ │ │ - }
│ │ │ │ │ - if ((typeof Proj4js == "object") && this.proj.defData && p.proj.defData) {
│ │ │ │ │ - equals = this.proj.defData.replace(this.titleRegEx, "") ==
│ │ │ │ │ - p.proj.defData.replace(this.titleRegEx, "");
│ │ │ │ │ - } else if (p.getCode) {
│ │ │ │ │ - var source = this.getCode(),
│ │ │ │ │ - target = p.getCode();
│ │ │ │ │ - equals = source == target ||
│ │ │ │ │ - !!OpenLayers.Projection.transforms[source] &&
│ │ │ │ │ - OpenLayers.Projection.transforms[source][target] ===
│ │ │ │ │ - OpenLayers.Projection.nullTransform;
│ │ │ │ │ + this._object.onreadystatechange = function() {
│ │ │ │ │ + if (bGecko && !bAsync)
│ │ │ │ │ + return;
│ │ │ │ │ +
│ │ │ │ │ + // Synchronize state
│ │ │ │ │ + oRequest.readyState = oRequest._object.readyState;
│ │ │ │ │ +
│ │ │ │ │ + //
│ │ │ │ │ + fSynchronizeValues(oRequest);
│ │ │ │ │ +
│ │ │ │ │ + // BUGFIX: Firefox fires unnecessary DONE when aborting
│ │ │ │ │ + if (oRequest._aborted) {
│ │ │ │ │ + // Reset readyState to UNSENT
│ │ │ │ │ + oRequest.readyState = cXMLHttpRequest.UNSENT;
│ │ │ │ │ +
│ │ │ │ │ + // Return now
│ │ │ │ │ + return;
│ │ │ │ │ }
│ │ │ │ │ - }
│ │ │ │ │ - return equals;
│ │ │ │ │ - },
│ │ │ │ │
│ │ │ │ │ - /* Method: destroy
│ │ │ │ │ - * Destroy projection object.
│ │ │ │ │ - */
│ │ │ │ │ - destroy: function() {
│ │ │ │ │ - delete this.proj;
│ │ │ │ │ - delete this.projCode;
│ │ │ │ │ - },
│ │ │ │ │ + if (oRequest.readyState == cXMLHttpRequest.DONE) {
│ │ │ │ │ + // Free up queue
│ │ │ │ │ + delete oRequest._data;
│ │ │ │ │ + /* if (bAsync)
│ │ │ │ │ + fQueue_remove(oRequest);*/
│ │ │ │ │ + //
│ │ │ │ │ + fCleanTransport(oRequest);
│ │ │ │ │ + // Uncomment this block if you need a fix for IE cache
│ │ │ │ │ + /*
│ │ │ │ │ + // BUGFIX: IE - cache issue
│ │ │ │ │ + if (!oRequest._object.getResponseHeader("Date")) {
│ │ │ │ │ + // Save object to cache
│ │ │ │ │ + oRequest._cached = oRequest._object;
│ │ │ │ │
│ │ │ │ │ - CLASS_NAME: "OpenLayers.Projection"
│ │ │ │ │ -});
│ │ │ │ │ + // Instantiate a new transport object
│ │ │ │ │ + cXMLHttpRequest.call(oRequest);
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * Property: transforms
│ │ │ │ │ - * {Object} Transforms is an object, with from properties, each of which may
│ │ │ │ │ - * have a to property. This allows you to define projections without
│ │ │ │ │ - * requiring support for proj4js to be included.
│ │ │ │ │ - *
│ │ │ │ │ - * This object has keys which correspond to a 'source' projection object. The
│ │ │ │ │ - * keys should be strings, corresponding to the projection.getCode() value.
│ │ │ │ │ - * Each source projection object should have a set of destination projection
│ │ │ │ │ - * keys included in the object.
│ │ │ │ │ - *
│ │ │ │ │ - * Each value in the destination object should be a transformation function,
│ │ │ │ │ - * where the function is expected to be passed an object with a .x and a .y
│ │ │ │ │ - * property. The function should return the object, with the .x and .y
│ │ │ │ │ - * transformed according to the transformation function.
│ │ │ │ │ - *
│ │ │ │ │ - * Note - Properties on this object should not be set directly. To add a
│ │ │ │ │ - * transform method to this object, use the method. For an
│ │ │ │ │ - * example of usage, see the OpenLayers.Layer.SphericalMercator file.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Projection.transforms = {};
│ │ │ │ │ + // Re-send request
│ │ │ │ │ + if (sUser) {
│ │ │ │ │ + if (sPassword)
│ │ │ │ │ + oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
│ │ │ │ │ + else
│ │ │ │ │ + oRequest._object.open(sMethod, sUrl, bAsync, sUser);
│ │ │ │ │ + }
│ │ │ │ │ + else
│ │ │ │ │ + oRequest._object.open(sMethod, sUrl, bAsync);
│ │ │ │ │ + oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified") || new window.Date(0));
│ │ │ │ │ + // Copy headers set
│ │ │ │ │ + if (oRequest._headers)
│ │ │ │ │ + for (var sHeader in oRequest._headers)
│ │ │ │ │ + if (typeof oRequest._headers[sHeader] == "string") // Some frameworks prototype objects with functions
│ │ │ │ │ + oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]);
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * APIProperty: defaults
│ │ │ │ │ - * {Object} Defaults for the SRS codes known to OpenLayers (currently
│ │ │ │ │ - * EPSG:4326, CRS:84, urn:ogc:def:crs:EPSG:6.6:4326, EPSG:900913, EPSG:3857,
│ │ │ │ │ - * EPSG:102113 and EPSG:102100). Keys are the SRS code, values are units,
│ │ │ │ │ - * maxExtent (the validity extent for the SRS) and yx (true if this SRS is
│ │ │ │ │ - * known to have a reverse axis order).
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Projection.defaults = {
│ │ │ │ │ - "EPSG:4326": {
│ │ │ │ │ - units: "degrees",
│ │ │ │ │ - maxExtent: [-180, -90, 180, 90],
│ │ │ │ │ - yx: true
│ │ │ │ │ - },
│ │ │ │ │ - "CRS:84": {
│ │ │ │ │ - units: "degrees",
│ │ │ │ │ - maxExtent: [-180, -90, 180, 90]
│ │ │ │ │ - },
│ │ │ │ │ - "EPSG:900913": {
│ │ │ │ │ - units: "m",
│ │ │ │ │ - maxExtent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34]
│ │ │ │ │ - }
│ │ │ │ │ -};
│ │ │ │ │ + oRequest._object.onreadystatechange = function() {
│ │ │ │ │ + // Synchronize state
│ │ │ │ │ + oRequest.readyState = oRequest._object.readyState;
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * 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;
│ │ │ │ │ -};
│ │ │ │ │ + if (oRequest._aborted) {
│ │ │ │ │ + //
│ │ │ │ │ + oRequest.readyState = cXMLHttpRequest.UNSENT;
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * APIMethod: transform
│ │ │ │ │ - * Transform a point coordinate from one projection to another. Note that
│ │ │ │ │ - * the input point is transformed in place.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * point - { | Object} An object with x and y
│ │ │ │ │ - * properties representing coordinates in those dimensions.
│ │ │ │ │ - * source - {OpenLayers.Projection} Source map coordinate system
│ │ │ │ │ - * dest - {OpenLayers.Projection} Destination map coordinate system
│ │ │ │ │ - *
│ │ │ │ │ - * Returns:
│ │ │ │ │ - * point - {object} A transformed coordinate. The original point is modified.
│ │ │ │ │ - */
│ │ │ │ │ -OpenLayers.Projection.transform = function(point, source, dest) {
│ │ │ │ │ - if (source && dest) {
│ │ │ │ │ - if (!(source instanceof OpenLayers.Projection)) {
│ │ │ │ │ - source = new OpenLayers.Projection(source);
│ │ │ │ │ - }
│ │ │ │ │ - if (!(dest instanceof OpenLayers.Projection)) {
│ │ │ │ │ - dest = new OpenLayers.Projection(dest);
│ │ │ │ │ + // Return
│ │ │ │ │ + return;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + if (oRequest.readyState == cXMLHttpRequest.DONE) {
│ │ │ │ │ + // Clean Object
│ │ │ │ │ + fCleanTransport(oRequest);
│ │ │ │ │ +
│ │ │ │ │ + // get cached request
│ │ │ │ │ + if (oRequest.status == 304)
│ │ │ │ │ + oRequest._object = oRequest._cached;
│ │ │ │ │ +
│ │ │ │ │ + //
│ │ │ │ │ + delete oRequest._cached;
│ │ │ │ │ +
│ │ │ │ │ + //
│ │ │ │ │ + fSynchronizeValues(oRequest);
│ │ │ │ │ +
│ │ │ │ │ + //
│ │ │ │ │ + fReadyStateChange(oRequest);
│ │ │ │ │ +
│ │ │ │ │ + // BUGFIX: IE - memory leak in interrupted
│ │ │ │ │ + if (bIE && bAsync)
│ │ │ │ │ + window.detachEvent("onunload", fOnUnload);
│ │ │ │ │ + }
│ │ │ │ │ + };
│ │ │ │ │ + oRequest._object.send(null);
│ │ │ │ │ +
│ │ │ │ │ + // Return now - wait until re-sent request is finished
│ │ │ │ │ + return;
│ │ │ │ │ + };
│ │ │ │ │ + */
│ │ │ │ │ + // BUGFIX: IE - memory leak in interrupted
│ │ │ │ │ + if (bIE && bAsync)
│ │ │ │ │ + window.detachEvent("onunload", fOnUnload);
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + // BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice
│ │ │ │ │ + if (nState != oRequest.readyState)
│ │ │ │ │ + fReadyStateChange(oRequest);
│ │ │ │ │ +
│ │ │ │ │ + nState = oRequest.readyState;
│ │ │ │ │ }
│ │ │ │ │ - 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);
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + function fXMLHttpRequest_send(oRequest) {
│ │ │ │ │ + oRequest._object.send(oRequest._data);
│ │ │ │ │ +
│ │ │ │ │ + // BUGFIX: Gecko - missing readystatechange calls in synchronous requests
│ │ │ │ │ + if (bGecko && !oRequest._async) {
│ │ │ │ │ + oRequest.readyState = cXMLHttpRequest.OPENED;
│ │ │ │ │ +
│ │ │ │ │ + // Synchronize state
│ │ │ │ │ + fSynchronizeValues(oRequest);
│ │ │ │ │ +
│ │ │ │ │ + // Simulate missing states
│ │ │ │ │ + while (oRequest.readyState < cXMLHttpRequest.DONE) {
│ │ │ │ │ + oRequest.readyState++;
│ │ │ │ │ + fReadyStateChange(oRequest);
│ │ │ │ │ + // Check if we are aborted
│ │ │ │ │ + if (oRequest._aborted)
│ │ │ │ │ + return;
│ │ │ │ │ }
│ │ │ │ │ }
│ │ │ │ │ - }
│ │ │ │ │ - return point;
│ │ │ │ │ -};
│ │ │ │ │ + };
│ │ │ │ │ + cXMLHttpRequest.prototype.send = function(vData) {
│ │ │ │ │ + // Add method sniffer
│ │ │ │ │ + if (cXMLHttpRequest.onsend)
│ │ │ │ │ + cXMLHttpRequest.onsend.apply(this, arguments);
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * 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;
│ │ │ │ │ -};
│ │ │ │ │ + if (!arguments.length)
│ │ │ │ │ + vData = null;
│ │ │ │ │
│ │ │ │ │ -/**
│ │ │ │ │ - * Note: Transforms for web mercator <-> geographic
│ │ │ │ │ - * OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113 and EPSG:102100.
│ │ │ │ │ - * OpenLayers originally started referring to EPSG:900913 as web mercator.
│ │ │ │ │ - * The EPSG has declared EPSG:3857 to be web mercator.
│ │ │ │ │ - * ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as
│ │ │ │ │ - * equivalent. See http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2009/11/20/ArcGIS-Online-moving-to-Google-_2F00_-Bing-tiling-scheme_3A00_-What-does-this-mean-for-you_3F00_.aspx#12084.
│ │ │ │ │ - * For geographic, OpenLayers recognizes EPSG:4326, CRS:84 and
│ │ │ │ │ - * urn:ogc:def:crs:EPSG:6.6:4326. OpenLayers also knows about the reverse axis
│ │ │ │ │ - * order for EPSG:4326.
│ │ │ │ │ - */
│ │ │ │ │ -(function() {
│ │ │ │ │ + // BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required
│ │ │ │ │ + // BUGFIX: IE - rewrites any custom mime-type to "text/xml" in case an XMLNode is sent
│ │ │ │ │ + // BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard)
│ │ │ │ │ + if (vData && vData.nodeType) {
│ │ │ │ │ + vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml;
│ │ │ │ │ + if (!this._headers["Content-Type"])
│ │ │ │ │ + this._object.setRequestHeader("Content-Type", "application/xml");
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - var pole = 20037508.34;
│ │ │ │ │ + this._data = vData;
│ │ │ │ │ + /*
│ │ │ │ │ + // Add to queue
│ │ │ │ │ + if (this._async)
│ │ │ │ │ + fQueue_add(this);
│ │ │ │ │ + else*/
│ │ │ │ │ + fXMLHttpRequest_send(this);
│ │ │ │ │ + };
│ │ │ │ │ + cXMLHttpRequest.prototype.abort = function() {
│ │ │ │ │ + // Add method sniffer
│ │ │ │ │ + if (cXMLHttpRequest.onabort)
│ │ │ │ │ + cXMLHttpRequest.onabort.apply(this, arguments);
│ │ │ │ │
│ │ │ │ │ - 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;
│ │ │ │ │ - }
│ │ │ │ │ + // BUGFIX: Gecko - unnecessary DONE when aborting
│ │ │ │ │ + if (this.readyState > cXMLHttpRequest.UNSENT)
│ │ │ │ │ + this._aborted = true;
│ │ │ │ │
│ │ │ │ │ - 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;
│ │ │ │ │ - }
│ │ │ │ │ + this._object.abort();
│ │ │ │ │
│ │ │ │ │ - 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);
│ │ │ │ │ - }
│ │ │ │ │ + // BUGFIX: IE - memory leak
│ │ │ │ │ + fCleanTransport(this);
│ │ │ │ │ +
│ │ │ │ │ + this.readyState = cXMLHttpRequest.UNSENT;
│ │ │ │ │ +
│ │ │ │ │ + delete this._data;
│ │ │ │ │ + /* if (this._async)
│ │ │ │ │ + fQueue_remove(this);*/
│ │ │ │ │ + };
│ │ │ │ │ + cXMLHttpRequest.prototype.getAllResponseHeaders = function() {
│ │ │ │ │ + return this._object.getAllResponseHeaders();
│ │ │ │ │ + };
│ │ │ │ │ + cXMLHttpRequest.prototype.getResponseHeader = function(sName) {
│ │ │ │ │ + return this._object.getResponseHeader(sName);
│ │ │ │ │ + };
│ │ │ │ │ + cXMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) {
│ │ │ │ │ + // BUGFIX: IE - cache issue
│ │ │ │ │ + if (!this._headers)
│ │ │ │ │ + this._headers = {};
│ │ │ │ │ + this._headers[sName] = sValue;
│ │ │ │ │ +
│ │ │ │ │ + return this._object.setRequestHeader(sName, sValue);
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + // EventTarget interface implementation
│ │ │ │ │ + cXMLHttpRequest.prototype.addEventListener = function(sName, fHandler, bUseCapture) {
│ │ │ │ │ + for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
│ │ │ │ │ + if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)
│ │ │ │ │ + return;
│ │ │ │ │ + // Add listener
│ │ │ │ │ + this._listeners.push([sName, fHandler, bUseCapture]);
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + cXMLHttpRequest.prototype.removeEventListener = function(sName, fHandler, bUseCapture) {
│ │ │ │ │ + for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
│ │ │ │ │ + if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture)
│ │ │ │ │ + break;
│ │ │ │ │ + // Remove listener
│ │ │ │ │ + if (oListener)
│ │ │ │ │ + this._listeners.splice(nIndex, 1);
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + cXMLHttpRequest.prototype.dispatchEvent = function(oEvent) {
│ │ │ │ │ + var oEventPseudo = {
│ │ │ │ │ + 'type': oEvent.type,
│ │ │ │ │ + 'target': this,
│ │ │ │ │ + 'currentTarget': this,
│ │ │ │ │ + 'eventPhase': 2,
│ │ │ │ │ + 'bubbles': oEvent.bubbles,
│ │ │ │ │ + 'cancelable': oEvent.cancelable,
│ │ │ │ │ + 'timeStamp': oEvent.timeStamp,
│ │ │ │ │ + 'stopPropagation': function() {}, // There is no flow
│ │ │ │ │ + 'preventDefault': function() {}, // There is no default action
│ │ │ │ │ + 'initEvent': function() {} // Original event object should be initialized
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + // Execute onreadystatechange
│ │ │ │ │ + if (oEventPseudo.type == "readystatechange" && this.onreadystatechange)
│ │ │ │ │ + (this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]);
│ │ │ │ │ +
│ │ │ │ │ + // Execute listeners
│ │ │ │ │ + for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++)
│ │ │ │ │ + if (oListener[0] == oEventPseudo.type && !oListener[2])
│ │ │ │ │ + (oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]);
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + //
│ │ │ │ │ + cXMLHttpRequest.prototype.toString = function() {
│ │ │ │ │ + return '[' + "object" + ' ' + "XMLHttpRequest" + ']';
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + cXMLHttpRequest.toString = function() {
│ │ │ │ │ + return '[' + "XMLHttpRequest" + ']';
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + // Helper function
│ │ │ │ │ + function fReadyStateChange(oRequest) {
│ │ │ │ │ + // Sniffing code
│ │ │ │ │ + if (cXMLHttpRequest.onreadystatechange)
│ │ │ │ │ + cXMLHttpRequest.onreadystatechange.apply(oRequest);
│ │ │ │ │ +
│ │ │ │ │ + // Fake event
│ │ │ │ │ + oRequest.dispatchEvent({
│ │ │ │ │ + 'type': "readystatechange",
│ │ │ │ │ + 'bubbles': false,
│ │ │ │ │ + 'cancelable': false,
│ │ │ │ │ + 'timeStamp': new Date + 0
│ │ │ │ │ + });
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + function fGetDocument(oRequest) {
│ │ │ │ │ + var oDocument = oRequest.responseXML,
│ │ │ │ │ + sResponse = oRequest.responseText;
│ │ │ │ │ + // Try parsing responseText
│ │ │ │ │ + if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) {
│ │ │ │ │ + oDocument = new window.ActiveXObject("Microsoft.XMLDOM");
│ │ │ │ │ + oDocument.async = false;
│ │ │ │ │ + oDocument.validateOnParse = false;
│ │ │ │ │ + oDocument.loadXML(sResponse);
│ │ │ │ │ }
│ │ │ │ │ - }
│ │ │ │ │ + // Check if there is no error in document
│ │ │ │ │ + if (oDocument)
│ │ │ │ │ + if ((bIE && oDocument.parseError != 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror"))
│ │ │ │ │ + return null;
│ │ │ │ │ + return oDocument;
│ │ │ │ │ + };
│ │ │ │ │
│ │ │ │ │ - // list of equivalent codes for web mercator
│ │ │ │ │ - var mercator = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"],
│ │ │ │ │ - geographic = ["CRS:84", "urn:ogc:def:crs:EPSG:6.6:4326", "EPSG:4326"],
│ │ │ │ │ - i;
│ │ │ │ │ - for (i = mercator.length - 1; i >= 0; --i) {
│ │ │ │ │ - map(mercator[i], geographic);
│ │ │ │ │ - }
│ │ │ │ │ - for (i = geographic.length - 1; i >= 0; --i) {
│ │ │ │ │ - map(geographic[i], mercator);
│ │ │ │ │ - }
│ │ │ │ │ + function fSynchronizeValues(oRequest) {
│ │ │ │ │ + try {
│ │ │ │ │ + oRequest.responseText = oRequest._object.responseText;
│ │ │ │ │ + } catch (e) {}
│ │ │ │ │ + try {
│ │ │ │ │ + oRequest.responseXML = fGetDocument(oRequest._object);
│ │ │ │ │ + } catch (e) {}
│ │ │ │ │ + try {
│ │ │ │ │ + oRequest.status = oRequest._object.status;
│ │ │ │ │ + } catch (e) {}
│ │ │ │ │ + try {
│ │ │ │ │ + oRequest.statusText = oRequest._object.statusText;
│ │ │ │ │ + } catch (e) {}
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + function fCleanTransport(oRequest) {
│ │ │ │ │ + // BUGFIX: IE - memory leak (on-page leak)
│ │ │ │ │ + oRequest._object.onreadystatechange = new window.Function;
│ │ │ │ │ + };
│ │ │ │ │ + /*
│ │ │ │ │ + // Queue manager
│ │ │ │ │ + var oQueuePending = {"CRITICAL":[],"HIGH":[],"NORMAL":[],"LOW":[],"LOWEST":[]},
│ │ │ │ │ + aQueueRunning = [];
│ │ │ │ │ + function fQueue_add(oRequest) {
│ │ │ │ │ + oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : "NORMAL"].push(oRequest);
│ │ │ │ │ + //
│ │ │ │ │ + setTimeout(fQueue_process);
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + function fQueue_remove(oRequest) {
│ │ │ │ │ + for (var nIndex = 0, bFound = false; nIndex < aQueueRunning.length; nIndex++)
│ │ │ │ │ + if (bFound)
│ │ │ │ │ + aQueueRunning[nIndex - 1] = aQueueRunning[nIndex];
│ │ │ │ │ + else
│ │ │ │ │ + if (aQueueRunning[nIndex] == oRequest)
│ │ │ │ │ + bFound = true;
│ │ │ │ │ + if (bFound)
│ │ │ │ │ + aQueueRunning.length--;
│ │ │ │ │ + //
│ │ │ │ │ + setTimeout(fQueue_process);
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + function fQueue_process() {
│ │ │ │ │ + if (aQueueRunning.length < 6) {
│ │ │ │ │ + for (var sPriority in oQueuePending) {
│ │ │ │ │ + if (oQueuePending[sPriority].length) {
│ │ │ │ │ + var oRequest = oQueuePending[sPriority][0];
│ │ │ │ │ + oQueuePending[sPriority] = oQueuePending[sPriority].slice(1);
│ │ │ │ │ + //
│ │ │ │ │ + aQueueRunning.push(oRequest);
│ │ │ │ │ + // Send request
│ │ │ │ │ + fXMLHttpRequest_send(oRequest);
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + };
│ │ │ │ │ + */
│ │ │ │ │ + // Internet Explorer 5.0 (missing apply)
│ │ │ │ │ + if (!window.Function.prototype.apply) {
│ │ │ │ │ + window.Function.prototype.apply = function(oRequest, oArguments) {
│ │ │ │ │ + if (!oArguments)
│ │ │ │ │ + oArguments = [];
│ │ │ │ │ + oRequest.__func = this;
│ │ │ │ │ + oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);
│ │ │ │ │ + delete oRequest.__func;
│ │ │ │ │ + };
│ │ │ │ │ + };
│ │ │ │ │
│ │ │ │ │ + // Register new object with window
│ │ │ │ │ + /**
│ │ │ │ │ + * Class: OpenLayers.Request.XMLHttpRequest
│ │ │ │ │ + * Standard-compliant (W3C) cross-browser implementation of the
│ │ │ │ │ + * XMLHttpRequest object. From
│ │ │ │ │ + * http://code.google.com/p/xmlhttprequest/.
│ │ │ │ │ + */
│ │ │ │ │ + if (!OpenLayers.Request) {
│ │ │ │ │ + /**
│ │ │ │ │ + * This allows for OpenLayers/Request.js to be included
│ │ │ │ │ + * before or after this script.
│ │ │ │ │ + */
│ │ │ │ │ + OpenLayers.Request = {};
│ │ │ │ │ + }
│ │ │ │ │ + OpenLayers.Request.XMLHttpRequest = cXMLHttpRequest;
│ │ │ │ │ })();
│ │ │ │ │ /* ======================================================================
│ │ │ │ │ - OpenLayers/Map.js
│ │ │ │ │ + OpenLayers/Request.js
│ │ │ │ │ ====================================================================== */
│ │ │ │ │
│ │ │ │ │ /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ * full text of the license. */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ - * @requires OpenLayers/Util.js
│ │ │ │ │ - * @requires OpenLayers/Util/vendorPrefix.js
│ │ │ │ │ * @requires OpenLayers/Events.js
│ │ │ │ │ - * @requires OpenLayers/Tween.js
│ │ │ │ │ - * @requires OpenLayers/Projection.js
│ │ │ │ │ + * @requires OpenLayers/Request/XMLHttpRequest.js
│ │ │ │ │ */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Class: OpenLayers.Map
│ │ │ │ │ - * Instances of OpenLayers.Map are interactive maps embedded in a web page.
│ │ │ │ │ - * Create a new map with the constructor.
│ │ │ │ │ - *
│ │ │ │ │ - * On their own maps do not provide much functionality. To extend a map
│ │ │ │ │ - * it's necessary to add controls () and
│ │ │ │ │ - * layers () to the map.
│ │ │ │ │ + * TODO: deprecate me
│ │ │ │ │ + * Use OpenLayers.Request.proxy instead.
│ │ │ │ │ */
│ │ │ │ │ -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
│ │ │ │ │ - },
│ │ │ │ │ +OpenLayers.ProxyHost = "";
│ │ │ │ │
│ │ │ │ │ +/**
│ │ │ │ │ + * Namespace: OpenLayers.Request
│ │ │ │ │ + * The OpenLayers.Request namespace contains convenience methods for working
│ │ │ │ │ + * with XMLHttpRequests. These methods work with a cross-browser
│ │ │ │ │ + * W3C compliant class.
│ │ │ │ │ + */
│ │ │ │ │ +if (!OpenLayers.Request) {
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: events
│ │ │ │ │ - * {}
│ │ │ │ │ - *
│ │ │ │ │ - * Register a listener for a particular event with the following syntax:
│ │ │ │ │ - * (code)
│ │ │ │ │ - * map.events.register(type, obj, listener);
│ │ │ │ │ - * (end)
│ │ │ │ │ - *
│ │ │ │ │ - * Listeners will be called with a reference to an event object. The
│ │ │ │ │ - * properties of this event depends on exactly what happened.
│ │ │ │ │ - *
│ │ │ │ │ - * All event objects have at least the following properties:
│ │ │ │ │ - * object - {Object} A reference to map.events.object.
│ │ │ │ │ - * element - {DOMElement} A reference to map.events.element.
│ │ │ │ │ - *
│ │ │ │ │ - * Browser events have the following additional properties:
│ │ │ │ │ - * xy - {} The pixel location of the event (relative
│ │ │ │ │ - * to the the map viewport).
│ │ │ │ │ - *
│ │ │ │ │ - * Supported map event types:
│ │ │ │ │ - * preaddlayer - triggered before a layer has been added. The event
│ │ │ │ │ - * object will include a *layer* property that references the layer
│ │ │ │ │ - * to be added. When a listener returns "false" the adding will be
│ │ │ │ │ - * aborted.
│ │ │ │ │ - * addlayer - triggered after a layer has been added. The event object
│ │ │ │ │ - * will include a *layer* property that references the added layer.
│ │ │ │ │ - * preremovelayer - triggered before a layer has been removed. The event
│ │ │ │ │ - * object will include a *layer* property that references the layer
│ │ │ │ │ - * to be removed. When a listener returns "false" the removal will be
│ │ │ │ │ - * aborted.
│ │ │ │ │ - * removelayer - triggered after a layer has been removed. The event
│ │ │ │ │ - * object will include a *layer* property that references the removed
│ │ │ │ │ - * layer.
│ │ │ │ │ - * changelayer - triggered after a layer name change, order change,
│ │ │ │ │ - * opacity change, params change, visibility change (actual visibility,
│ │ │ │ │ - * not the layer's visibility property) or attribution change (due to
│ │ │ │ │ - * extent change). Listeners will receive an event object with *layer*
│ │ │ │ │ - * and *property* properties. The *layer* property will be a reference
│ │ │ │ │ - * to the changed layer. The *property* property will be a key to the
│ │ │ │ │ - * changed property (name, order, opacity, params, visibility or
│ │ │ │ │ - * attribution).
│ │ │ │ │ - * movestart - triggered after the start of a drag, pan, or zoom. The event
│ │ │ │ │ - * object may include a *zoomChanged* property that tells whether the
│ │ │ │ │ - * zoom has changed.
│ │ │ │ │ - * move - triggered after each drag, pan, or zoom
│ │ │ │ │ - * moveend - triggered after a drag, pan, or zoom completes
│ │ │ │ │ - * zoomend - triggered after a zoom completes
│ │ │ │ │ - * mouseover - triggered after mouseover the map
│ │ │ │ │ - * mouseout - triggered after mouseout the map
│ │ │ │ │ - * mousemove - triggered after mousemove the map
│ │ │ │ │ - * changebaselayer - triggered after the base layer changes
│ │ │ │ │ - * updatesize - triggered after the method was executed
│ │ │ │ │ + * This allows for OpenLayers/Request/XMLHttpRequest.js to be included
│ │ │ │ │ + * before or after this script.
│ │ │ │ │ */
│ │ │ │ │ + OpenLayers.Request = {};
│ │ │ │ │ +}
│ │ │ │ │ +OpenLayers.Util.extend(OpenLayers.Request, {
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: id
│ │ │ │ │ - * {String} Unique identifier for the map
│ │ │ │ │ + * Constant: DEFAULT_CONFIG
│ │ │ │ │ + * {Object} Default configuration for all requests.
│ │ │ │ │ */
│ │ │ │ │ - id: null,
│ │ │ │ │ + DEFAULT_CONFIG: {
│ │ │ │ │ + method: "GET",
│ │ │ │ │ + url: window.location.href,
│ │ │ │ │ + async: true,
│ │ │ │ │ + user: undefined,
│ │ │ │ │ + password: undefined,
│ │ │ │ │ + params: null,
│ │ │ │ │ + proxy: OpenLayers.ProxyHost,
│ │ │ │ │ + headers: {},
│ │ │ │ │ + data: null,
│ │ │ │ │ + callback: function() {},
│ │ │ │ │ + success: null,
│ │ │ │ │ + failure: null,
│ │ │ │ │ + scope: null
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: fractionalZoom
│ │ │ │ │ - * {Boolean} For a base layer that supports it, allow the map resolution
│ │ │ │ │ - * to be set to a value between one of the values in the resolutions
│ │ │ │ │ - * array. Default is false.
│ │ │ │ │ - *
│ │ │ │ │ - * When fractionalZoom is set to true, it is possible to zoom to
│ │ │ │ │ - * an arbitrary extent. This requires a base layer from a source
│ │ │ │ │ - * that supports requests for arbitrary extents (i.e. not cached
│ │ │ │ │ - * tiles on a regular lattice). This means that fractionalZoom
│ │ │ │ │ - * will not work with commercial layers (Google, Yahoo, VE), layers
│ │ │ │ │ - * using TileCache, or any other pre-cached data sources.
│ │ │ │ │ - *
│ │ │ │ │ - * If you are using fractionalZoom, then you should also use
│ │ │ │ │ - * instead of layer.resolutions[zoom] as the
│ │ │ │ │ - * former works for non-integer zoom levels.
│ │ │ │ │ + * Constant: URL_SPLIT_REGEX
│ │ │ │ │ */
│ │ │ │ │ - fractionalZoom: false,
│ │ │ │ │ + URL_SPLIT_REGEX: /([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ * APIProperty: events
│ │ │ │ │ * {} An events object that handles all
│ │ │ │ │ - * events on the map
│ │ │ │ │ + * events on the {} object.
│ │ │ │ │ + *
│ │ │ │ │ + * All event listeners will receive an event object with three properties:
│ │ │ │ │ + * request - {} The request object.
│ │ │ │ │ + * config - {Object} The config object sent to the specific request method.
│ │ │ │ │ + * requestUrl - {String} The request url.
│ │ │ │ │ + *
│ │ │ │ │ + * Supported event types:
│ │ │ │ │ + * complete - Triggered when we have a response from the request, if a
│ │ │ │ │ + * listener returns false, no further response processing will take
│ │ │ │ │ + * place.
│ │ │ │ │ + * success - Triggered when the HTTP response has a success code (200-299).
│ │ │ │ │ + * failure - Triggered when the HTTP response does not have a success code.
│ │ │ │ │ */
│ │ │ │ │ - events: null,
│ │ │ │ │ + events: new OpenLayers.Events(this),
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * 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.
│ │ │ │ │ + * Method: makeSameOrigin
│ │ │ │ │ + * Using the specified proxy, returns a same origin url of the provided url.
│ │ │ │ │ *
│ │ │ │ │ - * Note:
│ │ │ │ │ - * If you set map.allOverlays to true, then you *cannot* use
│ │ │ │ │ - * map.setBaseLayer or layer.setIsBaseLayer. With allOverlays true,
│ │ │ │ │ - * the lowest layer in the draw layer is the base layer. So, to change
│ │ │ │ │ - * the base layer, use or to set the layer
│ │ │ │ │ - * index to 0.
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * url - {String} An arbitrary url
│ │ │ │ │ + * proxy {String|Function} The proxy to use to make the provided url a
│ │ │ │ │ + * same origin url.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns
│ │ │ │ │ + * {String} the same origin url. If no proxy is provided, the returned url
│ │ │ │ │ + * will be the same as the provided url.
│ │ │ │ │ */
│ │ │ │ │ - allOverlays: false,
│ │ │ │ │ + makeSameOrigin: function(url, proxy) {
│ │ │ │ │ + var sameOrigin = url.indexOf("http") !== 0;
│ │ │ │ │ + var urlParts = !sameOrigin && url.match(this.URL_SPLIT_REGEX);
│ │ │ │ │ + if (urlParts) {
│ │ │ │ │ + var location = window.location;
│ │ │ │ │ + sameOrigin =
│ │ │ │ │ + urlParts[1] == location.protocol &&
│ │ │ │ │ + urlParts[3] == location.hostname;
│ │ │ │ │ + var uPort = urlParts[4],
│ │ │ │ │ + lPort = location.port;
│ │ │ │ │ + if (uPort != 80 && uPort != "" || lPort != "80" && lPort != "") {
│ │ │ │ │ + sameOrigin = sameOrigin && uPort == lPort;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (!sameOrigin) {
│ │ │ │ │ + if (proxy) {
│ │ │ │ │ + if (typeof proxy == "function") {
│ │ │ │ │ + url = proxy(url);
│ │ │ │ │ + } else {
│ │ │ │ │ + url = proxy + encodeURIComponent(url);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return url;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: div
│ │ │ │ │ - * {DOMElement|String} The element that contains the map (or an id for
│ │ │ │ │ - * that element). If the constructor is called
│ │ │ │ │ - * with two arguments, this should be provided as the first argument.
│ │ │ │ │ - * Alternatively, the map constructor can be called with the options
│ │ │ │ │ - * object as the only argument. In this case (one argument), a
│ │ │ │ │ - * div property may or may not be provided. If the div property
│ │ │ │ │ - * is not provided, the map can be rendered to a container later
│ │ │ │ │ - * using the method.
│ │ │ │ │ - *
│ │ │ │ │ - * Note:
│ │ │ │ │ - * If you are calling after map construction, do not use
│ │ │ │ │ - * auto. Instead, divide your by your
│ │ │ │ │ - * maximum expected dimension.
│ │ │ │ │ + * APIMethod: issue
│ │ │ │ │ + * Create a new XMLHttpRequest object, open it, set any headers, bind
│ │ │ │ │ + * a callback to done state, and send any data. It is recommended that
│ │ │ │ │ + * you use one , , , , , or .
│ │ │ │ │ + * This method is only documented to provide detail on the configuration
│ │ │ │ │ + * options available to all request methods.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * config - {Object} Object containing properties for configuring the
│ │ │ │ │ + * request. Allowed configuration properties are described below.
│ │ │ │ │ + * This object is modified and should not be reused.
│ │ │ │ │ + *
│ │ │ │ │ + * Allowed config properties:
│ │ │ │ │ + * method - {String} One of GET, POST, PUT, DELETE, HEAD, or
│ │ │ │ │ + * OPTIONS. Default is GET.
│ │ │ │ │ + * url - {String} URL for the request.
│ │ │ │ │ + * async - {Boolean} Open an asynchronous request. Default is true.
│ │ │ │ │ + * user - {String} User for relevant authentication scheme. Set
│ │ │ │ │ + * to null to clear current user.
│ │ │ │ │ + * password - {String} Password for relevant authentication scheme.
│ │ │ │ │ + * Set to null to clear current password.
│ │ │ │ │ + * proxy - {String} Optional proxy. Defaults to
│ │ │ │ │ + * .
│ │ │ │ │ + * params - {Object} Any key:value pairs to be appended to the
│ │ │ │ │ + * url as a query string. Assumes url doesn't already include a query
│ │ │ │ │ + * string or hash. Typically, this is only appropriate for
│ │ │ │ │ + * requests where the query string will be appended to the url.
│ │ │ │ │ + * Parameter values that are arrays will be
│ │ │ │ │ + * concatenated with a comma (note that this goes against form-encoding)
│ │ │ │ │ + * as is done with .
│ │ │ │ │ + * headers - {Object} Object with header:value pairs to be set on
│ │ │ │ │ + * the request.
│ │ │ │ │ + * data - {String | Document} Optional data to send with the request.
│ │ │ │ │ + * Typically, this is only used with and requests.
│ │ │ │ │ + * Make sure to provide the appropriate "Content-Type" header for your
│ │ │ │ │ + * data. For and requests, the content type defaults to
│ │ │ │ │ + * "application-xml". If your data is a different content type, or
│ │ │ │ │ + * if you are using a different HTTP method, set the "Content-Type"
│ │ │ │ │ + * header to match your data type.
│ │ │ │ │ + * callback - {Function} Function to call when request is done.
│ │ │ │ │ + * To determine if the request failed, check request.status (200
│ │ │ │ │ + * indicates success).
│ │ │ │ │ + * success - {Function} Optional function to call if request status is in
│ │ │ │ │ + * the 200s. This will be called in addition to callback above and
│ │ │ │ │ + * would typically only be used as an alternative.
│ │ │ │ │ + * failure - {Function} Optional function to call if request status is not
│ │ │ │ │ + * in the 200s. This will be called in addition to callback above and
│ │ │ │ │ + * would typically only be used as an alternative.
│ │ │ │ │ + * scope - {Object} If callback is a public method on some object,
│ │ │ │ │ + * set the scope to that object.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {XMLHttpRequest} Request object. To abort the request before a response
│ │ │ │ │ + * is received, call abort() on the request object.
│ │ │ │ │ */
│ │ │ │ │ - div: null,
│ │ │ │ │ + issue: function(config) {
│ │ │ │ │ + // apply default config - proxy host may have changed
│ │ │ │ │ + var defaultConfig = OpenLayers.Util.extend(
│ │ │ │ │ + this.DEFAULT_CONFIG, {
│ │ │ │ │ + proxy: OpenLayers.ProxyHost
│ │ │ │ │ + }
│ │ │ │ │ + );
│ │ │ │ │ + config = config || {};
│ │ │ │ │ + config.headers = config.headers || {};
│ │ │ │ │ + config = OpenLayers.Util.applyDefaults(config, defaultConfig);
│ │ │ │ │ + config.headers = OpenLayers.Util.applyDefaults(config.headers, defaultConfig.headers);
│ │ │ │ │ + // Always set the "X-Requested-With" header to signal that this request
│ │ │ │ │ + // was issued through the XHR-object. Since header keys are case
│ │ │ │ │ + // insensitive and we want to allow overriding of the "X-Requested-With"
│ │ │ │ │ + // header through the user we cannot use applyDefaults, but have to
│ │ │ │ │ + // check manually whether we were called with a "X-Requested-With"
│ │ │ │ │ + // header.
│ │ │ │ │ + var customRequestedWithHeader = false,
│ │ │ │ │ + headerKey;
│ │ │ │ │ + for (headerKey in config.headers) {
│ │ │ │ │ + if (config.headers.hasOwnProperty(headerKey)) {
│ │ │ │ │ + if (headerKey.toLowerCase() === 'x-requested-with') {
│ │ │ │ │ + customRequestedWithHeader = true;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (customRequestedWithHeader === false) {
│ │ │ │ │ + // we did not have a custom "X-Requested-With" header
│ │ │ │ │ + config.headers['X-Requested-With'] = 'XMLHttpRequest';
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: dragging
│ │ │ │ │ - * {Boolean} The map is currently being dragged.
│ │ │ │ │ - */
│ │ │ │ │ - dragging: false,
│ │ │ │ │ + // create request, open, and set headers
│ │ │ │ │ + var request = new OpenLayers.Request.XMLHttpRequest();
│ │ │ │ │ + var url = OpenLayers.Util.urlAppend(config.url,
│ │ │ │ │ + OpenLayers.Util.getParameterString(config.params || {}));
│ │ │ │ │ + url = OpenLayers.Request.makeSameOrigin(url, config.proxy);
│ │ │ │ │ + request.open(
│ │ │ │ │ + config.method, url, config.async, config.user, config.password
│ │ │ │ │ + );
│ │ │ │ │ + for (var header in config.headers) {
│ │ │ │ │ + request.setRequestHeader(header, config.headers[header]);
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: size
│ │ │ │ │ - * {} Size of the main div (this.div)
│ │ │ │ │ - */
│ │ │ │ │ - size: null,
│ │ │ │ │ + var events = this.events;
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: viewPortDiv
│ │ │ │ │ - * {HTMLDivElement} The element that represents the map viewport
│ │ │ │ │ - */
│ │ │ │ │ - viewPortDiv: null,
│ │ │ │ │ + // we want to execute runCallbacks with "this" as the
│ │ │ │ │ + // execution scope
│ │ │ │ │ + var self = this;
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: layerContainerOrigin
│ │ │ │ │ - * {} The lonlat at which the later container was
│ │ │ │ │ - * re-initialized (on-zoom)
│ │ │ │ │ - */
│ │ │ │ │ - layerContainerOrigin: null,
│ │ │ │ │ + request.onreadystatechange = function() {
│ │ │ │ │ + if (request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
│ │ │ │ │ + var proceed = events.triggerEvent(
│ │ │ │ │ + "complete", {
│ │ │ │ │ + request: request,
│ │ │ │ │ + config: config,
│ │ │ │ │ + requestUrl: url
│ │ │ │ │ + }
│ │ │ │ │ + );
│ │ │ │ │ + if (proceed !== false) {
│ │ │ │ │ + self.runCallbacks({
│ │ │ │ │ + request: request,
│ │ │ │ │ + config: config,
│ │ │ │ │ + requestUrl: url
│ │ │ │ │ + });
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + };
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: layerContainerDiv
│ │ │ │ │ - * {HTMLDivElement} The element that contains the layers.
│ │ │ │ │ - */
│ │ │ │ │ - layerContainerDiv: null,
│ │ │ │ │ + // send request (optionally with data) and return
│ │ │ │ │ + // call in a timeout for asynchronous requests so the return is
│ │ │ │ │ + // available before readyState == 4 for cached docs
│ │ │ │ │ + if (config.async === false) {
│ │ │ │ │ + request.send(config.data);
│ │ │ │ │ + } else {
│ │ │ │ │ + window.setTimeout(function() {
│ │ │ │ │ + if (request.readyState !== 0) { // W3C: 0-UNSENT
│ │ │ │ │ + request.send(config.data);
│ │ │ │ │ + }
│ │ │ │ │ + }, 0);
│ │ │ │ │ + }
│ │ │ │ │ + return request;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: layers
│ │ │ │ │ - * {Array()} Ordered list of layers in the map
│ │ │ │ │ + * Method: runCallbacks
│ │ │ │ │ + * Calls the complete, success and failure callbacks. Application
│ │ │ │ │ + * can listen to the "complete" event, have the listener
│ │ │ │ │ + * display a confirm window and always return false, and
│ │ │ │ │ + * execute OpenLayers.Request.runCallbacks if the user
│ │ │ │ │ + * hits "yes" in the confirm window.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * options - {Object} Hash containing request, config and requestUrl keys
│ │ │ │ │ */
│ │ │ │ │ - layers: null,
│ │ │ │ │ + runCallbacks: function(options) {
│ │ │ │ │ + var request = options.request;
│ │ │ │ │ + var config = options.config;
│ │ │ │ │ +
│ │ │ │ │ + // bind callbacks to readyState 4 (done)
│ │ │ │ │ + var complete = (config.scope) ?
│ │ │ │ │ + OpenLayers.Function.bind(config.callback, config.scope) :
│ │ │ │ │ + config.callback;
│ │ │ │ │ +
│ │ │ │ │ + // optional success callback
│ │ │ │ │ + var success;
│ │ │ │ │ + if (config.success) {
│ │ │ │ │ + success = (config.scope) ?
│ │ │ │ │ + OpenLayers.Function.bind(config.success, config.scope) :
│ │ │ │ │ + config.success;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + // optional failure callback
│ │ │ │ │ + var failure;
│ │ │ │ │ + if (config.failure) {
│ │ │ │ │ + failure = (config.scope) ?
│ │ │ │ │ + OpenLayers.Function.bind(config.failure, config.scope) :
│ │ │ │ │ + config.failure;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + if (OpenLayers.Util.createUrlObject(config.url).protocol == "file:" &&
│ │ │ │ │ + request.responseText) {
│ │ │ │ │ + request.status = 200;
│ │ │ │ │ + }
│ │ │ │ │ + complete(request);
│ │ │ │ │ +
│ │ │ │ │ + if (!request.status || (request.status >= 200 && request.status < 300)) {
│ │ │ │ │ + this.events.triggerEvent("success", options);
│ │ │ │ │ + if (success) {
│ │ │ │ │ + success(request);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (request.status && (request.status < 200 || request.status >= 300)) {
│ │ │ │ │ + this.events.triggerEvent("failure", options);
│ │ │ │ │ + if (failure) {
│ │ │ │ │ + failure(request);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: controls
│ │ │ │ │ - * {Array()} List of controls associated with the map.
│ │ │ │ │ + * APIMethod: GET
│ │ │ │ │ + * Send an HTTP GET request. Additional configuration properties are
│ │ │ │ │ + * documented in the method, with the method property set
│ │ │ │ │ + * to GET.
│ │ │ │ │ *
│ │ │ │ │ - * If not provided in the map options at construction, the map will
│ │ │ │ │ - * by default be given the following controls if present in the build:
│ │ │ │ │ - * - or
│ │ │ │ │ - * - or
│ │ │ │ │ - * -
│ │ │ │ │ - * -
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ + * See the method for documentation of allowed properties.
│ │ │ │ │ + * This object is modified and should not be reused.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {XMLHttpRequest} Request object.
│ │ │ │ │ */
│ │ │ │ │ - controls: null,
│ │ │ │ │ + GET: function(config) {
│ │ │ │ │ + config = OpenLayers.Util.extend(config, {
│ │ │ │ │ + method: "GET"
│ │ │ │ │ + });
│ │ │ │ │ + return OpenLayers.Request.issue(config);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: popups
│ │ │ │ │ - * {Array()} List of popups associated with the map
│ │ │ │ │ + * APIMethod: POST
│ │ │ │ │ + * Send a POST request. Additional configuration properties are
│ │ │ │ │ + * documented in the method, with the method property set
│ │ │ │ │ + * to POST and "Content-Type" header set to "application/xml".
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ + * See the method for documentation of allowed properties. The
│ │ │ │ │ + * default "Content-Type" header will be set to "application-xml" if
│ │ │ │ │ + * none is provided. This object is modified and should not be reused.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {XMLHttpRequest} Request object.
│ │ │ │ │ */
│ │ │ │ │ - popups: null,
│ │ │ │ │ + POST: function(config) {
│ │ │ │ │ + config = OpenLayers.Util.extend(config, {
│ │ │ │ │ + method: "POST"
│ │ │ │ │ + });
│ │ │ │ │ + // set content type to application/xml if it isn't already set
│ │ │ │ │ + config.headers = config.headers ? config.headers : {};
│ │ │ │ │ + if (!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) {
│ │ │ │ │ + config.headers["Content-Type"] = "application/xml";
│ │ │ │ │ + }
│ │ │ │ │ + return OpenLayers.Request.issue(config);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: baseLayer
│ │ │ │ │ - * {} The currently selected base layer. This determines
│ │ │ │ │ - * min/max zoom level, projection, etc.
│ │ │ │ │ + * APIMethod: PUT
│ │ │ │ │ + * Send an HTTP PUT request. Additional configuration properties are
│ │ │ │ │ + * documented in the method, with the method property set
│ │ │ │ │ + * to PUT and "Content-Type" header set to "application/xml".
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ + * See the method for documentation of allowed properties. The
│ │ │ │ │ + * default "Content-Type" header will be set to "application-xml" if
│ │ │ │ │ + * none is provided. This object is modified and should not be reused.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {XMLHttpRequest} Request object.
│ │ │ │ │ */
│ │ │ │ │ - baseLayer: null,
│ │ │ │ │ + PUT: function(config) {
│ │ │ │ │ + config = OpenLayers.Util.extend(config, {
│ │ │ │ │ + method: "PUT"
│ │ │ │ │ + });
│ │ │ │ │ + // set content type to application/xml if it isn't already set
│ │ │ │ │ + config.headers = config.headers ? config.headers : {};
│ │ │ │ │ + if (!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) {
│ │ │ │ │ + config.headers["Content-Type"] = "application/xml";
│ │ │ │ │ + }
│ │ │ │ │ + return OpenLayers.Request.issue(config);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: center
│ │ │ │ │ - * {} The current center of the map
│ │ │ │ │ + * APIMethod: DELETE
│ │ │ │ │ + * Send an HTTP DELETE request. Additional configuration properties are
│ │ │ │ │ + * documented in the method, with the method property set
│ │ │ │ │ + * to DELETE.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ + * See the method for documentation of allowed properties.
│ │ │ │ │ + * This object is modified and should not be reused.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {XMLHttpRequest} Request object.
│ │ │ │ │ */
│ │ │ │ │ - center: null,
│ │ │ │ │ + DELETE: function(config) {
│ │ │ │ │ + config = OpenLayers.Util.extend(config, {
│ │ │ │ │ + method: "DELETE"
│ │ │ │ │ + });
│ │ │ │ │ + return OpenLayers.Request.issue(config);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: resolution
│ │ │ │ │ - * {Float} The resolution of the map.
│ │ │ │ │ + * APIMethod: HEAD
│ │ │ │ │ + * Send an HTTP HEAD request. Additional configuration properties are
│ │ │ │ │ + * documented in the method, with the method property set
│ │ │ │ │ + * to HEAD.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ + * See the method for documentation of allowed properties.
│ │ │ │ │ + * This object is modified and should not be reused.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {XMLHttpRequest} Request object.
│ │ │ │ │ */
│ │ │ │ │ - resolution: null,
│ │ │ │ │ + HEAD: function(config) {
│ │ │ │ │ + config = OpenLayers.Util.extend(config, {
│ │ │ │ │ + method: "HEAD"
│ │ │ │ │ + });
│ │ │ │ │ + return OpenLayers.Request.issue(config);
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: zoom
│ │ │ │ │ - * {Integer} The current zoom level of the map
│ │ │ │ │ + * APIMethod: OPTIONS
│ │ │ │ │ + * Send an HTTP OPTIONS request. Additional configuration properties are
│ │ │ │ │ + * documented in the method, with the method property set
│ │ │ │ │ + * to OPTIONS.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * config - {Object} Object with properties for configuring the request.
│ │ │ │ │ + * See the method for documentation of allowed properties.
│ │ │ │ │ + * This object is modified and should not be reused.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {XMLHttpRequest} Request object.
│ │ │ │ │ */
│ │ │ │ │ - zoom: 0,
│ │ │ │ │ + OPTIONS: function(config) {
│ │ │ │ │ + config = OpenLayers.Util.extend(config, {
│ │ │ │ │ + method: "OPTIONS"
│ │ │ │ │ + });
│ │ │ │ │ + return OpenLayers.Request.issue(config);
│ │ │ │ │ + }
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: panRatio
│ │ │ │ │ - * {Float} The ratio of the current extent within
│ │ │ │ │ - * which panning will tween.
│ │ │ │ │ - */
│ │ │ │ │ - panRatio: 1.5,
│ │ │ │ │ +});
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Feature.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: options
│ │ │ │ │ - * {Object} The options object passed to the class constructor. Read-only.
│ │ │ │ │ - */
│ │ │ │ │ - options: null,
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │
│ │ │ │ │ - // Options
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: tileSize
│ │ │ │ │ - * {} Set in the map options to override the default tile
│ │ │ │ │ - * size for this map.
│ │ │ │ │ - */
│ │ │ │ │ - tileSize: null,
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + * @requires OpenLayers/Util.js
│ │ │ │ │ + */
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: projection
│ │ │ │ │ - * {String} Set in the map options to specify the default projection
│ │ │ │ │ - * for layers added to this map. When using a projection other than EPSG:4326
│ │ │ │ │ - * (CRS:84, Geographic) or EPSG:3857 (EPSG:900913, Web Mercator),
│ │ │ │ │ - * also set maxExtent, maxResolution or resolutions. Default is "EPSG:4326".
│ │ │ │ │ - * Note that the projection of the map is usually determined
│ │ │ │ │ - * by that of the current baseLayer (see and ).
│ │ │ │ │ - */
│ │ │ │ │ - projection: "EPSG:4326",
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Feature
│ │ │ │ │ + * Features are combinations of geography and attributes. The OpenLayers.Feature
│ │ │ │ │ + * class specifically combines a marker and a lonlat.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Feature = OpenLayers.Class({
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: layer
│ │ │ │ │ + * {}
│ │ │ │ │ */
│ │ │ │ │ - units: null,
│ │ │ │ │ + layer: 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.).
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: id
│ │ │ │ │ + * {String}
│ │ │ │ │ */
│ │ │ │ │ - resolutions: null,
│ │ │ │ │ + id: null,
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: maxResolution
│ │ │ │ │ - * {Float} Required if you are not displaying the whole world on a tile
│ │ │ │ │ - * with the size specified in .
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: lonlat
│ │ │ │ │ + * {}
│ │ │ │ │ */
│ │ │ │ │ - maxResolution: null,
│ │ │ │ │ + lonlat: null,
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: minResolution
│ │ │ │ │ - * {Float}
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: data
│ │ │ │ │ + * {Object}
│ │ │ │ │ */
│ │ │ │ │ - minResolution: null,
│ │ │ │ │ + data: null,
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: maxScale
│ │ │ │ │ - * {Float}
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: marker
│ │ │ │ │ + * {}
│ │ │ │ │ */
│ │ │ │ │ - maxScale: null,
│ │ │ │ │ + marker: null,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: minScale
│ │ │ │ │ - * {Float}
│ │ │ │ │ + * APIProperty: popupClass
│ │ │ │ │ + * {} The class which will be used to instantiate
│ │ │ │ │ + * a new Popup. Default is .
│ │ │ │ │ */
│ │ │ │ │ - minScale: null,
│ │ │ │ │ + popupClass: null,
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: maxExtent
│ │ │ │ │ - * {|Array} If provided as an array, the array
│ │ │ │ │ - * should consist of four values (left, bottom, right, top).
│ │ │ │ │ - * The maximum extent for the map.
│ │ │ │ │ - * Default depends on projection; if this is one of those defined in OpenLayers.Projection.defaults
│ │ │ │ │ - * (EPSG:4326 or web mercator), maxExtent will be set to the value defined there;
│ │ │ │ │ - * else, defaults to null.
│ │ │ │ │ - * To restrict user panning and zooming of the map, use instead.
│ │ │ │ │ - * The value for will change calculations for tile URLs.
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: popup
│ │ │ │ │ + * {}
│ │ │ │ │ */
│ │ │ │ │ - maxExtent: null,
│ │ │ │ │ + popup: null,
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: minExtent
│ │ │ │ │ - * {|Array} If provided as an array, the array
│ │ │ │ │ - * should consist of four values (left, bottom, right, top).
│ │ │ │ │ - * The minimum extent for the map. Defaults to null.
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Feature
│ │ │ │ │ + * Constructor for features.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * layer - {}
│ │ │ │ │ + * lonlat - {}
│ │ │ │ │ + * data - {Object}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {}
│ │ │ │ │ */
│ │ │ │ │ - minExtent: null,
│ │ │ │ │ + initialize: function(layer, lonlat, data) {
│ │ │ │ │ + this.layer = layer;
│ │ │ │ │ + this.lonlat = lonlat;
│ │ │ │ │ + this.data = (data != null) ? data : {};
│ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: restrictedExtent
│ │ │ │ │ - * {|Array} If provided as an array, the array
│ │ │ │ │ - * should consist of four values (left, bottom, right, top).
│ │ │ │ │ - * Limit map navigation to this extent where possible.
│ │ │ │ │ - * If a non-null restrictedExtent is set, panning will be restricted
│ │ │ │ │ - * to the given bounds. In addition, zooming to a resolution that
│ │ │ │ │ - * displays more than the restricted extent will center the map
│ │ │ │ │ - * on the restricted extent. If you wish to limit the zoom level
│ │ │ │ │ - * or resolution, use maxResolution.
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: destroy
│ │ │ │ │ + * nullify references to prevent circular references and memory leaks
│ │ │ │ │ */
│ │ │ │ │ - restrictedExtent: null,
│ │ │ │ │ + destroy: function() {
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * 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,
│ │ │ │ │ + //remove the popup from the map
│ │ │ │ │ + if ((this.layer != null) && (this.layer.map != null)) {
│ │ │ │ │ + if (this.popup != null) {
│ │ │ │ │ + this.layer.map.removePopup(this.popup);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + // remove the marker from the layer
│ │ │ │ │ + if (this.layer != null && this.marker != null) {
│ │ │ │ │ + this.layer.removeMarker(this.marker);
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + this.layer = null;
│ │ │ │ │ + this.id = null;
│ │ │ │ │ + this.lonlat = null;
│ │ │ │ │ + this.data = null;
│ │ │ │ │ + if (this.marker != null) {
│ │ │ │ │ + this.destroyMarker(this.marker);
│ │ │ │ │ + this.marker = null;
│ │ │ │ │ + }
│ │ │ │ │ + if (this.popup != null) {
│ │ │ │ │ + this.destroyPopup(this.popup);
│ │ │ │ │ + this.popup = null;
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * 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.
│ │ │ │ │ + * Method: onScreen
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} Whether or not the feature is currently visible on screen
│ │ │ │ │ + * (based on its 'lonlat' property)
│ │ │ │ │ */
│ │ │ │ │ - theme: null,
│ │ │ │ │ + onScreen: function() {
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: displayProjection
│ │ │ │ │ - * {} Requires proj4js support for projections other
│ │ │ │ │ - * than EPSG:4326 or EPSG:900913/EPSG:3857. Projection used by
│ │ │ │ │ - * several controls to display data to user. If this property is set,
│ │ │ │ │ - * it will be set on any control which has a null displayProjection
│ │ │ │ │ - * property at the time the control is added to the map.
│ │ │ │ │ - */
│ │ │ │ │ - displayProjection: null,
│ │ │ │ │ + var onScreen = false;
│ │ │ │ │ + if ((this.layer != null) && (this.layer.map != null)) {
│ │ │ │ │ + var screenBounds = this.layer.map.getExtent();
│ │ │ │ │ + onScreen = screenBounds.containsLonLat(this.lonlat);
│ │ │ │ │ + }
│ │ │ │ │ + return onScreen;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: tileManager
│ │ │ │ │ - * {|Object} By default, and if the build contains
│ │ │ │ │ - * TileManager.js, the map will use the TileManager to queue image requests
│ │ │ │ │ - * and to cache tile image elements. To create a map without a TileManager
│ │ │ │ │ - * configure the map with tileManager: null. To create a TileManager with
│ │ │ │ │ - * non-default options, supply the options instead or alternatively supply
│ │ │ │ │ - * an instance of {}.
│ │ │ │ │ - */
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: fallThrough
│ │ │ │ │ - * {Boolean} Should OpenLayers allow events on the map to fall through to
│ │ │ │ │ - * other elements on the page, or should it swallow them? (#457)
│ │ │ │ │ - * Default is to swallow.
│ │ │ │ │ + * Method: createMarker
│ │ │ │ │ + * Based on the data associated with the Feature, create and return a marker object.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} A Marker Object created from the 'lonlat' and 'icon' properties
│ │ │ │ │ + * set in this.data. If no 'lonlat' is set, returns null. If no
│ │ │ │ │ + * 'icon' is set, OpenLayers.Marker() will load the default image.
│ │ │ │ │ + *
│ │ │ │ │ + * Note - this.marker is set to return value
│ │ │ │ │ + *
│ │ │ │ │ */
│ │ │ │ │ - fallThrough: false,
│ │ │ │ │ + createMarker: function() {
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * APIProperty: autoUpdateSize
│ │ │ │ │ - * {Boolean} Should OpenLayers automatically update the size of the map
│ │ │ │ │ - * when the resize event is fired. Default is true.
│ │ │ │ │ - */
│ │ │ │ │ - autoUpdateSize: true,
│ │ │ │ │ + if (this.lonlat != null) {
│ │ │ │ │ + this.marker = new OpenLayers.Marker(this.lonlat, this.data.icon);
│ │ │ │ │ + }
│ │ │ │ │ + return this.marker;
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * APIProperty: eventListeners
│ │ │ │ │ - * {Object} If set as an option at construction, the eventListeners
│ │ │ │ │ - * object will be registered with . Object
│ │ │ │ │ - * structure must be a listeners object as shown in the example for
│ │ │ │ │ - * the events.on method.
│ │ │ │ │ + * Method: destroyMarker
│ │ │ │ │ + * Destroys marker.
│ │ │ │ │ + * If user overrides the createMarker() function, s/he should be able
│ │ │ │ │ + * to also specify an alternative function for destroying it
│ │ │ │ │ */
│ │ │ │ │ - eventListeners: null,
│ │ │ │ │ + destroyMarker: function() {
│ │ │ │ │ + this.marker.destroy();
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: panTween
│ │ │ │ │ - * {} Animated panning tween object, see panTo()
│ │ │ │ │ + * Method: createPopup
│ │ │ │ │ + * Creates a popup object created from the 'lonlat', 'popupSize',
│ │ │ │ │ + * and 'popupContentHTML' properties set in this.data. It uses
│ │ │ │ │ + * this.marker.icon as default anchor.
│ │ │ │ │ + *
│ │ │ │ │ + * If no 'lonlat' is set, returns null.
│ │ │ │ │ + * If no this.marker has been created, no anchor is sent.
│ │ │ │ │ + *
│ │ │ │ │ + * Note - the returned popup object is 'owned' by the feature, so you
│ │ │ │ │ + * cannot use the popup's destroy method to discard the popup.
│ │ │ │ │ + * Instead, you must use the feature's destroyPopup
│ │ │ │ │ + *
│ │ │ │ │ + * Note - this.popup is set to return value
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * closeBox - {Boolean} create popup with closebox or not
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} Returns the created popup, which is also set
│ │ │ │ │ + * as 'popup' property of this feature. Will be of whatever type
│ │ │ │ │ + * specified by this feature's 'popupClass' property, but must be
│ │ │ │ │ + * of type .
│ │ │ │ │ + *
│ │ │ │ │ */
│ │ │ │ │ - panTween: null,
│ │ │ │ │ + createPopup: function(closeBox) {
│ │ │ │ │ +
│ │ │ │ │ + if (this.lonlat != null) {
│ │ │ │ │ + if (!this.popup) {
│ │ │ │ │ + var anchor = (this.marker) ? this.marker.icon : null;
│ │ │ │ │ + var popupClass = this.popupClass ?
│ │ │ │ │ + this.popupClass : OpenLayers.Popup.Anchored;
│ │ │ │ │ + this.popup = new popupClass(this.id + "_popup",
│ │ │ │ │ + this.lonlat,
│ │ │ │ │ + this.data.popupSize,
│ │ │ │ │ + this.data.popupContentHTML,
│ │ │ │ │ + anchor,
│ │ │ │ │ + closeBox);
│ │ │ │ │ + }
│ │ │ │ │ + if (this.data.overflow != null) {
│ │ │ │ │ + this.popup.contentDiv.style.overflow = this.data.overflow;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + this.popup.feature = this;
│ │ │ │ │ + }
│ │ │ │ │ + return this.popup;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * 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.
│ │ │ │ │ + * Method: destroyPopup
│ │ │ │ │ + * Destroys the popup created via createPopup.
│ │ │ │ │ + *
│ │ │ │ │ + * As with the marker, if user overrides the createPopup() function, s/he
│ │ │ │ │ + * should also be able to override the destruction
│ │ │ │ │ */
│ │ │ │ │ - panMethod: OpenLayers.Easing.Expo.easeOut,
│ │ │ │ │ + destroyPopup: function() {
│ │ │ │ │ + if (this.popup) {
│ │ │ │ │ + this.popup.feature = null;
│ │ │ │ │ + this.popup.destroy();
│ │ │ │ │ + this.popup = null;
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: panDuration
│ │ │ │ │ - * {Integer} The number of steps to be passed to the
│ │ │ │ │ - * OpenLayers.Tween.start() method when the map is
│ │ │ │ │ - * panned.
│ │ │ │ │ - * Default is 50.
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Feature"
│ │ │ │ │ +});
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Feature/Vector.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +// TRASH THIS
│ │ │ │ │ +OpenLayers.State = {
│ │ │ │ │ + /** states */
│ │ │ │ │ + UNKNOWN: 'Unknown',
│ │ │ │ │ + INSERT: 'Insert',
│ │ │ │ │ + UPDATE: 'Update',
│ │ │ │ │ + DELETE: 'Delete'
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/Feature.js
│ │ │ │ │ + * @requires OpenLayers/Util.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Feature.Vector
│ │ │ │ │ + * Vector features use the OpenLayers.Geometry classes as geometry description.
│ │ │ │ │ + * They have an 'attributes' property, which is the data object, and a 'style'
│ │ │ │ │ + * property, the default values of which are defined in the
│ │ │ │ │ + * objects.
│ │ │ │ │ + *
│ │ │ │ │ + * Inherits from:
│ │ │ │ │ + * -
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Feature.Vector = OpenLayers.Class(OpenLayers.Feature, {
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: fid
│ │ │ │ │ + * {String}
│ │ │ │ │ */
│ │ │ │ │ - panDuration: 50,
│ │ │ │ │ + fid: null,
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: zoomTween
│ │ │ │ │ - * {} Animated zooming tween object, see zoomTo()
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: geometry
│ │ │ │ │ + * {}
│ │ │ │ │ */
│ │ │ │ │ - zoomTween: null,
│ │ │ │ │ + geometry: 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.
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: attributes
│ │ │ │ │ + * {Object} This object holds arbitrary, serializable properties that
│ │ │ │ │ + * describe the feature.
│ │ │ │ │ */
│ │ │ │ │ - zoomMethod: OpenLayers.Easing.Quad.easeOut,
│ │ │ │ │ + attributes: null,
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Property: zoomDuration
│ │ │ │ │ - * {Integer} The number of steps to be passed to the
│ │ │ │ │ - * OpenLayers.Tween.start() method when the map is zoomed.
│ │ │ │ │ - * Default is 20.
│ │ │ │ │ + * Property: bounds
│ │ │ │ │ + * {} The box bounding that feature's geometry, that
│ │ │ │ │ + * property can be set by an object when
│ │ │ │ │ + * deserializing the feature, so in most cases it represents an
│ │ │ │ │ + * information set by the server.
│ │ │ │ │ */
│ │ │ │ │ - zoomDuration: 20,
│ │ │ │ │ + bounds: null,
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: paddingForPopups
│ │ │ │ │ - * {} Outside margin of the popup. Used to prevent
│ │ │ │ │ - * the popup from getting too close to the map border.
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: state
│ │ │ │ │ + * {String}
│ │ │ │ │ */
│ │ │ │ │ - paddingForPopups: null,
│ │ │ │ │ + state: null,
│ │ │ │ │
│ │ │ │ │ - /**
│ │ │ │ │ - * Property: layerContainerOriginPx
│ │ │ │ │ - * {Object} Cached object representing the layer container origin (in pixels).
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: style
│ │ │ │ │ + * {Object}
│ │ │ │ │ */
│ │ │ │ │ - layerContainerOriginPx: null,
│ │ │ │ │ + style: 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.
│ │ │ │ │ + * APIProperty: url
│ │ │ │ │ + * {String} If this property is set it will be taken into account by
│ │ │ │ │ + * {} when upadting or deleting the feature.
│ │ │ │ │ */
│ │ │ │ │ - minPx: null,
│ │ │ │ │ + url: 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.
│ │ │ │ │ + * Property: renderIntent
│ │ │ │ │ + * {String} rendering intent currently being used
│ │ │ │ │ */
│ │ │ │ │ - maxPx: null,
│ │ │ │ │ + renderIntent: "default",
│ │ │ │ │
│ │ │ │ │ /**
│ │ │ │ │ - * Constructor: OpenLayers.Map
│ │ │ │ │ - * Constructor for a new OpenLayers.Map instance. There are two possible
│ │ │ │ │ - * ways to call the map constructor. See the examples below.
│ │ │ │ │ - *
│ │ │ │ │ - * Parameters:
│ │ │ │ │ - * div - {DOMElement|String} The element or id of an element in your page
│ │ │ │ │ - * that will contain the map. May be omitted if the option is
│ │ │ │ │ - * provided or if you intend to call the
method later.
│ │ │ │ │ - * options - {Object} Optional object with properties to tag onto the map.
│ │ │ │ │ + * APIProperty: modified
│ │ │ │ │ + * {Object} An object with the originals of the geometry and attributes of
│ │ │ │ │ + * the feature, if they were changed. Currently this property is only read
│ │ │ │ │ + * by , and written by
│ │ │ │ │ + * , which sets the geometry property.
│ │ │ │ │ + * Applications can set the originals of modified attributes in the
│ │ │ │ │ + * attributes property. Note that applications have to check if this
│ │ │ │ │ + * object and the attributes property is already created before using it.
│ │ │ │ │ + * After a change made with ModifyFeature, this object could look like
│ │ │ │ │ *
│ │ │ │ │ - * Valid options (in addition to the listed API properties):
│ │ │ │ │ - * center - {|Array} The default initial center of the map.
│ │ │ │ │ - * If provided as array, the first value is the x coordinate,
│ │ │ │ │ - * and the 2nd value is the y coordinate.
│ │ │ │ │ - * Only specify if is provided.
│ │ │ │ │ - * Note that if an ArgParser/Permalink control is present,
│ │ │ │ │ - * and the querystring contains coordinates, center will be set
│ │ │ │ │ - * by that, and this option will be ignored.
│ │ │ │ │ - * zoom - {Number} The initial zoom level for the map. Only specify if
│ │ │ │ │ - * is provided.
│ │ │ │ │ - * Note that if an ArgParser/Permalink control is present,
│ │ │ │ │ - * and the querystring contains a zoom level, zoom will be set
│ │ │ │ │ - * by that, and this option will be ignored.
│ │ │ │ │ - * extent - {|Array} The initial extent of the map.
│ │ │ │ │ - * If provided as an array, the array should consist of
│ │ │ │ │ - * four values (left, bottom, right, top).
│ │ │ │ │ - * Only specify if and are not provided.
│ │ │ │ │ - *
│ │ │ │ │ - * Examples:
│ │ │ │ │ * (code)
│ │ │ │ │ - * // create a map with default options in an element with the id "map1"
│ │ │ │ │ - * var map = new OpenLayers.Map("map1");
│ │ │ │ │ + * {
│ │ │ │ │ + * geometry: >Object
│ │ │ │ │ + * }
│ │ │ │ │ + * (end)
│ │ │ │ │ *
│ │ │ │ │ - * // 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);
│ │ │ │ │ + * When an application has made changes to feature attributes, it could
│ │ │ │ │ + * have set the attributes to something like this:
│ │ │ │ │ *
│ │ │ │ │ - * // 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({
│ │ │ │ │ + * (code)
│ │ │ │ │ + * {
│ │ │ │ │ + * attributes: {
│ │ │ │ │ + * myAttribute: "original"
│ │ │ │ │ + * }
│ │ │ │ │ + * }
│ │ │ │ │ + * (end)
│ │ │ │ │ + *
│ │ │ │ │ + * Note that only checks for truthy values in
│ │ │ │ │ + * *modified.geometry* and the attribute names in *modified.attributes*,
│ │ │ │ │ + * but it is recommended to set the original values (and not just true) as
│ │ │ │ │ + * attribute value, so applications could use this information to undo
│ │ │ │ │ + * changes.
│ │ │ │ │ + */
│ │ │ │ │ + modified: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Feature.Vector
│ │ │ │ │ + * Create a vector feature.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * geometry - {} The geometry that this feature
│ │ │ │ │ + * represents.
│ │ │ │ │ + * attributes - {Object} An optional object that will be mapped to the
│ │ │ │ │ + * property.
│ │ │ │ │ + * style - {Object} An optional style object.
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(geometry, attributes, style) {
│ │ │ │ │ + OpenLayers.Feature.prototype.initialize.apply(this,
│ │ │ │ │ + [null, null, attributes]);
│ │ │ │ │ + this.lonlat = null;
│ │ │ │ │ + this.geometry = geometry ? geometry : null;
│ │ │ │ │ + this.state = null;
│ │ │ │ │ + this.attributes = {};
│ │ │ │ │ + if (attributes) {
│ │ │ │ │ + this.attributes = OpenLayers.Util.extend(this.attributes,
│ │ │ │ │ + attributes);
│ │ │ │ │ + }
│ │ │ │ │ + this.style = style ? style : null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: destroy
│ │ │ │ │ + * nullify references to prevent circular references and memory leaks
│ │ │ │ │ + */
│ │ │ │ │ + destroy: function() {
│ │ │ │ │ + if (this.layer) {
│ │ │ │ │ + this.layer.removeFeatures(this);
│ │ │ │ │ + this.layer = null;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + this.geometry = null;
│ │ │ │ │ + this.modified = null;
│ │ │ │ │ + OpenLayers.Feature.prototype.destroy.apply(this, arguments);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: clone
│ │ │ │ │ + * Create a clone of this vector feature. Does not set any non-standard
│ │ │ │ │ + * properties.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} An exact clone of this vector feature.
│ │ │ │ │ + */
│ │ │ │ │ + clone: function() {
│ │ │ │ │ + return new OpenLayers.Feature.Vector(
│ │ │ │ │ + this.geometry ? this.geometry.clone() : null,
│ │ │ │ │ + this.attributes,
│ │ │ │ │ + this.style);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: onScreen
│ │ │ │ │ + * Determine whether the feature is within the map viewport. This method
│ │ │ │ │ + * tests for an intersection between the geometry and the viewport
│ │ │ │ │ + * bounds. If a more effecient but less precise geometry bounds
│ │ │ │ │ + * intersection is desired, call the method with the boundsOnly
│ │ │ │ │ + * parameter true.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * boundsOnly - {Boolean} Only test whether a feature's bounds intersects
│ │ │ │ │ + * the viewport bounds. Default is false. If false, the feature's
│ │ │ │ │ + * geometry must intersect the viewport for onScreen to return true.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The feature is currently visible on screen (optionally
│ │ │ │ │ + * based on its bounds if boundsOnly is true).
│ │ │ │ │ + */
│ │ │ │ │ + onScreen: function(boundsOnly) {
│ │ │ │ │ + var onScreen = false;
│ │ │ │ │ + if (this.layer && this.layer.map) {
│ │ │ │ │ + var screenBounds = this.layer.map.getExtent();
│ │ │ │ │ + if (boundsOnly) {
│ │ │ │ │ + var featureBounds = this.geometry.getBounds();
│ │ │ │ │ + onScreen = screenBounds.intersectsBounds(featureBounds);
│ │ │ │ │ + } else {
│ │ │ │ │ + var screenPoly = screenBounds.toGeometry();
│ │ │ │ │ + onScreen = screenPoly.intersects(this.geometry);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return onScreen;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: getVisibility
│ │ │ │ │ + * Determine whether the feature is displayed or not. It may not displayed
│ │ │ │ │ + * because:
│ │ │ │ │ + * - its style display property is set to 'none',
│ │ │ │ │ + * - it doesn't belong to any layer,
│ │ │ │ │ + * - the styleMap creates a symbolizer with display property set to 'none'
│ │ │ │ │ + * for it,
│ │ │ │ │ + * - the layer which it belongs to is not visible.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The feature is currently displayed.
│ │ │ │ │ + */
│ │ │ │ │ + getVisibility: function() {
│ │ │ │ │ + return !(this.style && this.style.display == 'none' ||
│ │ │ │ │ + !this.layer ||
│ │ │ │ │ + this.layer && this.layer.styleMap &&
│ │ │ │ │ + this.layer.styleMap.createSymbolizer(this, this.renderIntent).display == 'none' ||
│ │ │ │ │ + this.layer && !this.layer.getVisibility());
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: createMarker
│ │ │ │ │ + * HACK - we need to decide if all vector features should be able to
│ │ │ │ │ + * create markers
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} For now just returns null
│ │ │ │ │ + */
│ │ │ │ │ + createMarker: function() {
│ │ │ │ │ + return null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: destroyMarker
│ │ │ │ │ + * HACK - we need to decide if all vector features should be able to
│ │ │ │ │ + * delete markers
│ │ │ │ │ + *
│ │ │ │ │ + * If user overrides the createMarker() function, s/he should be able
│ │ │ │ │ + * to also specify an alternative function for destroying it
│ │ │ │ │ + */
│ │ │ │ │ + destroyMarker: function() {
│ │ │ │ │ + // pass
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: createPopup
│ │ │ │ │ + * HACK - we need to decide if all vector features should be able to
│ │ │ │ │ + * create popups
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} For now just returns null
│ │ │ │ │ + */
│ │ │ │ │ + createPopup: function() {
│ │ │ │ │ + return null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: atPoint
│ │ │ │ │ + * Determins whether the feature intersects with the specified location.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * lonlat - {|Object} OpenLayers.LonLat or an
│ │ │ │ │ + * object with a 'lon' and 'lat' properties.
│ │ │ │ │ + * toleranceLon - {float} Optional tolerance in Geometric Coords
│ │ │ │ │ + * toleranceLat - {float} Optional tolerance in Geographic Coords
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} Whether or not the feature is at the specified location
│ │ │ │ │ + */
│ │ │ │ │ + atPoint: function(lonlat, toleranceLon, toleranceLat) {
│ │ │ │ │ + var atPoint = false;
│ │ │ │ │ + if (this.geometry) {
│ │ │ │ │ + atPoint = this.geometry.atPoint(lonlat, toleranceLon,
│ │ │ │ │ + toleranceLat);
│ │ │ │ │ + }
│ │ │ │ │ + return atPoint;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: destroyPopup
│ │ │ │ │ + * HACK - we need to decide if all vector features should be able to
│ │ │ │ │ + * delete popups
│ │ │ │ │ + */
│ │ │ │ │ + destroyPopup: function() {
│ │ │ │ │ + // pass
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: move
│ │ │ │ │ + * Moves the feature and redraws it at its new location
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * location - { or } the
│ │ │ │ │ + * location to which to move the feature.
│ │ │ │ │ + */
│ │ │ │ │ + move: function(location) {
│ │ │ │ │ +
│ │ │ │ │ + if (!this.layer || !this.geometry.move) {
│ │ │ │ │ + //do nothing if no layer or immoveable geometry
│ │ │ │ │ + return undefined;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + var pixel;
│ │ │ │ │ + if (location.CLASS_NAME == "OpenLayers.LonLat") {
│ │ │ │ │ + pixel = this.layer.getViewPortPxFromLonLat(location);
│ │ │ │ │ + } else {
│ │ │ │ │ + pixel = location;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + var lastPixel = this.layer.getViewPortPxFromLonLat(this.geometry.getBounds().getCenterLonLat());
│ │ │ │ │ + var res = this.layer.map.getResolution();
│ │ │ │ │ + this.geometry.move(res * (pixel.x - lastPixel.x),
│ │ │ │ │ + res * (lastPixel.y - pixel.y));
│ │ │ │ │ + this.layer.drawFeature(this);
│ │ │ │ │ + return lastPixel;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: toState
│ │ │ │ │ + * Sets the new state
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * state - {String}
│ │ │ │ │ + */
│ │ │ │ │ + toState: function(state) {
│ │ │ │ │ + if (state == OpenLayers.State.UPDATE) {
│ │ │ │ │ + switch (this.state) {
│ │ │ │ │ + case OpenLayers.State.UNKNOWN:
│ │ │ │ │ + case OpenLayers.State.DELETE:
│ │ │ │ │ + this.state = state;
│ │ │ │ │ + break;
│ │ │ │ │ + case OpenLayers.State.UPDATE:
│ │ │ │ │ + case OpenLayers.State.INSERT:
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + } else if (state == OpenLayers.State.INSERT) {
│ │ │ │ │ + switch (this.state) {
│ │ │ │ │ + case OpenLayers.State.UNKNOWN:
│ │ │ │ │ + break;
│ │ │ │ │ + default:
│ │ │ │ │ + this.state = state;
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + } else if (state == OpenLayers.State.DELETE) {
│ │ │ │ │ + switch (this.state) {
│ │ │ │ │ + case OpenLayers.State.INSERT:
│ │ │ │ │ + // the feature should be destroyed
│ │ │ │ │ + break;
│ │ │ │ │ + case OpenLayers.State.DELETE:
│ │ │ │ │ + break;
│ │ │ │ │ + case OpenLayers.State.UNKNOWN:
│ │ │ │ │ + case OpenLayers.State.UPDATE:
│ │ │ │ │ + this.state = state;
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + } else if (state == OpenLayers.State.UNKNOWN) {
│ │ │ │ │ + this.state = state;
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Feature.Vector"
│ │ │ │ │ +});
│ │ │ │ │ +
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Constant: OpenLayers.Feature.Vector.style
│ │ │ │ │ + * OpenLayers features can have a number of style attributes. The 'default'
│ │ │ │ │ + * style will typically be used if no other style is specified. These
│ │ │ │ │ + * styles correspond for the most part, to the styling properties defined
│ │ │ │ │ + * by the SVG standard.
│ │ │ │ │ + * Information on fill properties: http://www.w3.org/TR/SVG/painting.html#FillProperties
│ │ │ │ │ + * Information on stroke properties: http://www.w3.org/TR/SVG/painting.html#StrokeProperties
│ │ │ │ │ + *
│ │ │ │ │ + * Symbolizer properties:
│ │ │ │ │ + * fill - {Boolean} Set to false if no fill is desired.
│ │ │ │ │ + * fillColor - {String} Hex fill color. Default is "#ee9900".
│ │ │ │ │ + * fillOpacity - {Number} Fill opacity (0-1). Default is 0.4
│ │ │ │ │ + * stroke - {Boolean} Set to false if no stroke is desired.
│ │ │ │ │ + * strokeColor - {String} Hex stroke color. Default is "#ee9900".
│ │ │ │ │ + * strokeOpacity - {Number} Stroke opacity (0-1). Default is 1.
│ │ │ │ │ + * strokeWidth - {Number} Pixel stroke width. Default is 1.
│ │ │ │ │ + * strokeLinecap - {String} Stroke cap type. Default is "round". [butt | round | square]
│ │ │ │ │ + * strokeDashstyle - {String} Stroke dash style. Default is "solid". [dot | dash | dashdot | longdash | longdashdot | solid]
│ │ │ │ │ + * graphic - {Boolean} Set to false if no graphic is desired.
│ │ │ │ │ + * pointRadius - {Number} Pixel point radius. Default is 6.
│ │ │ │ │ + * pointerEvents - {String} Default is "visiblePainted".
│ │ │ │ │ + * cursor - {String} Default is "".
│ │ │ │ │ + * externalGraphic - {String} Url to an external graphic that will be used for rendering points.
│ │ │ │ │ + * graphicWidth - {Number} Pixel width for sizing an external graphic.
│ │ │ │ │ + * graphicHeight - {Number} Pixel height for sizing an external graphic.
│ │ │ │ │ + * graphicOpacity - {Number} Opacity (0-1) for an external graphic.
│ │ │ │ │ + * graphicXOffset - {Number} Pixel offset along the positive x axis for displacing an external graphic.
│ │ │ │ │ + * graphicYOffset - {Number} Pixel offset along the positive y axis for displacing an external graphic.
│ │ │ │ │ + * rotation - {Number} For point symbolizers, this is the rotation of a graphic in the clockwise direction about its center point (or any point off center as specified by graphicXOffset and graphicYOffset).
│ │ │ │ │ + * graphicZIndex - {Number} The integer z-index value to use in rendering.
│ │ │ │ │ + * graphicName - {String} Named graphic to use when rendering points. Supported values include "circle" (default),
│ │ │ │ │ + * "square", "star", "x", "cross", "triangle".
│ │ │ │ │ + * graphicTitle - {String} Tooltip when hovering over a feature. *deprecated*, use title instead
│ │ │ │ │ + * title - {String} Tooltip when hovering over a feature. Not supported by the canvas renderer.
│ │ │ │ │ + * backgroundGraphic - {String} Url to a graphic to be used as the background under an externalGraphic.
│ │ │ │ │ + * backgroundGraphicZIndex - {Number} The integer z-index value to use in rendering the background graphic.
│ │ │ │ │ + * backgroundXOffset - {Number} The x offset (in pixels) for the background graphic.
│ │ │ │ │ + * backgroundYOffset - {Number} The y offset (in pixels) for the background graphic.
│ │ │ │ │ + * backgroundHeight - {Number} The height of the background graphic. If not provided, the graphicHeight will be used.
│ │ │ │ │ + * backgroundWidth - {Number} The width of the background width. If not provided, the graphicWidth will be used.
│ │ │ │ │ + * label - {String} The text for an optional label. For browsers that use the canvas renderer, this requires either
│ │ │ │ │ + * fillText or mozDrawText to be available.
│ │ │ │ │ + * labelAlign - {String} Label alignment. This specifies the insertion point relative to the text. It is a string
│ │ │ │ │ + * composed of two characters. The first character is for the horizontal alignment, the second for the vertical
│ │ │ │ │ + * alignment. Valid values for horizontal alignment: "l"=left, "c"=center, "r"=right. Valid values for vertical
│ │ │ │ │ + * alignment: "t"=top, "m"=middle, "b"=bottom. Example values: "lt", "cm", "rb". Default is "cm".
│ │ │ │ │ + * labelXOffset - {Number} Pixel offset along the positive x axis for displacing the label. Not supported by the canvas renderer.
│ │ │ │ │ + * labelYOffset - {Number} Pixel offset along the positive y axis for displacing the label. Not supported by the canvas renderer.
│ │ │ │ │ + * labelSelect - {Boolean} If set to true, labels will be selectable using SelectFeature or similar controls.
│ │ │ │ │ + * Default is false.
│ │ │ │ │ + * labelOutlineColor - {String} The color of the label outline. Default is 'white'. Only supported by the canvas & SVG renderers.
│ │ │ │ │ + * labelOutlineWidth - {Number} The width of the label outline. Default is 3, set to 0 or null to disable. Only supported by the SVG renderers.
│ │ │ │ │ + * labelOutlineOpacity - {Number} The opacity (0-1) of the label outline. Default is fontOpacity. Only supported by the canvas & SVG renderers.
│ │ │ │ │ + * fontColor - {String} The font color for the label, to be provided like CSS.
│ │ │ │ │ + * fontOpacity - {Number} Opacity (0-1) for the label
│ │ │ │ │ + * fontFamily - {String} The font family for the label, to be provided like in CSS.
│ │ │ │ │ + * fontSize - {String} The font size for the label, to be provided like in CSS.
│ │ │ │ │ + * fontStyle - {String} The font style for the label, to be provided like in CSS.
│ │ │ │ │ + * fontWeight - {String} The font weight for the label, to be provided like in CSS.
│ │ │ │ │ + * display - {String} Symbolizers will have no effect if display is set to "none". All other values have no effect.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Feature.Vector.style = {
│ │ │ │ │ + 'default': {
│ │ │ │ │ + fillColor: "#ee9900",
│ │ │ │ │ + fillOpacity: 0.4,
│ │ │ │ │ + hoverFillColor: "white",
│ │ │ │ │ + hoverFillOpacity: 0.8,
│ │ │ │ │ + strokeColor: "#ee9900",
│ │ │ │ │ + strokeOpacity: 1,
│ │ │ │ │ + strokeWidth: 1,
│ │ │ │ │ + strokeLinecap: "round",
│ │ │ │ │ + strokeDashstyle: "solid",
│ │ │ │ │ + hoverStrokeColor: "red",
│ │ │ │ │ + hoverStrokeOpacity: 1,
│ │ │ │ │ + hoverStrokeWidth: 0.2,
│ │ │ │ │ + pointRadius: 6,
│ │ │ │ │ + hoverPointRadius: 1,
│ │ │ │ │ + hoverPointUnit: "%",
│ │ │ │ │ + pointerEvents: "visiblePainted",
│ │ │ │ │ + cursor: "inherit",
│ │ │ │ │ + fontColor: "#000000",
│ │ │ │ │ + labelAlign: "cm",
│ │ │ │ │ + labelOutlineColor: "white",
│ │ │ │ │ + labelOutlineWidth: 3
│ │ │ │ │ + },
│ │ │ │ │ + 'select': {
│ │ │ │ │ + fillColor: "blue",
│ │ │ │ │ + fillOpacity: 0.4,
│ │ │ │ │ + hoverFillColor: "white",
│ │ │ │ │ + hoverFillOpacity: 0.8,
│ │ │ │ │ + strokeColor: "blue",
│ │ │ │ │ + strokeOpacity: 1,
│ │ │ │ │ + strokeWidth: 2,
│ │ │ │ │ + strokeLinecap: "round",
│ │ │ │ │ + strokeDashstyle: "solid",
│ │ │ │ │ + hoverStrokeColor: "red",
│ │ │ │ │ + hoverStrokeOpacity: 1,
│ │ │ │ │ + hoverStrokeWidth: 0.2,
│ │ │ │ │ + pointRadius: 6,
│ │ │ │ │ + hoverPointRadius: 1,
│ │ │ │ │ + hoverPointUnit: "%",
│ │ │ │ │ + pointerEvents: "visiblePainted",
│ │ │ │ │ + cursor: "pointer",
│ │ │ │ │ + fontColor: "#000000",
│ │ │ │ │ + labelAlign: "cm",
│ │ │ │ │ + labelOutlineColor: "white",
│ │ │ │ │ + labelOutlineWidth: 3
│ │ │ │ │ +
│ │ │ │ │ + },
│ │ │ │ │ + 'temporary': {
│ │ │ │ │ + fillColor: "#66cccc",
│ │ │ │ │ + fillOpacity: 0.2,
│ │ │ │ │ + hoverFillColor: "white",
│ │ │ │ │ + hoverFillOpacity: 0.8,
│ │ │ │ │ + strokeColor: "#66cccc",
│ │ │ │ │ + strokeOpacity: 1,
│ │ │ │ │ + strokeLinecap: "round",
│ │ │ │ │ + strokeWidth: 2,
│ │ │ │ │ + strokeDashstyle: "solid",
│ │ │ │ │ + hoverStrokeColor: "red",
│ │ │ │ │ + hoverStrokeOpacity: 1,
│ │ │ │ │ + hoverStrokeWidth: 0.2,
│ │ │ │ │ + pointRadius: 6,
│ │ │ │ │ + hoverPointRadius: 1,
│ │ │ │ │ + hoverPointUnit: "%",
│ │ │ │ │ + pointerEvents: "visiblePainted",
│ │ │ │ │ + cursor: "inherit",
│ │ │ │ │ + fontColor: "#000000",
│ │ │ │ │ + labelAlign: "cm",
│ │ │ │ │ + labelOutlineColor: "white",
│ │ │ │ │ + labelOutlineWidth: 3
│ │ │ │ │ +
│ │ │ │ │ + },
│ │ │ │ │ + 'delete': {
│ │ │ │ │ + display: "none"
│ │ │ │ │ + }
│ │ │ │ │ +};
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Style.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + * @requires OpenLayers/Util.js
│ │ │ │ │ + * @requires OpenLayers/Feature/Vector.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Style
│ │ │ │ │ + * This class represents a UserStyle obtained
│ │ │ │ │ + * from a SLD, containing styling rules.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Style = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: id
│ │ │ │ │ + * {String} A unique id for this session.
│ │ │ │ │ + */
│ │ │ │ │ + id: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: name
│ │ │ │ │ + * {String}
│ │ │ │ │ + */
│ │ │ │ │ + name: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: title
│ │ │ │ │ + * {String} Title of this style (set if included in SLD)
│ │ │ │ │ + */
│ │ │ │ │ + title: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: description
│ │ │ │ │ + * {String} Description of this style (set if abstract is included in SLD)
│ │ │ │ │ + */
│ │ │ │ │ + description: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: layerName
│ │ │ │ │ + * {} name of the layer that this style belongs to, usually
│ │ │ │ │ + * according to the NamedLayer attribute of an SLD document.
│ │ │ │ │ + */
│ │ │ │ │ + layerName: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: isDefault
│ │ │ │ │ + * {Boolean}
│ │ │ │ │ + */
│ │ │ │ │ + isDefault: false,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: rules
│ │ │ │ │ + * {Array()}
│ │ │ │ │ + */
│ │ │ │ │ + rules: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: context
│ │ │ │ │ + * {Object} An optional object with properties that symbolizers' property
│ │ │ │ │ + * values should be evaluated against. If no context is specified,
│ │ │ │ │ + * feature.attributes will be used
│ │ │ │ │ + */
│ │ │ │ │ + context: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: defaultStyle
│ │ │ │ │ + * {Object} hash of style properties to use as default for merging
│ │ │ │ │ + * rule-based style symbolizers onto. If no rules are defined,
│ │ │ │ │ + * createSymbolizer will return this style. If is set to
│ │ │ │ │ + * true, the defaultStyle will only be taken into account if there are
│ │ │ │ │ + * rules defined.
│ │ │ │ │ + */
│ │ │ │ │ + defaultStyle: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: defaultsPerSymbolizer
│ │ │ │ │ + * {Boolean} If set to true, the will extend the symbolizer
│ │ │ │ │ + * of every rule. Properties of the will also be used to set
│ │ │ │ │ + * missing symbolizer properties if the symbolizer has stroke, fill or
│ │ │ │ │ + * graphic set to true. Default is false.
│ │ │ │ │ + */
│ │ │ │ │ + defaultsPerSymbolizer: false,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: propertyStyles
│ │ │ │ │ + * {Hash of Boolean} cache of style properties that need to be parsed for
│ │ │ │ │ + * propertyNames. Property names are keys, values won't be used.
│ │ │ │ │ + */
│ │ │ │ │ + propertyStyles: null,
│ │ │ │ │ +
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Style
│ │ │ │ │ + * Creates a UserStyle.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * style - {Object} Optional hash of style properties that will be
│ │ │ │ │ + * used as default style for this style object. This style
│ │ │ │ │ + * applies if no rules are specified. Symbolizers defined in
│ │ │ │ │ + * rules will extend this default style.
│ │ │ │ │ + * options - {Object} An optional object with properties to set on the
│ │ │ │ │ + * style.
│ │ │ │ │ + *
│ │ │ │ │ + * Valid options:
│ │ │ │ │ + * rules - {Array()} List of rules to be added to the
│ │ │ │ │ + * style.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {}
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(style, options) {
│ │ │ │ │ +
│ │ │ │ │ + OpenLayers.Util.extend(this, options);
│ │ │ │ │ + this.rules = [];
│ │ │ │ │ + if (options && options.rules) {
│ │ │ │ │ + this.addRules(options.rules);
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + // use the default style from OpenLayers.Feature.Vector if no style
│ │ │ │ │ + // was given in the constructor
│ │ │ │ │ + this.setDefaultStyle(style ||
│ │ │ │ │ + OpenLayers.Feature.Vector.style["default"]);
│ │ │ │ │ +
│ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: destroy
│ │ │ │ │ + * nullify references to prevent circular references and memory leaks
│ │ │ │ │ + */
│ │ │ │ │ + destroy: function() {
│ │ │ │ │ + for (var i = 0, len = this.rules.length; i < len; i++) {
│ │ │ │ │ + this.rules[i].destroy();
│ │ │ │ │ + this.rules[i] = null;
│ │ │ │ │ + }
│ │ │ │ │ + this.rules = null;
│ │ │ │ │ + this.defaultStyle = null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: createSymbolizer
│ │ │ │ │ + * creates a style by applying all feature-dependent rules to the base
│ │ │ │ │ + * style.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * feature - {} feature to evaluate rules for
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Object} symbolizer hash
│ │ │ │ │ + */
│ │ │ │ │ + createSymbolizer: function(feature) {
│ │ │ │ │ + var style = this.defaultsPerSymbolizer ? {} : this.createLiterals(
│ │ │ │ │ + OpenLayers.Util.extend({}, this.defaultStyle), feature);
│ │ │ │ │ +
│ │ │ │ │ + var rules = this.rules;
│ │ │ │ │ +
│ │ │ │ │ + var rule, context;
│ │ │ │ │ + var elseRules = [];
│ │ │ │ │ + var appliedRules = false;
│ │ │ │ │ + for (var i = 0, len = rules.length; i < len; i++) {
│ │ │ │ │ + rule = rules[i];
│ │ │ │ │ + // does the rule apply?
│ │ │ │ │ + var applies = rule.evaluate(feature);
│ │ │ │ │ +
│ │ │ │ │ + if (applies) {
│ │ │ │ │ + if (rule instanceof OpenLayers.Rule && rule.elseFilter) {
│ │ │ │ │ + elseRules.push(rule);
│ │ │ │ │ + } else {
│ │ │ │ │ + appliedRules = true;
│ │ │ │ │ + this.applySymbolizer(rule, style, feature);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + // if no other rules apply, apply the rules with else filters
│ │ │ │ │ + if (appliedRules == false && elseRules.length > 0) {
│ │ │ │ │ + appliedRules = true;
│ │ │ │ │ + for (var i = 0, len = elseRules.length; i < len; i++) {
│ │ │ │ │ + this.applySymbolizer(elseRules[i], style, feature);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + // don't display if there were rules but none applied
│ │ │ │ │ + if (rules.length > 0 && appliedRules == false) {
│ │ │ │ │ + style.display = "none";
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + if (style.label != null && typeof style.label !== "string") {
│ │ │ │ │ + style.label = String(style.label);
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + return style;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: applySymbolizer
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * rule - {}
│ │ │ │ │ + * style - {Object}
│ │ │ │ │ + * feature - {}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Object} A style with new symbolizer applied.
│ │ │ │ │ + */
│ │ │ │ │ + applySymbolizer: function(rule, style, feature) {
│ │ │ │ │ + var symbolizerPrefix = feature.geometry ?
│ │ │ │ │ + this.getSymbolizerPrefix(feature.geometry) :
│ │ │ │ │ + OpenLayers.Style.SYMBOLIZER_PREFIXES[0];
│ │ │ │ │ +
│ │ │ │ │ + var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer;
│ │ │ │ │ +
│ │ │ │ │ + if (this.defaultsPerSymbolizer === true) {
│ │ │ │ │ + var defaults = this.defaultStyle;
│ │ │ │ │ + OpenLayers.Util.applyDefaults(symbolizer, {
│ │ │ │ │ + pointRadius: defaults.pointRadius
│ │ │ │ │ + });
│ │ │ │ │ + if (symbolizer.stroke === true || symbolizer.graphic === true) {
│ │ │ │ │ + OpenLayers.Util.applyDefaults(symbolizer, {
│ │ │ │ │ + strokeWidth: defaults.strokeWidth,
│ │ │ │ │ + strokeColor: defaults.strokeColor,
│ │ │ │ │ + strokeOpacity: defaults.strokeOpacity,
│ │ │ │ │ + strokeDashstyle: defaults.strokeDashstyle,
│ │ │ │ │ + strokeLinecap: defaults.strokeLinecap
│ │ │ │ │ + });
│ │ │ │ │ + }
│ │ │ │ │ + if (symbolizer.fill === true || symbolizer.graphic === true) {
│ │ │ │ │ + OpenLayers.Util.applyDefaults(symbolizer, {
│ │ │ │ │ + fillColor: defaults.fillColor,
│ │ │ │ │ + fillOpacity: defaults.fillOpacity
│ │ │ │ │ + });
│ │ │ │ │ + }
│ │ │ │ │ + if (symbolizer.graphic === true) {
│ │ │ │ │ + OpenLayers.Util.applyDefaults(symbolizer, {
│ │ │ │ │ + pointRadius: this.defaultStyle.pointRadius,
│ │ │ │ │ + externalGraphic: this.defaultStyle.externalGraphic,
│ │ │ │ │ + graphicName: this.defaultStyle.graphicName,
│ │ │ │ │ + graphicOpacity: this.defaultStyle.graphicOpacity,
│ │ │ │ │ + graphicWidth: this.defaultStyle.graphicWidth,
│ │ │ │ │ + graphicHeight: this.defaultStyle.graphicHeight,
│ │ │ │ │ + graphicXOffset: this.defaultStyle.graphicXOffset,
│ │ │ │ │ + graphicYOffset: this.defaultStyle.graphicYOffset
│ │ │ │ │ + });
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + // merge the style with the current style
│ │ │ │ │ + return this.createLiterals(
│ │ │ │ │ + OpenLayers.Util.extend(style, symbolizer), feature);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: createLiterals
│ │ │ │ │ + * creates literals for all style properties that have an entry in
│ │ │ │ │ + * .
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * style - {Object} style to create literals for. Will be modified
│ │ │ │ │ + * inline.
│ │ │ │ │ + * feature - {Object}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Object} the modified style
│ │ │ │ │ + */
│ │ │ │ │ + createLiterals: function(style, feature) {
│ │ │ │ │ + var context = OpenLayers.Util.extend({}, feature.attributes || feature.data);
│ │ │ │ │ + OpenLayers.Util.extend(context, this.context);
│ │ │ │ │ +
│ │ │ │ │ + for (var i in this.propertyStyles) {
│ │ │ │ │ + style[i] = OpenLayers.Style.createLiteral(style[i], context, feature, i);
│ │ │ │ │ + }
│ │ │ │ │ + return style;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: findPropertyStyles
│ │ │ │ │ + * Looks into all rules for this style and the defaultStyle to collect
│ │ │ │ │ + * all the style hash property names containing ${...} strings that have
│ │ │ │ │ + * to be replaced using the createLiteral method before returning them.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Object} hash of property names that need createLiteral parsing. The
│ │ │ │ │ + * name of the property is the key, and the value is true;
│ │ │ │ │ + */
│ │ │ │ │ + findPropertyStyles: function() {
│ │ │ │ │ + var propertyStyles = {};
│ │ │ │ │ +
│ │ │ │ │ + // check the default style
│ │ │ │ │ + var style = this.defaultStyle;
│ │ │ │ │ + this.addPropertyStyles(propertyStyles, style);
│ │ │ │ │ +
│ │ │ │ │ + // walk through all rules to check for properties in their symbolizer
│ │ │ │ │ + var rules = this.rules;
│ │ │ │ │ + var symbolizer, value;
│ │ │ │ │ + for (var i = 0, len = rules.length; i < len; i++) {
│ │ │ │ │ + symbolizer = rules[i].symbolizer;
│ │ │ │ │ + for (var key in symbolizer) {
│ │ │ │ │ + value = symbolizer[key];
│ │ │ │ │ + if (typeof value == "object") {
│ │ │ │ │ + // symbolizer key is "Point", "Line" or "Polygon"
│ │ │ │ │ + this.addPropertyStyles(propertyStyles, value);
│ │ │ │ │ + } else {
│ │ │ │ │ + // symbolizer is a hash of style properties
│ │ │ │ │ + this.addPropertyStyles(propertyStyles, symbolizer);
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return propertyStyles;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: addPropertyStyles
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * propertyStyles - {Object} hash to add new property styles to. Will be
│ │ │ │ │ + * modified inline
│ │ │ │ │ + * symbolizer - {Object} search this symbolizer for property styles
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Object} propertyStyles hash
│ │ │ │ │ + */
│ │ │ │ │ + addPropertyStyles: function(propertyStyles, symbolizer) {
│ │ │ │ │ + var property;
│ │ │ │ │ + for (var key in symbolizer) {
│ │ │ │ │ + property = symbolizer[key];
│ │ │ │ │ + if (typeof property == "string" &&
│ │ │ │ │ + property.match(/\$\{\w+\}/)) {
│ │ │ │ │ + propertyStyles[key] = true;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return propertyStyles;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: addRules
│ │ │ │ │ + * Adds rules to this style.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * rules - {Array()}
│ │ │ │ │ + */
│ │ │ │ │ + addRules: function(rules) {
│ │ │ │ │ + Array.prototype.push.apply(this.rules, rules);
│ │ │ │ │ + this.propertyStyles = this.findPropertyStyles();
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: setDefaultStyle
│ │ │ │ │ + * Sets the default style for this style object.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * style - {Object} Hash of style properties
│ │ │ │ │ + */
│ │ │ │ │ + setDefaultStyle: function(style) {
│ │ │ │ │ + this.defaultStyle = style;
│ │ │ │ │ + this.propertyStyles = this.findPropertyStyles();
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: getSymbolizerPrefix
│ │ │ │ │ + * Returns the correct symbolizer prefix according to the
│ │ │ │ │ + * geometry type of the passed geometry
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * geometry - {}
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {String} key of the according symbolizer
│ │ │ │ │ + */
│ │ │ │ │ + getSymbolizerPrefix: function(geometry) {
│ │ │ │ │ + var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES;
│ │ │ │ │ + for (var i = 0, len = prefixes.length; i < len; i++) {
│ │ │ │ │ + if (geometry.CLASS_NAME.indexOf(prefixes[i]) != -1) {
│ │ │ │ │ + return prefixes[i];
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: clone
│ │ │ │ │ + * Clones this style.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} Clone of this style.
│ │ │ │ │ + */
│ │ │ │ │ + clone: function() {
│ │ │ │ │ + var options = OpenLayers.Util.extend({}, this);
│ │ │ │ │ + // clone rules
│ │ │ │ │ + if (this.rules) {
│ │ │ │ │ + options.rules = [];
│ │ │ │ │ + for (var i = 0, len = this.rules.length; i < len; ++i) {
│ │ │ │ │ + options.rules.push(this.rules[i].clone());
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + // clone context
│ │ │ │ │ + options.context = this.context && OpenLayers.Util.extend({}, this.context);
│ │ │ │ │ + //clone default style
│ │ │ │ │ + var defaultStyle = OpenLayers.Util.extend({}, this.defaultStyle);
│ │ │ │ │ + return new OpenLayers.Style(defaultStyle, options);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Style"
│ │ │ │ │ +});
│ │ │ │ │ +
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Function: createLiteral
│ │ │ │ │ + * converts a style value holding a combination of PropertyName and Literal
│ │ │ │ │ + * into a Literal, taking the property values from the passed features.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * value - {String} value to parse. If this string contains a construct like
│ │ │ │ │ + * "foo ${bar}", then "foo " will be taken as literal, and "${bar}"
│ │ │ │ │ + * will be replaced by the value of the "bar" attribute of the passed
│ │ │ │ │ + * feature.
│ │ │ │ │ + * context - {Object} context to take attribute values from
│ │ │ │ │ + * feature - {} optional feature to pass to
│ │ │ │ │ + * for evaluating functions in the
│ │ │ │ │ + * context.
│ │ │ │ │ + * property - {String} optional, name of the property for which the literal is
│ │ │ │ │ + * being created for evaluating functions in the context.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {String} the parsed value. In the example of the value parameter above, the
│ │ │ │ │ + * result would be "foo valueOfBar", assuming that the passed feature has an
│ │ │ │ │ + * attribute named "bar" with the value "valueOfBar".
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Style.createLiteral = function(value, context, feature, property) {
│ │ │ │ │ + if (typeof value == "string" && value.indexOf("${") != -1) {
│ │ │ │ │ + value = OpenLayers.String.format(value, context, [feature, property]);
│ │ │ │ │ + value = (isNaN(value) || !value) ? value : parseFloat(value);
│ │ │ │ │ + }
│ │ │ │ │ + return value;
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Constant: OpenLayers.Style.SYMBOLIZER_PREFIXES
│ │ │ │ │ + * {Array} prefixes of the sld symbolizers. These are the
│ │ │ │ │ + * same as the main geometry types
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text',
│ │ │ │ │ + 'Raster'
│ │ │ │ │ +];
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Tile.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + * @requires OpenLayers/Util.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Tile
│ │ │ │ │ + * This is a class designed to designate a single tile, however
│ │ │ │ │ + * it is explicitly designed to do relatively little. Tiles store
│ │ │ │ │ + * information about themselves -- such as the URL that they are related
│ │ │ │ │ + * to, and their size - but do not add themselves to the layer div
│ │ │ │ │ + * automatically, for example. Create a new tile with the
│ │ │ │ │ + * constructor, or a subclass.
│ │ │ │ │ + *
│ │ │ │ │ + * TBD 3.0 - remove reference to url in above paragraph
│ │ │ │ │ + *
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Tile = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: events
│ │ │ │ │ + * {} An events object that handles all
│ │ │ │ │ + * events on the tile.
│ │ │ │ │ + *
│ │ │ │ │ + * Register a listener for a particular event with the following syntax:
│ │ │ │ │ + * (code)
│ │ │ │ │ + * tile.events.register(type, obj, listener);
│ │ │ │ │ + * (end)
│ │ │ │ │ + *
│ │ │ │ │ + * Supported event types:
│ │ │ │ │ + * beforedraw - Triggered before the tile is drawn. Used to defer
│ │ │ │ │ + * drawing to an animation queue. To defer drawing, listeners need
│ │ │ │ │ + * to return false, which will abort drawing. The queue handler needs
│ │ │ │ │ + * to call (true) to actually draw the tile.
│ │ │ │ │ + * loadstart - Triggered when tile loading starts.
│ │ │ │ │ + * loadend - Triggered when tile loading ends.
│ │ │ │ │ + * loaderror - Triggered before the loadend event (i.e. when the tile is
│ │ │ │ │ + * still hidden) if the tile could not be loaded.
│ │ │ │ │ + * reload - Triggered when an already loading tile is reloaded.
│ │ │ │ │ + * unload - Triggered before a tile is unloaded.
│ │ │ │ │ + */
│ │ │ │ │ + events: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: eventListeners
│ │ │ │ │ + * {Object} If set as an option at construction, the eventListeners
│ │ │ │ │ + * object will be registered with . Object
│ │ │ │ │ + * structure must be a listeners object as shown in the example for
│ │ │ │ │ + * the events.on method.
│ │ │ │ │ + *
│ │ │ │ │ + * This options can be set in the ``tileOptions`` option from
│ │ │ │ │ + * . For example, to be notified of the
│ │ │ │ │ + * ``loadend`` event of each tiles:
│ │ │ │ │ + * (code)
│ │ │ │ │ + * new OpenLayers.Layer.OSM('osm', 'http://tile.openstreetmap.org/${z}/${x}/${y}.png', {
│ │ │ │ │ + * tileOptions: {
│ │ │ │ │ + * eventListeners: {
│ │ │ │ │ + * 'loadend': function(evt) {
│ │ │ │ │ + * // do something on loadend
│ │ │ │ │ + * }
│ │ │ │ │ + * }
│ │ │ │ │ + * }
│ │ │ │ │ + * });
│ │ │ │ │ + * (end)
│ │ │ │ │ + */
│ │ │ │ │ + eventListeners: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: id
│ │ │ │ │ + * {String} null
│ │ │ │ │ + */
│ │ │ │ │ + id: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: layer
│ │ │ │ │ + * {} layer the tile is attached to
│ │ │ │ │ + */
│ │ │ │ │ + layer: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: url
│ │ │ │ │ + * {String} url of the request.
│ │ │ │ │ + *
│ │ │ │ │ + * TBD 3.0
│ │ │ │ │ + * Deprecated. The base tile class does not need an url. This should be
│ │ │ │ │ + * handled in subclasses. Does not belong here.
│ │ │ │ │ + */
│ │ │ │ │ + url: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: bounds
│ │ │ │ │ + * {} null
│ │ │ │ │ + */
│ │ │ │ │ + bounds: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: size
│ │ │ │ │ + * {} null
│ │ │ │ │ + */
│ │ │ │ │ + size: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: position
│ │ │ │ │ + * {} Top Left pixel of the tile
│ │ │ │ │ + */
│ │ │ │ │ + position: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: isLoading
│ │ │ │ │ + * {Boolean} Is the tile loading?
│ │ │ │ │ + */
│ │ │ │ │ + isLoading: false,
│ │ │ │ │ +
│ │ │ │ │ + /** TBD 3.0 -- remove 'url' from the list of parameters to the constructor.
│ │ │ │ │ + * there is no need for the base tile class to have a url.
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Tile
│ │ │ │ │ + * Constructor for a new instance.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * layer - {} layer that the tile will go in.
│ │ │ │ │ + * position - {}
│ │ │ │ │ + * bounds - {}
│ │ │ │ │ + * url - {}
│ │ │ │ │ + * size - {}
│ │ │ │ │ + * options - {Object}
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(layer, position, bounds, url, size, options) {
│ │ │ │ │ + this.layer = layer;
│ │ │ │ │ + this.position = position.clone();
│ │ │ │ │ + this.setBounds(bounds);
│ │ │ │ │ + this.url = url;
│ │ │ │ │ + if (size) {
│ │ │ │ │ + this.size = size.clone();
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + //give the tile a unique id based on its BBOX.
│ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID("Tile_");
│ │ │ │ │ +
│ │ │ │ │ + OpenLayers.Util.extend(this, options);
│ │ │ │ │ +
│ │ │ │ │ + this.events = new OpenLayers.Events(this);
│ │ │ │ │ + if (this.eventListeners instanceof Object) {
│ │ │ │ │ + this.events.on(this.eventListeners);
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: unload
│ │ │ │ │ + * Call immediately before destroying if you are listening to tile
│ │ │ │ │ + * events, so that counters are properly handled if tile is still
│ │ │ │ │ + * loading at destroy-time. Will only fire an event if the tile is
│ │ │ │ │ + * still loading.
│ │ │ │ │ + */
│ │ │ │ │ + unload: function() {
│ │ │ │ │ + if (this.isLoading) {
│ │ │ │ │ + this.isLoading = false;
│ │ │ │ │ + this.events.triggerEvent("unload");
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: destroy
│ │ │ │ │ + * Nullify references to prevent circular references and memory leaks.
│ │ │ │ │ + */
│ │ │ │ │ + destroy: function() {
│ │ │ │ │ + this.layer = null;
│ │ │ │ │ + this.bounds = null;
│ │ │ │ │ + this.size = null;
│ │ │ │ │ + this.position = null;
│ │ │ │ │ +
│ │ │ │ │ + if (this.eventListeners) {
│ │ │ │ │ + this.events.un(this.eventListeners);
│ │ │ │ │ + }
│ │ │ │ │ + this.events.destroy();
│ │ │ │ │ + this.eventListeners = null;
│ │ │ │ │ + this.events = null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: draw
│ │ │ │ │ + * Clear whatever is currently in the tile, then return whether or not
│ │ │ │ │ + * it should actually be re-drawn. This is an example implementation
│ │ │ │ │ + * that can be overridden by subclasses. The minimum thing to do here
│ │ │ │ │ + * is to call and return the result from .
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * force - {Boolean} If true, the tile will not be cleared and no beforedraw
│ │ │ │ │ + * event will be fired. This is used for drawing tiles asynchronously
│ │ │ │ │ + * after drawing has been cancelled by returning false from a beforedraw
│ │ │ │ │ + * listener.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} Whether or not the tile should actually be drawn. Returns null
│ │ │ │ │ + * if a beforedraw listener returned false.
│ │ │ │ │ + */
│ │ │ │ │ + draw: function(force) {
│ │ │ │ │ + if (!force) {
│ │ │ │ │ + //clear tile's contents and mark as not drawn
│ │ │ │ │ + this.clear();
│ │ │ │ │ + }
│ │ │ │ │ + var draw = this.shouldDraw();
│ │ │ │ │ + if (draw && !force && this.events.triggerEvent("beforedraw") === false) {
│ │ │ │ │ + draw = null;
│ │ │ │ │ + }
│ │ │ │ │ + return draw;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: shouldDraw
│ │ │ │ │ + * Return whether or not the tile should actually be (re-)drawn. The only
│ │ │ │ │ + * case where we *wouldn't* want to draw the tile is if the tile is outside
│ │ │ │ │ + * its layer's maxExtent
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} Whether or not the tile should actually be drawn.
│ │ │ │ │ + */
│ │ │ │ │ + shouldDraw: function() {
│ │ │ │ │ + var withinMaxExtent = false,
│ │ │ │ │ + maxExtent = this.layer.maxExtent;
│ │ │ │ │ + if (maxExtent) {
│ │ │ │ │ + var map = this.layer.map;
│ │ │ │ │ + var worldBounds = map.baseLayer.wrapDateLine && map.getMaxExtent();
│ │ │ │ │ + if (this.bounds.intersectsBounds(maxExtent, {
│ │ │ │ │ + inclusive: false,
│ │ │ │ │ + worldBounds: worldBounds
│ │ │ │ │ + })) {
│ │ │ │ │ + withinMaxExtent = true;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + return withinMaxExtent || this.layer.displayOutsideMaxExtent;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: setBounds
│ │ │ │ │ + * Sets the bounds on this instance
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * bounds {}
│ │ │ │ │ + */
│ │ │ │ │ + setBounds: function(bounds) {
│ │ │ │ │ + bounds = bounds.clone();
│ │ │ │ │ + if (this.layer.map.baseLayer.wrapDateLine) {
│ │ │ │ │ + var worldExtent = this.layer.map.getMaxExtent(),
│ │ │ │ │ + tolerance = this.layer.map.getResolution();
│ │ │ │ │ + bounds = bounds.wrapDateLine(worldExtent, {
│ │ │ │ │ + leftTolerance: tolerance,
│ │ │ │ │ + rightTolerance: tolerance
│ │ │ │ │ + });
│ │ │ │ │ + }
│ │ │ │ │ + this.bounds = bounds;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: moveTo
│ │ │ │ │ + * Reposition the tile.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * bounds - {}
│ │ │ │ │ + * position - {}
│ │ │ │ │ + * redraw - {Boolean} Call draw method on tile after moving.
│ │ │ │ │ + * Default is true
│ │ │ │ │ + */
│ │ │ │ │ + moveTo: function(bounds, position, redraw) {
│ │ │ │ │ + if (redraw == null) {
│ │ │ │ │ + redraw = true;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + this.setBounds(bounds);
│ │ │ │ │ + this.position = position.clone();
│ │ │ │ │ + if (redraw) {
│ │ │ │ │ + this.draw();
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: clear
│ │ │ │ │ + * Clear the tile of any bounds/position-related data so that it can
│ │ │ │ │ + * be reused in a new location.
│ │ │ │ │ + */
│ │ │ │ │ + clear: function(draw) {
│ │ │ │ │ + // to be extended by subclasses
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Tile"
│ │ │ │ │ +});
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Strategy.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Strategy
│ │ │ │ │ + * Abstract vector layer strategy class. Not to be instantiated directly. Use
│ │ │ │ │ + * one of the strategy subclasses instead.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Strategy = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: layer
│ │ │ │ │ + * {} The layer this strategy belongs to.
│ │ │ │ │ + */
│ │ │ │ │ + layer: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: options
│ │ │ │ │ + * {Object} Any options sent to the constructor.
│ │ │ │ │ + */
│ │ │ │ │ + options: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: active
│ │ │ │ │ + * {Boolean} The control is active.
│ │ │ │ │ + */
│ │ │ │ │ + active: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: autoActivate
│ │ │ │ │ + * {Boolean} The creator of the strategy can set autoActivate to false
│ │ │ │ │ + * to fully control when the protocol is activated and deactivated.
│ │ │ │ │ + * Defaults to true.
│ │ │ │ │ + */
│ │ │ │ │ + autoActivate: true,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: autoDestroy
│ │ │ │ │ + * {Boolean} The creator of the strategy can set autoDestroy to false
│ │ │ │ │ + * to fully control when the strategy is destroyed. Defaults to
│ │ │ │ │ + * true.
│ │ │ │ │ + */
│ │ │ │ │ + autoDestroy: true,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Strategy
│ │ │ │ │ + * Abstract class for vector strategies. Create instances of a subclass.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * options - {Object} Optional object whose properties will be set on the
│ │ │ │ │ + * instance.
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(options) {
│ │ │ │ │ + OpenLayers.Util.extend(this, options);
│ │ │ │ │ + this.options = options;
│ │ │ │ │ + // set the active property here, so that user cannot override it
│ │ │ │ │ + this.active = false;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: destroy
│ │ │ │ │ + * Clean up the strategy.
│ │ │ │ │ + */
│ │ │ │ │ + destroy: function() {
│ │ │ │ │ + this.deactivate();
│ │ │ │ │ + this.layer = null;
│ │ │ │ │ + this.options = null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: setLayer
│ │ │ │ │ + * Called to set the property.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * layer - {}
│ │ │ │ │ + */
│ │ │ │ │ + setLayer: function(layer) {
│ │ │ │ │ + this.layer = layer;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: activate
│ │ │ │ │ + * Activate the strategy. Register any listeners, do appropriate setup.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} True if the strategy was successfully activated or false if
│ │ │ │ │ + * the strategy was already active.
│ │ │ │ │ + */
│ │ │ │ │ + activate: function() {
│ │ │ │ │ + if (!this.active) {
│ │ │ │ │ + this.active = true;
│ │ │ │ │ + return true;
│ │ │ │ │ + }
│ │ │ │ │ + return false;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: deactivate
│ │ │ │ │ + * Deactivate the strategy. Unregister any listeners, do appropriate
│ │ │ │ │ + * tear-down.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} True if the strategy was successfully deactivated or false if
│ │ │ │ │ + * the strategy was already inactive.
│ │ │ │ │ + */
│ │ │ │ │ + deactivate: function() {
│ │ │ │ │ + if (this.active) {
│ │ │ │ │ + this.active = false;
│ │ │ │ │ + return true;
│ │ │ │ │ + }
│ │ │ │ │ + return false;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Strategy"
│ │ │ │ │ +});
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Handler.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + * @requires OpenLayers/Events.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Handler
│ │ │ │ │ + * Base class to construct a higher-level handler for event sequences. All
│ │ │ │ │ + * handlers have activate and deactivate methods. In addition, they have
│ │ │ │ │ + * methods named like browser events. When a handler is activated, any
│ │ │ │ │ + * additional methods named like a browser event is registered as a
│ │ │ │ │ + * listener for the corresponding event. When a handler is deactivated,
│ │ │ │ │ + * those same methods are unregistered as event listeners.
│ │ │ │ │ + *
│ │ │ │ │ + * Handlers also typically have a callbacks object with keys named like
│ │ │ │ │ + * the abstracted events or event sequences that they are in charge of
│ │ │ │ │ + * handling. The controls that wrap handlers define the methods that
│ │ │ │ │ + * correspond to these abstract events - so instead of listening for
│ │ │ │ │ + * individual browser events, they only listen for the abstract events
│ │ │ │ │ + * defined by the handler.
│ │ │ │ │ + *
│ │ │ │ │ + * Handlers are created by controls, which ultimately have the responsibility
│ │ │ │ │ + * of making changes to the the state of the application. Handlers
│ │ │ │ │ + * themselves may make temporary changes, but in general are expected to
│ │ │ │ │ + * return the application in the same state that they found it.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Handler = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: id
│ │ │ │ │ + * {String}
│ │ │ │ │ + */
│ │ │ │ │ + id: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: control
│ │ │ │ │ + * {}. The control that initialized this handler. The
│ │ │ │ │ + * control is assumed to have a valid map property - that map is used
│ │ │ │ │ + * in the handler's own setMap method.
│ │ │ │ │ + */
│ │ │ │ │ + control: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: map
│ │ │ │ │ + * {}
│ │ │ │ │ + */
│ │ │ │ │ + map: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: keyMask
│ │ │ │ │ + * {Integer} Use bitwise operators and one or more of the OpenLayers.Handler
│ │ │ │ │ + * constants to construct a keyMask. The keyMask is used by
│ │ │ │ │ + * . If the keyMask matches the combination of keys
│ │ │ │ │ + * down on an event, checkModifiers returns true.
│ │ │ │ │ + *
│ │ │ │ │ + * Example:
│ │ │ │ │ + * (code)
│ │ │ │ │ + * // handler only responds if the Shift key is down
│ │ │ │ │ + * handler.keyMask = OpenLayers.Handler.MOD_SHIFT;
│ │ │ │ │ + *
│ │ │ │ │ + * // handler only responds if Ctrl-Shift is down
│ │ │ │ │ + * handler.keyMask = OpenLayers.Handler.MOD_SHIFT |
│ │ │ │ │ + * OpenLayers.Handler.MOD_CTRL;
│ │ │ │ │ + * (end)
│ │ │ │ │ + */
│ │ │ │ │ + keyMask: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: active
│ │ │ │ │ + * {Boolean}
│ │ │ │ │ + */
│ │ │ │ │ + active: false,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: evt
│ │ │ │ │ + * {Event} This property references the last event handled by the handler.
│ │ │ │ │ + * Note that this property is not part of the stable API. Use of the
│ │ │ │ │ + * evt property should be restricted to controls in the library
│ │ │ │ │ + * or other applications that are willing to update with changes to
│ │ │ │ │ + * the OpenLayers code.
│ │ │ │ │ + */
│ │ │ │ │ + evt: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: touch
│ │ │ │ │ + * {Boolean} Indicates the support of touch events. When touch events are
│ │ │ │ │ + * started touch will be true and all mouse related listeners will do
│ │ │ │ │ + * nothing.
│ │ │ │ │ + */
│ │ │ │ │ + touch: false,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Handler
│ │ │ │ │ + * Construct a handler.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * control - {} The control that initialized this
│ │ │ │ │ + * handler. The control is assumed to have a valid map property; that
│ │ │ │ │ + * map is used in the handler's own setMap method. If a map property
│ │ │ │ │ + * is present in the options argument it will be used instead.
│ │ │ │ │ + * callbacks - {Object} An object whose properties correspond to abstracted
│ │ │ │ │ + * events or sequences of browser events. The values for these
│ │ │ │ │ + * properties are functions defined by the control that get called by
│ │ │ │ │ + * the handler.
│ │ │ │ │ + * options - {Object} An optional object whose properties will be set on
│ │ │ │ │ + * the handler.
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(control, callbacks, options) {
│ │ │ │ │ + OpenLayers.Util.extend(this, options);
│ │ │ │ │ + this.control = control;
│ │ │ │ │ + this.callbacks = callbacks;
│ │ │ │ │ +
│ │ │ │ │ + var map = this.map || control.map;
│ │ │ │ │ + if (map) {
│ │ │ │ │ + this.setMap(map);
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: setMap
│ │ │ │ │ + */
│ │ │ │ │ + setMap: function(map) {
│ │ │ │ │ + this.map = map;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: checkModifiers
│ │ │ │ │ + * Check the keyMask on the handler. If no is set, this always
│ │ │ │ │ + * returns true. If a is set and it matches the combination
│ │ │ │ │ + * of keys down on an event, this returns true.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The keyMask matches the keys down on an event.
│ │ │ │ │ + */
│ │ │ │ │ + checkModifiers: function(evt) {
│ │ │ │ │ + if (this.keyMask == null) {
│ │ │ │ │ + return true;
│ │ │ │ │ + }
│ │ │ │ │ + /* calculate the keyboard modifier mask for this event */
│ │ │ │ │ + var keyModifiers =
│ │ │ │ │ + (evt.shiftKey ? OpenLayers.Handler.MOD_SHIFT : 0) |
│ │ │ │ │ + (evt.ctrlKey ? OpenLayers.Handler.MOD_CTRL : 0) |
│ │ │ │ │ + (evt.altKey ? OpenLayers.Handler.MOD_ALT : 0) |
│ │ │ │ │ + (evt.metaKey ? OpenLayers.Handler.MOD_META : 0);
│ │ │ │ │ +
│ │ │ │ │ + /* if it differs from the handler object's key mask,
│ │ │ │ │ + bail out of the event handler */
│ │ │ │ │ + return (keyModifiers == this.keyMask);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: activate
│ │ │ │ │ + * Turn on the handler. Returns false if the handler was already active.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The handler was activated.
│ │ │ │ │ + */
│ │ │ │ │ + activate: function() {
│ │ │ │ │ + if (this.active) {
│ │ │ │ │ + return false;
│ │ │ │ │ + }
│ │ │ │ │ + // register for event handlers defined on this class.
│ │ │ │ │ + var events = OpenLayers.Events.prototype.BROWSER_EVENTS;
│ │ │ │ │ + for (var i = 0, len = events.length; i < len; i++) {
│ │ │ │ │ + if (this[events[i]]) {
│ │ │ │ │ + this.register(events[i], this[events[i]]);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + this.active = true;
│ │ │ │ │ + return true;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: deactivate
│ │ │ │ │ + * Turn off the handler. Returns false if the handler was already inactive.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The handler was deactivated.
│ │ │ │ │ + */
│ │ │ │ │ + deactivate: function() {
│ │ │ │ │ + if (!this.active) {
│ │ │ │ │ + return false;
│ │ │ │ │ + }
│ │ │ │ │ + // unregister event handlers defined on this class.
│ │ │ │ │ + var events = OpenLayers.Events.prototype.BROWSER_EVENTS;
│ │ │ │ │ + for (var i = 0, len = events.length; i < len; i++) {
│ │ │ │ │ + if (this[events[i]]) {
│ │ │ │ │ + this.unregister(events[i], this[events[i]]);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + this.touch = false;
│ │ │ │ │ + this.active = false;
│ │ │ │ │ + return true;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: startTouch
│ │ │ │ │ + * Start touch events, this method must be called by subclasses in
│ │ │ │ │ + * "touchstart" method. When touch events are started will be
│ │ │ │ │ + * true and all mouse related listeners will do nothing.
│ │ │ │ │ + */
│ │ │ │ │ + startTouch: function() {
│ │ │ │ │ + if (!this.touch) {
│ │ │ │ │ + this.touch = true;
│ │ │ │ │ + var events = [
│ │ │ │ │ + "mousedown", "mouseup", "mousemove", "click", "dblclick",
│ │ │ │ │ + "mouseout"
│ │ │ │ │ + ];
│ │ │ │ │ + for (var i = 0, len = events.length; i < len; i++) {
│ │ │ │ │ + if (this[events[i]]) {
│ │ │ │ │ + this.unregister(events[i], this[events[i]]);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: callback
│ │ │ │ │ + * Trigger the control's named callback with the given arguments
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * name - {String} The key for the callback that is one of the properties
│ │ │ │ │ + * of the handler's callbacks object.
│ │ │ │ │ + * args - {Array(*)} An array of arguments (any type) with which to call
│ │ │ │ │ + * the callback (defined by the control).
│ │ │ │ │ + */
│ │ │ │ │ + callback: function(name, args) {
│ │ │ │ │ + if (name && this.callbacks[name]) {
│ │ │ │ │ + this.callbacks[name].apply(this.control, args);
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: register
│ │ │ │ │ + * register an event on the map
│ │ │ │ │ + */
│ │ │ │ │ + register: function(name, method) {
│ │ │ │ │ + // TODO: deal with registerPriority in 3.0
│ │ │ │ │ + this.map.events.registerPriority(name, this, method);
│ │ │ │ │ + this.map.events.registerPriority(name, this, this.setEvent);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: unregister
│ │ │ │ │ + * unregister an event from the map
│ │ │ │ │ + */
│ │ │ │ │ + unregister: function(name, method) {
│ │ │ │ │ + this.map.events.unregister(name, this, method);
│ │ │ │ │ + this.map.events.unregister(name, this, this.setEvent);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: setEvent
│ │ │ │ │ + * With each registered browser event, the handler sets its own evt
│ │ │ │ │ + * property. This property can be accessed by controls if needed
│ │ │ │ │ + * to get more information about the event that the handler is
│ │ │ │ │ + * processing.
│ │ │ │ │ + *
│ │ │ │ │ + * This allows modifier keys on the event to be checked (alt, shift, ctrl,
│ │ │ │ │ + * and meta cannot be checked with the keyboard handler). For a
│ │ │ │ │ + * control to determine which modifier keys are associated with the
│ │ │ │ │ + * event that a handler is currently processing, it should access
│ │ │ │ │ + * (code)handler.evt.altKey || handler.evt.shiftKey ||
│ │ │ │ │ + * handler.evt.ctrlKey || handler.evt.metaKey(end).
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * evt - {Event} The browser event.
│ │ │ │ │ + */
│ │ │ │ │ + setEvent: function(evt) {
│ │ │ │ │ + this.evt = evt;
│ │ │ │ │ + return true;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: destroy
│ │ │ │ │ + * Deconstruct the handler.
│ │ │ │ │ + */
│ │ │ │ │ + destroy: function() {
│ │ │ │ │ + // unregister event listeners
│ │ │ │ │ + this.deactivate();
│ │ │ │ │ + // eliminate circular references
│ │ │ │ │ + this.control = this.map = null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Handler"
│ │ │ │ │ +});
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Constant: OpenLayers.Handler.MOD_NONE
│ │ │ │ │ + * If set as the , returns false if any key is down.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Handler.MOD_NONE = 0;
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Constant: OpenLayers.Handler.MOD_SHIFT
│ │ │ │ │ + * If set as the , returns false if Shift is down.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Handler.MOD_SHIFT = 1;
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Constant: OpenLayers.Handler.MOD_CTRL
│ │ │ │ │ + * If set as the , returns false if Ctrl is down.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Handler.MOD_CTRL = 2;
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Constant: OpenLayers.Handler.MOD_ALT
│ │ │ │ │ + * If set as the , returns false if Alt is down.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Handler.MOD_ALT = 4;
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Constant: OpenLayers.Handler.MOD_META
│ │ │ │ │ + * If set as the , returns false if Cmd is down.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Handler.MOD_META = 8;
│ │ │ │ │ +
│ │ │ │ │ +
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Protocol.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Protocol
│ │ │ │ │ + * Abstract vector layer protocol class. Not to be instantiated directly. Use
│ │ │ │ │ + * one of the protocol subclasses instead.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Protocol = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: format
│ │ │ │ │ + * {} The format used by this protocol.
│ │ │ │ │ + */
│ │ │ │ │ + format: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: options
│ │ │ │ │ + * {Object} Any options sent to the constructor.
│ │ │ │ │ + */
│ │ │ │ │ + options: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: autoDestroy
│ │ │ │ │ + * {Boolean} The creator of the protocol can set autoDestroy to false
│ │ │ │ │ + * to fully control when the protocol is destroyed. Defaults to
│ │ │ │ │ + * true.
│ │ │ │ │ + */
│ │ │ │ │ + autoDestroy: true,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: defaultFilter
│ │ │ │ │ + * {} Optional default filter to read requests
│ │ │ │ │ + */
│ │ │ │ │ + defaultFilter: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Protocol
│ │ │ │ │ + * Abstract class for vector protocols. Create instances of a subclass.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * options - {Object} Optional object whose properties will be set on the
│ │ │ │ │ + * instance.
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(options) {
│ │ │ │ │ + options = options || {};
│ │ │ │ │ + OpenLayers.Util.extend(this, options);
│ │ │ │ │ + this.options = options;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: mergeWithDefaultFilter
│ │ │ │ │ + * Merge filter passed to the read method with the default one
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * filter - {}
│ │ │ │ │ + */
│ │ │ │ │ + mergeWithDefaultFilter: function(filter) {
│ │ │ │ │ + var merged;
│ │ │ │ │ + if (filter && this.defaultFilter) {
│ │ │ │ │ + merged = new OpenLayers.Filter.Logical({
│ │ │ │ │ + type: OpenLayers.Filter.Logical.AND,
│ │ │ │ │ + filters: [this.defaultFilter, filter]
│ │ │ │ │ + });
│ │ │ │ │ + } else {
│ │ │ │ │ + merged = filter || this.defaultFilter || undefined;
│ │ │ │ │ + }
│ │ │ │ │ + return merged;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: destroy
│ │ │ │ │ + * Clean up the protocol.
│ │ │ │ │ + */
│ │ │ │ │ + destroy: function() {
│ │ │ │ │ + this.options = null;
│ │ │ │ │ + this.format = null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: read
│ │ │ │ │ + * Construct a request for reading new features.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * options - {Object} Optional object for configuring the request.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} An
│ │ │ │ │ + * object, the same object will be passed to the callback function passed
│ │ │ │ │ + * if one exists in the options object.
│ │ │ │ │ + */
│ │ │ │ │ + read: function(options) {
│ │ │ │ │ + options = options || {};
│ │ │ │ │ + options.filter = this.mergeWithDefaultFilter(options.filter);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: create
│ │ │ │ │ + * Construct a request for writing newly created features.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * features - {Array({})} or
│ │ │ │ │ + * {}
│ │ │ │ │ + * options - {Object} Optional object for configuring the request.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} An
│ │ │ │ │ + * object, the same object will be passed to the callback function passed
│ │ │ │ │ + * if one exists in the options object.
│ │ │ │ │ + */
│ │ │ │ │ + create: function() {},
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: update
│ │ │ │ │ + * Construct a request updating modified features.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * features - {Array({})} or
│ │ │ │ │ + * {}
│ │ │ │ │ + * options - {Object} Optional object for configuring the request.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} An
│ │ │ │ │ + * object, the same object will be passed to the callback function passed
│ │ │ │ │ + * if one exists in the options object.
│ │ │ │ │ + */
│ │ │ │ │ + update: function() {},
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: delete
│ │ │ │ │ + * Construct a request deleting a removed feature.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * feature - {}
│ │ │ │ │ + * options - {Object} Optional object for configuring the request.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} An
│ │ │ │ │ + * object, the same object will be passed to the callback function passed
│ │ │ │ │ + * if one exists in the options object.
│ │ │ │ │ + */
│ │ │ │ │ + "delete": function() {},
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: commit
│ │ │ │ │ + * Go over the features and for each take action
│ │ │ │ │ + * based on the feature state. Possible actions are create,
│ │ │ │ │ + * update and delete.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * features - {Array({})}
│ │ │ │ │ + * options - {Object} Object whose possible keys are "create", "update",
│ │ │ │ │ + * "delete", "callback" and "scope", the values referenced by the
│ │ │ │ │ + * first three are objects as passed to the "create", "update", and
│ │ │ │ │ + * "delete" methods, the value referenced by the "callback" key is
│ │ │ │ │ + * a function which is called when the commit operation is complete
│ │ │ │ │ + * using the scope referenced by the "scope" key.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Array({})} An array of
│ │ │ │ │ + * objects.
│ │ │ │ │ + */
│ │ │ │ │ + commit: function() {},
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: abort
│ │ │ │ │ + * Abort an ongoing request.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * response - {}
│ │ │ │ │ + */
│ │ │ │ │ + abort: function(response) {},
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: createCallback
│ │ │ │ │ + * Returns a function that applies the given public method with resp and
│ │ │ │ │ + * options arguments.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * method - {Function} The method to be applied by the callback.
│ │ │ │ │ + * response - {} The protocol response object.
│ │ │ │ │ + * options - {Object} Options sent to the protocol method
│ │ │ │ │ + */
│ │ │ │ │ + createCallback: function(method, response, options) {
│ │ │ │ │ + return OpenLayers.Function.bind(function() {
│ │ │ │ │ + method.apply(this, [response, options]);
│ │ │ │ │ + }, this);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Protocol"
│ │ │ │ │ +});
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Protocol.Response
│ │ │ │ │ + * Protocols return Response objects to their users.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Protocol.Response = OpenLayers.Class({
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: code
│ │ │ │ │ + * {Number} - OpenLayers.Protocol.Response.SUCCESS or
│ │ │ │ │ + * OpenLayers.Protocol.Response.FAILURE
│ │ │ │ │ + */
│ │ │ │ │ + code: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: requestType
│ │ │ │ │ + * {String} The type of request this response corresponds to. Either
│ │ │ │ │ + * "create", "read", "update" or "delete".
│ │ │ │ │ + */
│ │ │ │ │ + requestType: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: last
│ │ │ │ │ + * {Boolean} - true if this is the last response expected in a commit,
│ │ │ │ │ + * false otherwise, defaults to true.
│ │ │ │ │ + */
│ │ │ │ │ + last: true,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: features
│ │ │ │ │ + * {Array({})} or {}
│ │ │ │ │ + * The features returned in the response by the server. Depending on the
│ │ │ │ │ + * protocol's read payload, either features or data will be populated.
│ │ │ │ │ + */
│ │ │ │ │ + features: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: data
│ │ │ │ │ + * {Object}
│ │ │ │ │ + * The data returned in the response by the server. Depending on the
│ │ │ │ │ + * protocol's read payload, either features or data will be populated.
│ │ │ │ │ + */
│ │ │ │ │ + data: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: reqFeatures
│ │ │ │ │ + * {Array({})} or {}
│ │ │ │ │ + * The features provided by the user and placed in the request by the
│ │ │ │ │ + * protocol.
│ │ │ │ │ + */
│ │ │ │ │ + reqFeatures: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: priv
│ │ │ │ │ + */
│ │ │ │ │ + priv: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: error
│ │ │ │ │ + * {Object} The error object in case a service exception was encountered.
│ │ │ │ │ + */
│ │ │ │ │ + error: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Protocol.Response
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * options - {Object} Optional object whose properties will be set on the
│ │ │ │ │ + * instance.
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(options) {
│ │ │ │ │ + OpenLayers.Util.extend(this, options);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: success
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} - true on success, false otherwise
│ │ │ │ │ + */
│ │ │ │ │ + success: function() {
│ │ │ │ │ + return this.code > 0;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Protocol.Response"
│ │ │ │ │ +});
│ │ │ │ │ +
│ │ │ │ │ +OpenLayers.Protocol.Response.SUCCESS = 1;
│ │ │ │ │ +OpenLayers.Protocol.Response.FAILURE = 0;
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/StyleMap.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + * @requires OpenLayers/Style.js
│ │ │ │ │ + * @requires OpenLayers/Feature/Vector.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.StyleMap
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.StyleMap = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: styles
│ │ │ │ │ + * {Object} Hash of {}, keyed by names of well known
│ │ │ │ │ + * rendering intents (e.g. "default", "temporary", "select", "delete").
│ │ │ │ │ + */
│ │ │ │ │ + styles: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: extendDefault
│ │ │ │ │ + * {Boolean} if true, every render intent will extend the symbolizers
│ │ │ │ │ + * specified for the "default" intent at rendering time. Otherwise, every
│ │ │ │ │ + * rendering intent will be treated as a completely independent style.
│ │ │ │ │ + */
│ │ │ │ │ + extendDefault: true,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.StyleMap
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * style - {Object} Optional. Either a style hash, or a style object, or
│ │ │ │ │ + * a hash of style objects (style hashes) keyed by rendering
│ │ │ │ │ + * intent. If just one style hash or style object is passed,
│ │ │ │ │ + * this will be used for all known render intents (default,
│ │ │ │ │ + * select, temporary)
│ │ │ │ │ + * options - {Object} optional hash of additional options for this
│ │ │ │ │ + * instance
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(style, options) {
│ │ │ │ │ + this.styles = {
│ │ │ │ │ + "default": new OpenLayers.Style(
│ │ │ │ │ + OpenLayers.Feature.Vector.style["default"]),
│ │ │ │ │ + "select": new OpenLayers.Style(
│ │ │ │ │ + OpenLayers.Feature.Vector.style["select"]),
│ │ │ │ │ + "temporary": new OpenLayers.Style(
│ │ │ │ │ + OpenLayers.Feature.Vector.style["temporary"]),
│ │ │ │ │ + "delete": new OpenLayers.Style(
│ │ │ │ │ + OpenLayers.Feature.Vector.style["delete"])
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ + // take whatever the user passed as style parameter and convert it
│ │ │ │ │ + // into parts of stylemap.
│ │ │ │ │ + if (style instanceof OpenLayers.Style) {
│ │ │ │ │ + // user passed a style object
│ │ │ │ │ + this.styles["default"] = style;
│ │ │ │ │ + this.styles["select"] = style;
│ │ │ │ │ + this.styles["temporary"] = style;
│ │ │ │ │ + this.styles["delete"] = style;
│ │ │ │ │ + } else if (typeof style == "object") {
│ │ │ │ │ + for (var key in style) {
│ │ │ │ │ + if (style[key] instanceof OpenLayers.Style) {
│ │ │ │ │ + // user passed a hash of style objects
│ │ │ │ │ + this.styles[key] = style[key];
│ │ │ │ │ + } else if (typeof style[key] == "object") {
│ │ │ │ │ + // user passsed a hash of style hashes
│ │ │ │ │ + this.styles[key] = new OpenLayers.Style(style[key]);
│ │ │ │ │ + } else {
│ │ │ │ │ + // user passed a style hash (i.e. symbolizer)
│ │ │ │ │ + this.styles["default"] = new OpenLayers.Style(style);
│ │ │ │ │ + this.styles["select"] = new OpenLayers.Style(style);
│ │ │ │ │ + this.styles["temporary"] = new OpenLayers.Style(style);
│ │ │ │ │ + this.styles["delete"] = new OpenLayers.Style(style);
│ │ │ │ │ + break;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + OpenLayers.Util.extend(this, options);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: destroy
│ │ │ │ │ + */
│ │ │ │ │ + destroy: function() {
│ │ │ │ │ + for (var key in this.styles) {
│ │ │ │ │ + this.styles[key].destroy();
│ │ │ │ │ + }
│ │ │ │ │ + this.styles = null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: createSymbolizer
│ │ │ │ │ + * Creates the symbolizer for a feature for a render intent.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * feature - {} The feature to evaluate the rules
│ │ │ │ │ + * of the intended style against.
│ │ │ │ │ + * intent - {String} The intent determines the symbolizer that will be
│ │ │ │ │ + * used to draw the feature. Well known intents are "default"
│ │ │ │ │ + * (for just drawing the features), "select" (for selected
│ │ │ │ │ + * features) and "temporary" (for drawing features).
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Object} symbolizer hash
│ │ │ │ │ + */
│ │ │ │ │ + createSymbolizer: function(feature, intent) {
│ │ │ │ │ + if (!feature) {
│ │ │ │ │ + feature = new OpenLayers.Feature.Vector();
│ │ │ │ │ + }
│ │ │ │ │ + if (!this.styles[intent]) {
│ │ │ │ │ + intent = "default";
│ │ │ │ │ + }
│ │ │ │ │ + feature.renderIntent = intent;
│ │ │ │ │ + var defaultSymbolizer = {};
│ │ │ │ │ + if (this.extendDefault && intent != "default") {
│ │ │ │ │ + defaultSymbolizer = this.styles["default"].createSymbolizer(feature);
│ │ │ │ │ + }
│ │ │ │ │ + return OpenLayers.Util.extend(defaultSymbolizer,
│ │ │ │ │ + this.styles[intent].createSymbolizer(feature));
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: addUniqueValueRules
│ │ │ │ │ + * Convenience method to create comparison rules for unique values of a
│ │ │ │ │ + * property. The rules will be added to the style object for a specified
│ │ │ │ │ + * rendering intent. This method is a shortcut for creating something like
│ │ │ │ │ + * the "unique value legends" familiar from well known desktop GIS systems
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * renderIntent - {String} rendering intent to add the rules to
│ │ │ │ │ + * property - {String} values of feature attributes to create the
│ │ │ │ │ + * rules for
│ │ │ │ │ + * symbolizers - {Object} Hash of symbolizers, keyed by the desired
│ │ │ │ │ + * property values
│ │ │ │ │ + * context - {Object} An optional object with properties that
│ │ │ │ │ + * symbolizers' property values should be evaluated
│ │ │ │ │ + * against. If no context is specified, feature.attributes
│ │ │ │ │ + * will be used
│ │ │ │ │ + */
│ │ │ │ │ + addUniqueValueRules: function(renderIntent, property, symbolizers, context) {
│ │ │ │ │ + var rules = [];
│ │ │ │ │ + for (var value in symbolizers) {
│ │ │ │ │ + rules.push(new OpenLayers.Rule({
│ │ │ │ │ + symbolizer: symbolizers[value],
│ │ │ │ │ + context: context,
│ │ │ │ │ + filter: new OpenLayers.Filter.Comparison({
│ │ │ │ │ + type: OpenLayers.Filter.Comparison.EQUAL_TO,
│ │ │ │ │ + property: property,
│ │ │ │ │ + value: value
│ │ │ │ │ + })
│ │ │ │ │ + }));
│ │ │ │ │ + }
│ │ │ │ │ + this.styles[renderIntent].addRules(rules);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.StyleMap"
│ │ │ │ │ +});
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Spherical.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/SingleFile.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Namespace: Spherical
│ │ │ │ │ + * The OpenLayers.Spherical namespace includes utility functions for
│ │ │ │ │ + * calculations on the basis of a spherical earth (ignoring ellipsoidal
│ │ │ │ │ + * effects), which is accurate enough for most purposes.
│ │ │ │ │ + *
│ │ │ │ │ + * Relevant links:
│ │ │ │ │ + * * http://www.movable-type.co.uk/scripts/latlong.html
│ │ │ │ │ + * * http://code.google.com/apis/maps/documentation/javascript/reference.html#spherical
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +OpenLayers.Spherical = OpenLayers.Spherical || {};
│ │ │ │ │ +
│ │ │ │ │ +OpenLayers.Spherical.DEFAULT_RADIUS = 6378137;
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * APIFunction: computeDistanceBetween
│ │ │ │ │ + * Computes the distance between two LonLats.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * from - {} or {Object} Starting point. A LonLat or
│ │ │ │ │ + * a JavaScript literal with lon lat properties.
│ │ │ │ │ + * to - {} or {Object} Ending point. A LonLat or a
│ │ │ │ │ + * JavaScript literal with lon lat properties.
│ │ │ │ │ + * radius - {Float} The radius. Optional. Defaults to 6378137 meters.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float} The distance in meters.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Spherical.computeDistanceBetween = function(from, to, radius) {
│ │ │ │ │ + var R = radius || OpenLayers.Spherical.DEFAULT_RADIUS;
│ │ │ │ │ + var sinHalfDeltaLon = Math.sin(Math.PI * (to.lon - from.lon) / 360);
│ │ │ │ │ + var sinHalfDeltaLat = Math.sin(Math.PI * (to.lat - from.lat) / 360);
│ │ │ │ │ + var a = sinHalfDeltaLat * sinHalfDeltaLat +
│ │ │ │ │ + sinHalfDeltaLon * sinHalfDeltaLon * Math.cos(Math.PI * from.lat / 180) * Math.cos(Math.PI * to.lat / 180);
│ │ │ │ │ + return 2 * R * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * APIFunction: computeHeading
│ │ │ │ │ + * Computes the heading from one LonLat to another LonLat.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * from - {} or {Object} Starting point. A LonLat or
│ │ │ │ │ + * a JavaScript literal with lon lat properties.
│ │ │ │ │ + * to - {} or {Object} Ending point. A LonLat or a
│ │ │ │ │ + * JavaScript literal with lon lat properties.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float} The heading in degrees.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Spherical.computeHeading = function(from, to) {
│ │ │ │ │ + var y = Math.sin(Math.PI * (from.lon - to.lon) / 180) * Math.cos(Math.PI * to.lat / 180);
│ │ │ │ │ + var x = Math.cos(Math.PI * from.lat / 180) * Math.sin(Math.PI * to.lat / 180) -
│ │ │ │ │ + Math.sin(Math.PI * from.lat / 180) * Math.cos(Math.PI * to.lat / 180) * Math.cos(Math.PI * (from.lon - to.lon) / 180);
│ │ │ │ │ + return 180 * Math.atan2(y, x) / Math.PI;
│ │ │ │ │ +};
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Filter.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + * @requires OpenLayers/Util.js
│ │ │ │ │ + * @requires OpenLayers/Style.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Filter
│ │ │ │ │ + * This class represents an OGC Filter.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Filter = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Filter
│ │ │ │ │ + * This class represents a generic filter.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * options - {Object} Optional object whose properties will be set on the
│ │ │ │ │ + * instance.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {}
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(options) {
│ │ │ │ │ + OpenLayers.Util.extend(this, options);
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: destroy
│ │ │ │ │ + * Remove reference to anything added.
│ │ │ │ │ + */
│ │ │ │ │ + destroy: function() {},
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: evaluate
│ │ │ │ │ + * Evaluates this filter in a specific context. Instances or subclasses
│ │ │ │ │ + * are supposed to override this method.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * context - {Object} Context to use in evaluating the filter. If a vector
│ │ │ │ │ + * feature is provided, the feature.attributes will be used as context.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The filter applies.
│ │ │ │ │ + */
│ │ │ │ │ + evaluate: function(context) {
│ │ │ │ │ + return true;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: clone
│ │ │ │ │ + * Clones this filter. Should be implemented by subclasses.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} Clone of this filter.
│ │ │ │ │ + */
│ │ │ │ │ + clone: function() {
│ │ │ │ │ + return null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: toString
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {String} Include in your build to get a CQL
│ │ │ │ │ + * representation of the filter returned. Otherwise "[Object object]"
│ │ │ │ │ + * will be returned.
│ │ │ │ │ + */
│ │ │ │ │ + toString: function() {
│ │ │ │ │ + var string;
│ │ │ │ │ + if (OpenLayers.Format && OpenLayers.Format.CQL) {
│ │ │ │ │ + string = OpenLayers.Format.CQL.prototype.write(this);
│ │ │ │ │ + } else {
│ │ │ │ │ + string = Object.prototype.toString.call(this);
│ │ │ │ │ + }
│ │ │ │ │ + return string;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Filter"
│ │ │ │ │ +});
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Util/vendorPrefix.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/SingleFile.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +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-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/SingleFile.js
│ │ │ │ │ + * @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 in series for some
│ │ │ │ │ + * duration.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * callback - {Function} The function to be called at the next animation frame.
│ │ │ │ │ + * duration - {Number} Optional duration for the loop. If not provided, the
│ │ │ │ │ + * animation loop will execute indefinitely.
│ │ │ │ │ + * element - {DOMElement} Optional element that visually bounds the animation.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Number} Identifier for the animation loop. Used to stop animations with
│ │ │ │ │ + * .
│ │ │ │ │ + */
│ │ │ │ │ + function start(callback, duration, element) {
│ │ │ │ │ + duration = duration > 0 ? duration : Number.POSITIVE_INFINITY;
│ │ │ │ │ + var id = ++counter;
│ │ │ │ │ + var start = +new Date;
│ │ │ │ │ + loops[id] = function() {
│ │ │ │ │ + if (loops[id] && +new Date - start <= duration) {
│ │ │ │ │ + callback();
│ │ │ │ │ + if (loops[id]) {
│ │ │ │ │ + requestFrame(loops[id], element);
│ │ │ │ │ + }
│ │ │ │ │ + } else {
│ │ │ │ │ + delete loops[id];
│ │ │ │ │ + }
│ │ │ │ │ + };
│ │ │ │ │ + requestFrame(loops[id], element);
│ │ │ │ │ + return id;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Function: stop
│ │ │ │ │ + * Terminates an animation loop started with .
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * id - {Number} Identifier returned from .
│ │ │ │ │ + */
│ │ │ │ │ + function stop(id) {
│ │ │ │ │ + delete loops[id];
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + return {
│ │ │ │ │ + isNative: isNative,
│ │ │ │ │ + requestFrame: requestFrame,
│ │ │ │ │ + start: start,
│ │ │ │ │ + stop: stop
│ │ │ │ │ + };
│ │ │ │ │ +
│ │ │ │ │ +})(window);
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Tween.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + * @requires OpenLayers/Animation.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Namespace: OpenLayers.Tween
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Tween = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: easing
│ │ │ │ │ + * {(Function)} Easing equation used for the animation
│ │ │ │ │ + * Defaultly set to OpenLayers.Easing.Expo.easeOut
│ │ │ │ │ + */
│ │ │ │ │ + easing: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: begin
│ │ │ │ │ + * {Object} Values to start the animation with
│ │ │ │ │ + */
│ │ │ │ │ + begin: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: finish
│ │ │ │ │ + * {Object} Values to finish the animation with
│ │ │ │ │ + */
│ │ │ │ │ + finish: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: duration
│ │ │ │ │ + * {int} duration of the tween (number of steps)
│ │ │ │ │ + */
│ │ │ │ │ + duration: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: callbacks
│ │ │ │ │ + * {Object} An object with start, eachStep and done properties whose values
│ │ │ │ │ + * are functions to be call during the animation. They are passed the
│ │ │ │ │ + * current computed value as argument.
│ │ │ │ │ + */
│ │ │ │ │ + callbacks: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: time
│ │ │ │ │ + * {int} Step counter
│ │ │ │ │ + */
│ │ │ │ │ + time: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: minFrameRate
│ │ │ │ │ + * {Number} The minimum framerate for animations in frames per second. After
│ │ │ │ │ + * each step, the time spent in the animation is compared to the calculated
│ │ │ │ │ + * time at this frame rate. If the animation runs longer than the calculated
│ │ │ │ │ + * time, the next step is skipped. Default is 30.
│ │ │ │ │ + */
│ │ │ │ │ + minFrameRate: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: startTime
│ │ │ │ │ + * {Number} The timestamp of the first execution step. Used for skipping
│ │ │ │ │ + * frames
│ │ │ │ │ + */
│ │ │ │ │ + startTime: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: animationId
│ │ │ │ │ + * {int} Loop id returned by OpenLayers.Animation.start
│ │ │ │ │ + */
│ │ │ │ │ + animationId: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: playing
│ │ │ │ │ + * {Boolean} Tells if the easing is currently playing
│ │ │ │ │ + */
│ │ │ │ │ + playing: false,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Tween
│ │ │ │ │ + * Creates a Tween.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * easing - {(Function)} easing function method to use
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(easing) {
│ │ │ │ │ + this.easing = (easing) ? easing : OpenLayers.Easing.Expo.easeOut;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: start
│ │ │ │ │ + * Plays the Tween, and calls the callback method on each step
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * begin - {Object} values to start the animation with
│ │ │ │ │ + * finish - {Object} values to finish the animation with
│ │ │ │ │ + * duration - {int} duration of the tween (number of steps)
│ │ │ │ │ + * options - {Object} hash of options (callbacks (start, eachStep, done),
│ │ │ │ │ + * minFrameRate)
│ │ │ │ │ + */
│ │ │ │ │ + start: function(begin, finish, duration, options) {
│ │ │ │ │ + this.playing = true;
│ │ │ │ │ + this.begin = begin;
│ │ │ │ │ + this.finish = finish;
│ │ │ │ │ + this.duration = duration;
│ │ │ │ │ + this.callbacks = options.callbacks;
│ │ │ │ │ + this.minFrameRate = options.minFrameRate || 30;
│ │ │ │ │ + this.time = 0;
│ │ │ │ │ + this.startTime = new Date().getTime();
│ │ │ │ │ + OpenLayers.Animation.stop(this.animationId);
│ │ │ │ │ + this.animationId = null;
│ │ │ │ │ + if (this.callbacks && this.callbacks.start) {
│ │ │ │ │ + this.callbacks.start.call(this, this.begin);
│ │ │ │ │ + }
│ │ │ │ │ + this.animationId = OpenLayers.Animation.start(
│ │ │ │ │ + OpenLayers.Function.bind(this.play, this)
│ │ │ │ │ + );
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: stop
│ │ │ │ │ + * Stops the Tween, and calls the done callback
│ │ │ │ │ + * Doesn't do anything if animation is already finished
│ │ │ │ │ + */
│ │ │ │ │ + stop: function() {
│ │ │ │ │ + if (!this.playing) {
│ │ │ │ │ + return;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + if (this.callbacks && this.callbacks.done) {
│ │ │ │ │ + this.callbacks.done.call(this, this.finish);
│ │ │ │ │ + }
│ │ │ │ │ + OpenLayers.Animation.stop(this.animationId);
│ │ │ │ │ + this.animationId = null;
│ │ │ │ │ + this.playing = false;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: play
│ │ │ │ │ + * Calls the appropriate easing method
│ │ │ │ │ + */
│ │ │ │ │ + play: function() {
│ │ │ │ │ + var value = {};
│ │ │ │ │ + for (var i in this.begin) {
│ │ │ │ │ + var b = this.begin[i];
│ │ │ │ │ + var f = this.finish[i];
│ │ │ │ │ + if (b == null || f == null || isNaN(b) || isNaN(f)) {
│ │ │ │ │ + throw new TypeError('invalid value for Tween');
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + var c = f - b;
│ │ │ │ │ + value[i] = this.easing.apply(this, [this.time, b, c, this.duration]);
│ │ │ │ │ + }
│ │ │ │ │ + this.time++;
│ │ │ │ │ +
│ │ │ │ │ + if (this.callbacks && this.callbacks.eachStep) {
│ │ │ │ │ + // skip frames if frame rate drops below threshold
│ │ │ │ │ + if ((new Date().getTime() - this.startTime) / this.time <= 1000 / this.minFrameRate) {
│ │ │ │ │ + this.callbacks.eachStep.call(this, value);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + if (this.time > this.duration) {
│ │ │ │ │ + this.stop();
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Create empty functions for all easing methods.
│ │ │ │ │ + */
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Tween"
│ │ │ │ │ +});
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Namespace: OpenLayers.Easing
│ │ │ │ │ + *
│ │ │ │ │ + * Credits:
│ │ │ │ │ + * Easing Equations by Robert Penner,
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Easing = {
│ │ │ │ │ + /**
│ │ │ │ │ + * Create empty functions for all easing methods.
│ │ │ │ │ + */
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Easing"
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Namespace: OpenLayers.Easing.Linear
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Easing.Linear = {
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Function: easeIn
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * t - {Float} time
│ │ │ │ │ + * b - {Float} beginning position
│ │ │ │ │ + * c - {Float} total change
│ │ │ │ │ + * d - {Float} duration of the transition
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float}
│ │ │ │ │ + */
│ │ │ │ │ + easeIn: function(t, b, c, d) {
│ │ │ │ │ + return c * t / d + b;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Function: easeOut
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * t - {Float} time
│ │ │ │ │ + * b - {Float} beginning position
│ │ │ │ │ + * c - {Float} total change
│ │ │ │ │ + * d - {Float} duration of the transition
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float}
│ │ │ │ │ + */
│ │ │ │ │ + easeOut: function(t, b, c, d) {
│ │ │ │ │ + return c * t / d + b;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Function: easeInOut
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * t - {Float} time
│ │ │ │ │ + * b - {Float} beginning position
│ │ │ │ │ + * c - {Float} total change
│ │ │ │ │ + * d - {Float} duration of the transition
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float}
│ │ │ │ │ + */
│ │ │ │ │ + easeInOut: function(t, b, c, d) {
│ │ │ │ │ + return c * t / d + b;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Easing.Linear"
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Namespace: OpenLayers.Easing.Expo
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Easing.Expo = {
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Function: easeIn
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * t - {Float} time
│ │ │ │ │ + * b - {Float} beginning position
│ │ │ │ │ + * c - {Float} total change
│ │ │ │ │ + * d - {Float} duration of the transition
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float}
│ │ │ │ │ + */
│ │ │ │ │ + easeIn: function(t, b, c, d) {
│ │ │ │ │ + return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Function: easeOut
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * t - {Float} time
│ │ │ │ │ + * b - {Float} beginning position
│ │ │ │ │ + * c - {Float} total change
│ │ │ │ │ + * d - {Float} duration of the transition
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float}
│ │ │ │ │ + */
│ │ │ │ │ + easeOut: function(t, b, c, d) {
│ │ │ │ │ + return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Function: easeInOut
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * t - {Float} time
│ │ │ │ │ + * b - {Float} beginning position
│ │ │ │ │ + * c - {Float} total change
│ │ │ │ │ + * d - {Float} duration of the transition
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float}
│ │ │ │ │ + */
│ │ │ │ │ + easeInOut: function(t, b, c, d) {
│ │ │ │ │ + if (t == 0) return b;
│ │ │ │ │ + if (t == d) return b + c;
│ │ │ │ │ + if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
│ │ │ │ │ + return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Easing.Expo"
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Namespace: OpenLayers.Easing.Quad
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Easing.Quad = {
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Function: easeIn
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * t - {Float} time
│ │ │ │ │ + * b - {Float} beginning position
│ │ │ │ │ + * c - {Float} total change
│ │ │ │ │ + * d - {Float} duration of the transition
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float}
│ │ │ │ │ + */
│ │ │ │ │ + easeIn: function(t, b, c, d) {
│ │ │ │ │ + return c * (t /= d) * t + b;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Function: easeOut
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * t - {Float} time
│ │ │ │ │ + * b - {Float} beginning position
│ │ │ │ │ + * c - {Float} total change
│ │ │ │ │ + * d - {Float} duration of the transition
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float}
│ │ │ │ │ + */
│ │ │ │ │ + easeOut: function(t, b, c, d) {
│ │ │ │ │ + return -c * (t /= d) * (t - 2) + b;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Function: easeInOut
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * t - {Float} time
│ │ │ │ │ + * b - {Float} beginning position
│ │ │ │ │ + * c - {Float} total change
│ │ │ │ │ + * d - {Float} duration of the transition
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Float}
│ │ │ │ │ + */
│ │ │ │ │ + easeInOut: function(t, b, c, d) {
│ │ │ │ │ + if ((t /= d / 2) < 1) return c / 2 * t * t + b;
│ │ │ │ │ + return -c / 2 * ((--t) * (t - 2) - 1) + b;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Easing.Quad"
│ │ │ │ │ +};
│ │ │ │ │ +/* ======================================================================
│ │ │ │ │ + OpenLayers/Projection.js
│ │ │ │ │ + ====================================================================== */
│ │ │ │ │ +
│ │ │ │ │ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + * @requires OpenLayers/Util.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Namespace: OpenLayers.Projection
│ │ │ │ │ + * Methods for coordinate transforms between coordinate systems. By default,
│ │ │ │ │ + * OpenLayers ships with the ability to transform coordinates between
│ │ │ │ │ + * geographic (EPSG:4326) and web or spherical mercator (EPSG:900913 et al.)
│ │ │ │ │ + * coordinate reference systems. See the method for details
│ │ │ │ │ + * on usage.
│ │ │ │ │ + *
│ │ │ │ │ + * Additional transforms may be added by using the
│ │ │ │ │ + * library. If the proj4js library is included, the method
│ │ │ │ │ + * will work between any two coordinate reference systems with proj4js
│ │ │ │ │ + * definitions.
│ │ │ │ │ + *
│ │ │ │ │ + * If the proj4js library is not included, or if you wish to allow transforms
│ │ │ │ │ + * between arbitrary coordinate reference systems, use the
│ │ │ │ │ + * method to register a custom transform method.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Projection = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: proj
│ │ │ │ │ + * {Object} Proj4js.Proj instance.
│ │ │ │ │ + */
│ │ │ │ │ + proj: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: projCode
│ │ │ │ │ + * {String}
│ │ │ │ │ + */
│ │ │ │ │ + projCode: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: titleRegEx
│ │ │ │ │ + * {RegExp} regular expression to strip the title from a proj4js definition
│ │ │ │ │ + */
│ │ │ │ │ + titleRegEx: /\+title=[^\+]*/,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constructor: OpenLayers.Projection
│ │ │ │ │ + * This class offers several methods for interacting with a wrapped
│ │ │ │ │ + * pro4js projection object.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * projCode - {String} A string identifying the Well Known Identifier for
│ │ │ │ │ + * the projection.
│ │ │ │ │ + * options - {Object} An optional object to set additional properties
│ │ │ │ │ + * on the projection.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {} A projection object.
│ │ │ │ │ + */
│ │ │ │ │ + initialize: function(projCode, options) {
│ │ │ │ │ + OpenLayers.Util.extend(this, options);
│ │ │ │ │ + this.projCode = projCode;
│ │ │ │ │ + if (typeof Proj4js == "object") {
│ │ │ │ │ + this.proj = new Proj4js.Proj(projCode);
│ │ │ │ │ + }
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getCode
│ │ │ │ │ + * Get the string SRS code.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {String} The SRS code.
│ │ │ │ │ + */
│ │ │ │ │ + getCode: function() {
│ │ │ │ │ + return this.proj ? this.proj.srsCode : this.projCode;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIMethod: getUnits
│ │ │ │ │ + * Get the units string for the projection -- returns null if
│ │ │ │ │ + * proj4js is not available.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {String} The units abbreviation.
│ │ │ │ │ + */
│ │ │ │ │ + getUnits: function() {
│ │ │ │ │ + return this.proj ? this.proj.units : null;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: toString
│ │ │ │ │ + * Convert projection to string (getCode wrapper).
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {String} The projection code.
│ │ │ │ │ + */
│ │ │ │ │ + toString: function() {
│ │ │ │ │ + return this.getCode();
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Method: equals
│ │ │ │ │ + * Test equality of two projection instances. Determines equality based
│ │ │ │ │ + * soley on the projection code.
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * {Boolean} The two projections are equivalent.
│ │ │ │ │ + */
│ │ │ │ │ + equals: function(projection) {
│ │ │ │ │ + var p = projection,
│ │ │ │ │ + equals = false;
│ │ │ │ │ + if (p) {
│ │ │ │ │ + if (!(p instanceof OpenLayers.Projection)) {
│ │ │ │ │ + p = new OpenLayers.Projection(p);
│ │ │ │ │ + }
│ │ │ │ │ + if ((typeof Proj4js == "object") && this.proj.defData && p.proj.defData) {
│ │ │ │ │ + equals = this.proj.defData.replace(this.titleRegEx, "") ==
│ │ │ │ │ + p.proj.defData.replace(this.titleRegEx, "");
│ │ │ │ │ + } else if (p.getCode) {
│ │ │ │ │ + var source = this.getCode(),
│ │ │ │ │ + target = p.getCode();
│ │ │ │ │ + equals = source == target ||
│ │ │ │ │ + !!OpenLayers.Projection.transforms[source] &&
│ │ │ │ │ + OpenLayers.Projection.transforms[source][target] ===
│ │ │ │ │ + OpenLayers.Projection.nullTransform;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return equals;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /* Method: destroy
│ │ │ │ │ + * Destroy projection object.
│ │ │ │ │ + */
│ │ │ │ │ + destroy: function() {
│ │ │ │ │ + delete this.proj;
│ │ │ │ │ + delete this.projCode;
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + CLASS_NAME: "OpenLayers.Projection"
│ │ │ │ │ +});
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Property: transforms
│ │ │ │ │ + * {Object} Transforms is an object, with from properties, each of which may
│ │ │ │ │ + * have a to property. This allows you to define projections without
│ │ │ │ │ + * requiring support for proj4js to be included.
│ │ │ │ │ + *
│ │ │ │ │ + * This object has keys which correspond to a 'source' projection object. The
│ │ │ │ │ + * keys should be strings, corresponding to the projection.getCode() value.
│ │ │ │ │ + * Each source projection object should have a set of destination projection
│ │ │ │ │ + * keys included in the object.
│ │ │ │ │ + *
│ │ │ │ │ + * Each value in the destination object should be a transformation function,
│ │ │ │ │ + * where the function is expected to be passed an object with a .x and a .y
│ │ │ │ │ + * property. The function should return the object, with the .x and .y
│ │ │ │ │ + * transformed according to the transformation function.
│ │ │ │ │ + *
│ │ │ │ │ + * Note - Properties on this object should not be set directly. To add a
│ │ │ │ │ + * transform method to this object, use the method. For an
│ │ │ │ │ + * example of usage, see the OpenLayers.Layer.SphericalMercator file.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Projection.transforms = {};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * APIProperty: defaults
│ │ │ │ │ + * {Object} Defaults for the SRS codes known to OpenLayers (currently
│ │ │ │ │ + * EPSG:4326, CRS:84, urn:ogc:def:crs:EPSG:6.6:4326, EPSG:900913, EPSG:3857,
│ │ │ │ │ + * EPSG:102113 and EPSG:102100). Keys are the SRS code, values are units,
│ │ │ │ │ + * maxExtent (the validity extent for the SRS) and yx (true if this SRS is
│ │ │ │ │ + * known to have a reverse axis order).
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Projection.defaults = {
│ │ │ │ │ + "EPSG:4326": {
│ │ │ │ │ + units: "degrees",
│ │ │ │ │ + maxExtent: [-180, -90, 180, 90],
│ │ │ │ │ + yx: true
│ │ │ │ │ + },
│ │ │ │ │ + "CRS:84": {
│ │ │ │ │ + units: "degrees",
│ │ │ │ │ + maxExtent: [-180, -90, 180, 90]
│ │ │ │ │ + },
│ │ │ │ │ + "EPSG:900913": {
│ │ │ │ │ + units: "m",
│ │ │ │ │ + maxExtent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34]
│ │ │ │ │ + }
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * APIMethod: addTransform
│ │ │ │ │ + * Set a custom transform method between two projections. Use this method in
│ │ │ │ │ + * cases where the proj4js lib is not available or where custom projections
│ │ │ │ │ + * need to be handled.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * from - {String} The code for the source projection
│ │ │ │ │ + * to - {String} the code for the destination projection
│ │ │ │ │ + * method - {Function} A function that takes a point as an argument and
│ │ │ │ │ + * transforms that point from the source to the destination projection
│ │ │ │ │ + * in place. The original point should be modified.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Projection.addTransform = function(from, to, method) {
│ │ │ │ │ + if (method === OpenLayers.Projection.nullTransform) {
│ │ │ │ │ + var defaults = OpenLayers.Projection.defaults[from];
│ │ │ │ │ + if (defaults && !OpenLayers.Projection.defaults[to]) {
│ │ │ │ │ + OpenLayers.Projection.defaults[to] = defaults;
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + if (!OpenLayers.Projection.transforms[from]) {
│ │ │ │ │ + OpenLayers.Projection.transforms[from] = {};
│ │ │ │ │ + }
│ │ │ │ │ + OpenLayers.Projection.transforms[from][to] = method;
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * APIMethod: transform
│ │ │ │ │ + * Transform a point coordinate from one projection to another. Note that
│ │ │ │ │ + * the input point is transformed in place.
│ │ │ │ │ + *
│ │ │ │ │ + * Parameters:
│ │ │ │ │ + * point - { | Object} An object with x and y
│ │ │ │ │ + * properties representing coordinates in those dimensions.
│ │ │ │ │ + * source - {OpenLayers.Projection} Source map coordinate system
│ │ │ │ │ + * dest - {OpenLayers.Projection} Destination map coordinate system
│ │ │ │ │ + *
│ │ │ │ │ + * Returns:
│ │ │ │ │ + * point - {object} A transformed coordinate. The original point is modified.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Projection.transform = function(point, source, dest) {
│ │ │ │ │ + if (source && dest) {
│ │ │ │ │ + if (!(source instanceof OpenLayers.Projection)) {
│ │ │ │ │ + source = new OpenLayers.Projection(source);
│ │ │ │ │ + }
│ │ │ │ │ + if (!(dest instanceof OpenLayers.Projection)) {
│ │ │ │ │ + dest = new OpenLayers.Projection(dest);
│ │ │ │ │ + }
│ │ │ │ │ + if (source.proj && dest.proj) {
│ │ │ │ │ + point = Proj4js.transform(source.proj, dest.proj, point);
│ │ │ │ │ + } else {
│ │ │ │ │ + var sourceCode = source.getCode();
│ │ │ │ │ + var destCode = dest.getCode();
│ │ │ │ │ + var transforms = OpenLayers.Projection.transforms;
│ │ │ │ │ + if (transforms[sourceCode] && transforms[sourceCode][destCode]) {
│ │ │ │ │ + transforms[sourceCode][destCode](point);
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + }
│ │ │ │ │ + return point;
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * APIFunction: nullTransform
│ │ │ │ │ + * A null transformation - useful for defining projection aliases when
│ │ │ │ │ + * proj4js is not available:
│ │ │ │ │ + *
│ │ │ │ │ + * (code)
│ │ │ │ │ + * OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:900913",
│ │ │ │ │ + * OpenLayers.Projection.nullTransform);
│ │ │ │ │ + * OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:3857",
│ │ │ │ │ + * OpenLayers.Projection.nullTransform);
│ │ │ │ │ + * (end)
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Projection.nullTransform = function(point) {
│ │ │ │ │ + return point;
│ │ │ │ │ +};
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Note: Transforms for web mercator <-> geographic
│ │ │ │ │ + * OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113 and EPSG:102100.
│ │ │ │ │ + * OpenLayers originally started referring to EPSG:900913 as web mercator.
│ │ │ │ │ + * The EPSG has declared EPSG:3857 to be web mercator.
│ │ │ │ │ + * ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as
│ │ │ │ │ + * equivalent. See http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2009/11/20/ArcGIS-Online-moving-to-Google-_2F00_-Bing-tiling-scheme_3A00_-What-does-this-mean-for-you_3F00_.aspx#12084.
│ │ │ │ │ + * For geographic, OpenLayers recognizes EPSG:4326, CRS:84 and
│ │ │ │ │ + * urn:ogc:def:crs:EPSG:6.6:4326. OpenLayers also knows about the reverse axis
│ │ │ │ │ + * order for EPSG:4326.
│ │ │ │ │ + */
│ │ │ │ │ +(function() {
│ │ │ │ │ +
│ │ │ │ │ + var pole = 20037508.34;
│ │ │ │ │ +
│ │ │ │ │ + function inverseMercator(xy) {
│ │ │ │ │ + xy.x = 180 * xy.x / pole;
│ │ │ │ │ + xy.y = 180 / Math.PI * (2 * Math.atan(Math.exp((xy.y / pole) * Math.PI)) - Math.PI / 2);
│ │ │ │ │ + return xy;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + function forwardMercator(xy) {
│ │ │ │ │ + xy.x = xy.x * pole / 180;
│ │ │ │ │ + var y = Math.log(Math.tan((90 + xy.y) * Math.PI / 360)) / Math.PI * pole;
│ │ │ │ │ + xy.y = Math.max(-20037508.34, Math.min(y, 20037508.34));
│ │ │ │ │ + return xy;
│ │ │ │ │ + }
│ │ │ │ │ +
│ │ │ │ │ + function map(base, codes) {
│ │ │ │ │ + var add = OpenLayers.Projection.addTransform;
│ │ │ │ │ + var same = OpenLayers.Projection.nullTransform;
│ │ │ │ │ + var i, len, code, other, j;
│ │ │ │ │ + for (i = 0, len = codes.length; i < 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"],
│ │ │ │ │ + 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-2013 by OpenLayers Contributors (see authors.txt for
│ │ │ │ │ + * full list of contributors). Published under the 2-clause BSD license.
│ │ │ │ │ + * See license.txt in the OpenLayers distribution or repository for the
│ │ │ │ │ + * full text of the license. */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * @requires OpenLayers/BaseTypes/Class.js
│ │ │ │ │ + * @requires OpenLayers/Util.js
│ │ │ │ │ + * @requires OpenLayers/Util/vendorPrefix.js
│ │ │ │ │ + * @requires OpenLayers/Events.js
│ │ │ │ │ + * @requires OpenLayers/Tween.js
│ │ │ │ │ + * @requires OpenLayers/Projection.js
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ +/**
│ │ │ │ │ + * Class: OpenLayers.Map
│ │ │ │ │ + * Instances of OpenLayers.Map are interactive maps embedded in a web page.
│ │ │ │ │ + * Create a new map with the constructor.
│ │ │ │ │ + *
│ │ │ │ │ + * On their own maps do not provide much functionality. To extend a map
│ │ │ │ │ + * it's necessary to add controls () and
│ │ │ │ │ + * layers () to the map.
│ │ │ │ │ + */
│ │ │ │ │ +OpenLayers.Map = OpenLayers.Class({
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Constant: Z_INDEX_BASE
│ │ │ │ │ + * {Object} Base z-indexes for different classes of thing
│ │ │ │ │ + */
│ │ │ │ │ + Z_INDEX_BASE: {
│ │ │ │ │ + BaseLayer: 100,
│ │ │ │ │ + Overlay: 325,
│ │ │ │ │ + Feature: 725,
│ │ │ │ │ + Popup: 750,
│ │ │ │ │ + Control: 1000
│ │ │ │ │ + },
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: events
│ │ │ │ │ + * {}
│ │ │ │ │ + *
│ │ │ │ │ + * Register a listener for a particular event with the following syntax:
│ │ │ │ │ + * (code)
│ │ │ │ │ + * map.events.register(type, obj, listener);
│ │ │ │ │ + * (end)
│ │ │ │ │ + *
│ │ │ │ │ + * Listeners will be called with a reference to an event object. The
│ │ │ │ │ + * properties of this event depends on exactly what happened.
│ │ │ │ │ + *
│ │ │ │ │ + * All event objects have at least the following properties:
│ │ │ │ │ + * object - {Object} A reference to map.events.object.
│ │ │ │ │ + * element - {DOMElement} A reference to map.events.element.
│ │ │ │ │ + *
│ │ │ │ │ + * Browser events have the following additional properties:
│ │ │ │ │ + * xy - {} The pixel location of the event (relative
│ │ │ │ │ + * to the the map viewport).
│ │ │ │ │ + *
│ │ │ │ │ + * Supported map event types:
│ │ │ │ │ + * preaddlayer - triggered before a layer has been added. The event
│ │ │ │ │ + * object will include a *layer* property that references the layer
│ │ │ │ │ + * to be added. When a listener returns "false" the adding will be
│ │ │ │ │ + * aborted.
│ │ │ │ │ + * addlayer - triggered after a layer has been added. The event object
│ │ │ │ │ + * will include a *layer* property that references the added layer.
│ │ │ │ │ + * preremovelayer - triggered before a layer has been removed. The event
│ │ │ │ │ + * object will include a *layer* property that references the layer
│ │ │ │ │ + * to be removed. When a listener returns "false" the removal will be
│ │ │ │ │ + * aborted.
│ │ │ │ │ + * removelayer - triggered after a layer has been removed. The event
│ │ │ │ │ + * object will include a *layer* property that references the removed
│ │ │ │ │ + * layer.
│ │ │ │ │ + * changelayer - triggered after a layer name change, order change,
│ │ │ │ │ + * opacity change, params change, visibility change (actual visibility,
│ │ │ │ │ + * not the layer's visibility property) or attribution change (due to
│ │ │ │ │ + * extent change). Listeners will receive an event object with *layer*
│ │ │ │ │ + * and *property* properties. The *layer* property will be a reference
│ │ │ │ │ + * to the changed layer. The *property* property will be a key to the
│ │ │ │ │ + * changed property (name, order, opacity, params, visibility or
│ │ │ │ │ + * attribution).
│ │ │ │ │ + * movestart - triggered after the start of a drag, pan, or zoom. The event
│ │ │ │ │ + * object may include a *zoomChanged* property that tells whether the
│ │ │ │ │ + * zoom has changed.
│ │ │ │ │ + * move - triggered after each drag, pan, or zoom
│ │ │ │ │ + * moveend - triggered after a drag, pan, or zoom completes
│ │ │ │ │ + * zoomend - triggered after a zoom completes
│ │ │ │ │ + * mouseover - triggered after mouseover the map
│ │ │ │ │ + * mouseout - triggered after mouseout the map
│ │ │ │ │ + * mousemove - triggered after mousemove the map
│ │ │ │ │ + * changebaselayer - triggered after the base layer changes
│ │ │ │ │ + * updatesize - triggered after the method was executed
│ │ │ │ │ + */
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: id
│ │ │ │ │ + * {String} Unique identifier for the map
│ │ │ │ │ + */
│ │ │ │ │ + id: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: fractionalZoom
│ │ │ │ │ + * {Boolean} For a base layer that supports it, allow the map resolution
│ │ │ │ │ + * to be set to a value between one of the values in the resolutions
│ │ │ │ │ + * array. Default is false.
│ │ │ │ │ + *
│ │ │ │ │ + * When fractionalZoom is set to true, it is possible to zoom to
│ │ │ │ │ + * an arbitrary extent. This requires a base layer from a source
│ │ │ │ │ + * that supports requests for arbitrary extents (i.e. not cached
│ │ │ │ │ + * tiles on a regular lattice). This means that fractionalZoom
│ │ │ │ │ + * will not work with commercial layers (Google, Yahoo, VE), layers
│ │ │ │ │ + * using TileCache, or any other pre-cached data sources.
│ │ │ │ │ + *
│ │ │ │ │ + * If you are using fractionalZoom, then you should also use
│ │ │ │ │ + * instead of layer.resolutions[zoom] as the
│ │ │ │ │ + * former works for non-integer zoom levels.
│ │ │ │ │ + */
│ │ │ │ │ + fractionalZoom: false,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: events
│ │ │ │ │ + * {} An events object that handles all
│ │ │ │ │ + * events on the map
│ │ │ │ │ + */
│ │ │ │ │ + events: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: allOverlays
│ │ │ │ │ + * {Boolean} Allow the map to function with "overlays" only. Defaults to
│ │ │ │ │ + * false. If true, the lowest layer in the draw order will act as
│ │ │ │ │ + * the base layer. In addition, if set to true, all layers will
│ │ │ │ │ + * have isBaseLayer set to false when they are added to the map.
│ │ │ │ │ + *
│ │ │ │ │ + * Note:
│ │ │ │ │ + * If you set map.allOverlays to true, then you *cannot* use
│ │ │ │ │ + * map.setBaseLayer or layer.setIsBaseLayer. With allOverlays true,
│ │ │ │ │ + * the lowest layer in the draw layer is the base layer. So, to change
│ │ │ │ │ + * the base layer, use or to set the layer
│ │ │ │ │ + * index to 0.
│ │ │ │ │ + */
│ │ │ │ │ + allOverlays: false,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: div
│ │ │ │ │ + * {DOMElement|String} The element that contains the map (or an id for
│ │ │ │ │ + * that element). If the constructor is called
│ │ │ │ │ + * with two arguments, this should be provided as the first argument.
│ │ │ │ │ + * Alternatively, the map constructor can be called with the options
│ │ │ │ │ + * object as the only argument. In this case (one argument), a
│ │ │ │ │ + * div property may or may not be provided. If the div property
│ │ │ │ │ + * is not provided, the map can be rendered to a container later
│ │ │ │ │ + * using the method.
│ │ │ │ │ + *
│ │ │ │ │ + * Note:
│ │ │ │ │ + * If you are calling after map construction, do not use
│ │ │ │ │ + * auto. Instead, divide your by your
│ │ │ │ │ + * maximum expected dimension.
│ │ │ │ │ + */
│ │ │ │ │ + div: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: dragging
│ │ │ │ │ + * {Boolean} The map is currently being dragged.
│ │ │ │ │ + */
│ │ │ │ │ + dragging: false,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: size
│ │ │ │ │ + * {} Size of the main div (this.div)
│ │ │ │ │ + */
│ │ │ │ │ + size: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: viewPortDiv
│ │ │ │ │ + * {HTMLDivElement} The element that represents the map viewport
│ │ │ │ │ + */
│ │ │ │ │ + viewPortDiv: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: layerContainerOrigin
│ │ │ │ │ + * {} The lonlat at which the later container was
│ │ │ │ │ + * re-initialized (on-zoom)
│ │ │ │ │ + */
│ │ │ │ │ + layerContainerOrigin: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * Property: layerContainerDiv
│ │ │ │ │ + * {HTMLDivElement} The element that contains the layers.
│ │ │ │ │ + */
│ │ │ │ │ + layerContainerDiv: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: layers
│ │ │ │ │ + * {Array()} Ordered list of layers in the map
│ │ │ │ │ + */
│ │ │ │ │ + layers: null,
│ │ │ │ │ +
│ │ │ │ │ + /**
│ │ │ │ │ + * APIProperty: controls
│ │ │ │ │ + * {Array()} List of controls associated with the map.
│ │ │ │ │ + *
│ │ │ │ │ + * If not provided in the map options at construction, the map will
│ │ │ │ │ + * by default be given the following controls if present in the build:
│ │ │ │ │ + * - or
│ │ │ │ │ + * - or
│ │ │ │ │ + * -