vendor/assets/javascripts/openlayers/OpenLayers.js in openlayers-rails-0.0.3 vs vendor/assets/javascripts/openlayers/OpenLayers.js in openlayers-rails-0.0.4
- old
+ new
@@ -57,20 +57,20 @@
*/
/* ======================================================================
OpenLayers/SingleFile.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
var OpenLayers = {
/**
* Constant: VERSION_NUMBER
*/
- VERSION_NUMBER: "Release 2.13 dev",
+ VERSION_NUMBER: "Release 2.14 dev",
/**
* Constant: singleFile
* TODO: remove this in 3.0 when we stop supporting build profiles that
* include OpenLayers.js
@@ -139,11 +139,11 @@
};
/* ======================================================================
OpenLayers/BaseTypes/Class.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -264,11 +264,11 @@
};
/* ======================================================================
OpenLayers/BaseTypes.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -393,11 +393,13 @@
var subs = match.split(/\.+/);
for (var i=0; i< subs.length; i++) {
if (i == 0) {
replacement = context;
}
-
+ if (replacement === undefined) {
+ break;
+ }
replacement = replacement[subs[i]];
}
if(typeof replacement == "function") {
replacement = args ?
@@ -729,11 +731,11 @@
};
/* ======================================================================
OpenLayers/BaseTypes/Bounds.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -794,11 +796,11 @@
*
* Parameters (four arguments):
* left - {Number} The left bounds of the box. Note that for width
* calculations, this is assumed to be less than the right value.
* bottom - {Number} The bottom bounds of the box. Note that for height
- * calculations, this is assumed to be more than the top value.
+ * calculations, this is assumed to be less than the top value.
* right - {Number} The right bounds.
* top - {Number} The top bounds.
*
* Parameters (single argument):
* bounds - {Array(Number)} [left, bottom, right, top]
@@ -895,11 +897,11 @@
/**
* APIMethod: toBBOX
* Returns a boundingbox-string representation of the bounds object.
*
* Parameters:
- * decimal - {Integer} How many significant digits in the bbox coords?
+ * decimal - {Integer} How many decimal places in the bbox coords?
* Default is 6
* reverseAxisOrder - {Boolean} Should we reverse the axis order?
*
* Returns:
* {String} Simple String representation of bounds object.
@@ -1086,47 +1088,67 @@
* object - {<OpenLayers.LonLat>, <OpenLayers.Geometry.Point> or
* <OpenLayers.Bounds>} The object to be included in the new bounds
* object.
*/
extend:function(object) {
- var bounds = null;
if (object) {
- // clear cached center location
switch(object.CLASS_NAME) {
- case "OpenLayers.LonLat":
- bounds = new OpenLayers.Bounds(object.lon, object.lat,
- object.lon, object.lat);
+ case "OpenLayers.LonLat":
+ this.extendXY(object.lon, object.lat);
break;
case "OpenLayers.Geometry.Point":
- bounds = new OpenLayers.Bounds(object.x, object.y,
- object.x, object.y);
+ this.extendXY(object.x, object.y);
break;
-
- case "OpenLayers.Bounds":
- bounds = object;
+
+ case "OpenLayers.Bounds":
+ // clear cached center location
+ this.centerLonLat = null;
+
+ if ( (this.left == null) || (object.left < this.left)) {
+ this.left = object.left;
+ }
+ if ( (this.bottom == null) || (object.bottom < this.bottom) ) {
+ this.bottom = object.bottom;
+ }
+ if ( (this.right == null) || (object.right > this.right) ) {
+ this.right = object.right;
+ }
+ if ( (this.top == null) || (object.top > this.top) ) {
+ this.top = object.top;
+ }
break;
}
-
- if (bounds) {
- this.centerLonLat = null;
- if ( (this.left == null) || (bounds.left < this.left)) {
- this.left = bounds.left;
- }
- if ( (this.bottom == null) || (bounds.bottom < this.bottom) ) {
- this.bottom = bounds.bottom;
- }
- if ( (this.right == null) || (bounds.right > this.right) ) {
- this.right = bounds.right;
- }
- if ( (this.top == null) || (bounds.top > this.top) ) {
- this.top = bounds.top;
- }
- }
}
},
/**
+ * APIMethod: extendXY
+ * Extend the bounds to include the XY coordinate specified.
+ *
+ * Parameters:
+ * x - {number} The X part of the the coordinate.
+ * y - {number} The Y part of the the coordinate.
+ */
+ extendXY:function(x, y) {
+ // clear cached center location
+ this.centerLonLat = null;
+
+ if ((this.left == null) || (x < this.left)) {
+ this.left = x;
+ }
+ if ((this.bottom == null) || (y < this.bottom)) {
+ this.bottom = y;
+ }
+ if ((this.right == null) || (x > this.right)) {
+ this.right = x;
+ }
+ if ((this.top == null) || (y > this.top)) {
+ this.top = y;
+ }
+ },
+
+ /**
* APIMethod: containsLonLat
* Returns whether the bounds object contains the given <OpenLayers.LonLat>.
*
* Parameters:
* ll - {<OpenLayers.LonLat>|Object} OpenLayers.LonLat or an
@@ -1550,11 +1572,11 @@
};
/* ======================================================================
OpenLayers/BaseTypes/Element.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -1743,11 +1765,11 @@
};
/* ======================================================================
OpenLayers/BaseTypes/LonLat.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -1962,11 +1984,11 @@
};
/* ======================================================================
OpenLayers/BaseTypes/Pixel.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -2109,11 +2131,11 @@
});
/* ======================================================================
OpenLayers/BaseTypes/Size.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -2202,11 +2224,11 @@
});
/* ======================================================================
OpenLayers/Console.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -2456,11 +2478,11 @@
})();
/* ======================================================================
OpenLayers/Lang.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -2594,11 +2616,11 @@
OpenLayers.i18n = OpenLayers.Lang.translate;
/* ======================================================================
OpenLayers/Util.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -3462,15 +3484,21 @@
*
* Parameters:
* url - {String} Optional url used to extract the query string.
* If url is null or is not supplied, query string is taken
* from the page location.
+ * options - {Object} Additional options. Optional.
+ *
+ * Valid options:
+ * splitArgs - {Boolean} Split comma delimited params into arrays? Default is
+ * true.
*
* Returns:
* {Object} An object of key/value pairs from the query string.
*/
-OpenLayers.Util.getParameters = function(url) {
+OpenLayers.Util.getParameters = function(url, options) {
+ options = options || {};
// if no url specified, take it from the location bar
url = (url === null || url === undefined) ? window.location.href : url;
//parse out parameters portion of url string
var paramsString = "";
@@ -3502,11 +3530,13 @@
} catch (err) {
value = unescape(value);
}
// follow OGC convention of comma delimited values
- value = value.split(",");
+ if (options.splitArgs !== false) {
+ value = value.split(",");
+ }
//if there's only one value, do not return as array
if (value.length == 1) {
value = value[0];
}
@@ -3895,11 +3925,12 @@
options = options || {};
OpenLayers.Util.applyDefaults(options, {
ignoreCase: true,
ignorePort80: true,
- ignoreHash: true
+ ignoreHash: true,
+ splitArgs: false
});
var urlObj1 = OpenLayers.Util.createUrlObject(url1, options);
var urlObj2 = OpenLayers.Util.createUrlObject(url2, options);
@@ -3936,10 +3967,12 @@
*
* Valid options:
* ignoreCase - {Boolean} lowercase url,
* ignorePort80 - {Boolean} don't include explicit port if port is 80,
* ignoreHash - {Boolean} Don't include part of url after the hash (#).
+ * splitArgs - {Boolean} Split comma delimited params into arrays? Default is
+ * true.
*
* Returns:
* {Object} An object with separate url, a, port, host, and args parsed out
* and ready for comparison
*/
@@ -3991,11 +4024,12 @@
var queryString = a.search;
if (!queryString) {
var qMark = url.indexOf("?");
queryString = (qMark != -1) ? url.substr(qMark) : "";
}
- urlObject.args = OpenLayers.Util.getParameters(queryString);
+ urlObject.args = OpenLayers.Util.getParameters(queryString,
+ {splitArgs: options.splitArgs});
// pathname
//
// This is a workaround for Internet Explorer where
// window.location.pathname has a leading "/", but
@@ -4355,15 +4389,41 @@
str += coordinate < 0 ? OpenLayers.i18n("S") : OpenLayers.i18n("N");
}
return str;
};
+/**
+ * Function: getConstructor
+ * Take an OpenLayers style CLASS_NAME and return a constructor.
+ *
+ * Parameters:
+ * className - {String} The dot delimited class name (e.g. 'OpenLayers.Foo').
+ *
+ * Returns:
+ * {Function} The constructor.
+ */
+OpenLayers.Util.getConstructor = function(className) {
+ var Constructor;
+ var parts = className.split('.');
+ if (parts[0] === "OpenLayers") {
+ Constructor = OpenLayers;
+ } else {
+ // someone extended our base class and used their own namespace
+ // this will not work when the library is evaluated in a closure
+ // but it is the best we can do (until we ourselves provide a global)
+ Constructor = window[parts[0]];
+ }
+ for (var i = 1, ii = parts.length; i < ii; ++i) {
+ Constructor = Constructor[parts[i]];
+ }
+ return Constructor;
+};
/* ======================================================================
OpenLayers/Format.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -4486,11 +4546,11 @@
});
/* ======================================================================
OpenLayers/Format/XML.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -5514,11 +5574,11 @@
};
/* ======================================================================
OpenLayers/Feature.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -5743,11 +5803,11 @@
});
/* ======================================================================
OpenLayers/Feature/Vector.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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
@@ -5817,11 +5877,11 @@
style: null,
/**
* APIProperty: url
* {String} If this property is set it will be taken into account by
- * {<OpenLayers.HTTP>} when upadting or deleting the feature.
+ * {<OpenLayers.HTTP>} when updating or deleting the feature.
*/
url: null,
/**
* Property: renderIntent
@@ -6167,11 +6227,12 @@
* 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 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.
@@ -6256,11 +6317,11 @@
};
/* ======================================================================
OpenLayers/Geometry.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -6696,25 +6757,52 @@
* point coordinates.
* segment - {Object} An object with x1, y1, x2, and y2 properties
* representing endpoint coordinates.
*
* Returns:
- * {Object} An object with distance, x, and y properties. The distance
+ * {Object} An object with distance, along, x, and y properties. The distance
* will be the shortest distance between the input point and segment.
* The x and y properties represent the coordinates along the segment
- * where the shortest distance meets the segment.
+ * where the shortest distance meets the segment. The along attribute
+ * describes how far between the two segment points the given point is.
*/
OpenLayers.Geometry.distanceToSegment = function(point, segment) {
+ var result = OpenLayers.Geometry.distanceSquaredToSegment(point, segment);
+ result.distance = Math.sqrt(result.distance);
+ return result;
+};
+
+/**
+ * Function: OpenLayers.Geometry.distanceSquaredToSegment
+ *
+ * Usually the distanceToSegment function should be used. This variant however
+ * can be used for comparisons where the exact distance is not important.
+ *
+ * Parameters:
+ * point - {Object} An object with x and y properties representing the
+ * point coordinates.
+ * segment - {Object} An object with x1, y1, x2, and y2 properties
+ * representing endpoint coordinates.
+ *
+ * Returns:
+ * {Object} An object with squared distance, along, x, and y properties.
+ * The distance will be the shortest distance between the input point and
+ * segment. The x and y properties represent the coordinates along the
+ * segment where the shortest distance meets the segment. The along
+ * attribute describes how far between the two segment points the given
+ * point is.
+ */
+OpenLayers.Geometry.distanceSquaredToSegment = function(point, segment) {
var x0 = point.x;
var y0 = point.y;
var x1 = segment.x1;
var y1 = segment.y1;
var x2 = segment.x2;
var y2 = segment.y2;
var dx = x2 - x1;
var dy = y2 - y1;
- var along = ((dx * (x0 - x1)) + (dy * (y0 - y1))) /
+ var along = (dx == 0 && dy == 0) ? 0 : ((dx * (x0 - x1)) + (dy * (y0 - y1))) /
(Math.pow(dx, 2) + Math.pow(dy, 2));
var x, y;
if(along <= 0.0) {
x = x1;
y = y1;
@@ -6724,19 +6812,20 @@
} else {
x = x1 + along * dx;
y = y1 + along * dy;
}
return {
- distance: Math.sqrt(Math.pow(x - x0, 2) + Math.pow(y - y0, 2)),
- x: x, y: y
+ distance: Math.pow(x - x0, 2) + Math.pow(y - y0, 2),
+ x: x, y: y,
+ along: along
};
};
/* ======================================================================
OpenLayers/Geometry/Point.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -7019,11 +7108,11 @@
});
/* ======================================================================
OpenLayers/Geometry/Collection.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -7096,11 +7185,12 @@
*
* Returns:
* {<OpenLayers.Geometry.Collection>} An exact clone of this collection
*/
clone: function() {
- var geometry = eval("new " + this.CLASS_NAME + "()");
+ var Constructor = OpenLayers.Util.getConstructor(this.CLASS_NAME);
+ var geometry = new Constructor();
for(var i=0, len=this.components.length; i<len; i++) {
geometry.addComponent(this.components[i].clone());
}
// catch any randomly tagged-on properties
@@ -7586,11 +7676,11 @@
});
/* ======================================================================
OpenLayers/Geometry/MultiPoint.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -7656,11 +7746,11 @@
});
/* ======================================================================
OpenLayers/Geometry/Curve.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -7749,11 +7839,11 @@
});
/* ======================================================================
OpenLayers/Geometry/LineString.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -8209,30 +8299,26 @@
for(var i=0, len=segs.length; i<len; ++i) {
seg = segs[i];
result = OpenLayers.Geometry.distanceToSegment(geometry, seg);
if(result.distance < min) {
min = result.distance;
- best = result;
+ if(details) {
+ best = {
+ distance: min,
+ x0: result.x, y0: result.y,
+ x1: x, y1: y,
+ index: i,
+ indexDistance: new OpenLayers.Geometry.Point(seg.x1, seg.y1).distanceTo(geometry)
+ };
+ } else {
+ best = min;
+ }
if(min === 0) {
break;
}
- } else {
- // if distance increases and we cross y0 to the right of x0, no need to keep looking.
- if(seg.x2 > x && ((y > seg.y1 && y < seg.y2) || (y < seg.y1 && y > seg.y2))) {
- break;
- }
}
}
- if(details) {
- best = {
- distance: best.distance,
- x0: best.x, y0: best.y,
- x1: x, y1: y
- };
- } else {
- best = best.distance;
- }
} else if(geometry instanceof OpenLayers.Geometry.LineString) {
var segs0 = this.getSortedSegments();
var segs1 = geometry.getSortedSegments();
var seg0, seg1, intersection, x0, y0;
var len1 = segs1.length;
@@ -8399,11 +8485,11 @@
});
/* ======================================================================
OpenLayers/Geometry/LinearRing.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -8836,11 +8922,11 @@
});
/* ======================================================================
OpenLayers/Geometry/Polygon.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -9095,11 +9181,11 @@
};
/* ======================================================================
OpenLayers/Events.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -9663,10 +9749,11 @@
this.object = object;
this.fallThrough = fallThrough;
this.listeners = {};
this.extensions = {};
this.extensionCount = {};
+ this._msTouches = [];
// if a dom element is specified, add a listeners list
// for browser events on the element and register them
if (element != null) {
this.attachToElement(element);
@@ -9729,15 +9816,20 @@
this.clearMouseListener = OpenLayers.Function.bind(
this.clearMouseCache, this
);
}
this.element = element;
+ var msTouch = !!window.navigator.msMaxTouchPoints;
+ var type;
for (var i = 0, len = this.BROWSER_EVENTS.length; i < len; i++) {
+ type = this.BROWSER_EVENTS[i];
// register the event cross-browser
- OpenLayers.Event.observe(
- element, this.BROWSER_EVENTS[i], this.eventHandler
+ OpenLayers.Event.observe(element, type, this.eventHandler
);
+ if (msTouch && type.indexOf('touch') === 0) {
+ this.addMsTouchListener(element, type, this.eventHandler);
+ }
}
// disable dragstart in IE so that mousedown/move/up works normally
OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop);
},
@@ -10111,17 +10203,163 @@
(evt.clientY + this.element.scrolls[1]) - this.element.offsets[1]
- this.element.lefttop[1]
);
},
+ /**
+ * Method: addMsTouchListener
+ *
+ * Parameters:
+ * element - {DOMElement} The DOM element to register the listener on
+ * type - {String} The event type
+ * handler - {Function} the handler
+ */
+ addMsTouchListener: function (element, type, handler) {
+ var eventHandler = this.eventHandler;
+ var touches = this._msTouches;
+
+ function msHandler(evt) {
+ handler(OpenLayers.Util.applyDefaults({
+ stopPropagation: function() {
+ for (var i=touches.length-1; i>=0; --i) {
+ touches[i].stopPropagation();
+ }
+ },
+ preventDefault: function() {
+ for (var i=touches.length-1; i>=0; --i) {
+ touches[i].preventDefault();
+ }
+ },
+ type: type
+ }, evt));
+ }
+
+ switch (type) {
+ case 'touchstart':
+ return this.addMsTouchListenerStart(element, type, msHandler);
+ case 'touchend':
+ return this.addMsTouchListenerEnd(element, type, msHandler);
+ case 'touchmove':
+ return this.addMsTouchListenerMove(element, type, msHandler);
+ default:
+ throw 'Unknown touch event type';
+ }
+ },
+
+ /**
+ * Method: addMsTouchListenerStart
+ *
+ * Parameters:
+ * element - {DOMElement} The DOM element to register the listener on
+ * type - {String} The event type
+ * handler - {Function} the handler
+ */
+ addMsTouchListenerStart: function(element, type, handler) {
+ var touches = this._msTouches;
+
+ var cb = function(e) {
+
+ var alreadyInArray = false;
+ for (var i=0, ii=touches.length; i<ii; ++i) {
+ if (touches[i].pointerId == e.pointerId) {
+ alreadyInArray = true;
+ break;
+ }
+ }
+ if (!alreadyInArray) {
+ touches.push(e);
+ }
+
+ e.touches = touches.slice();
+ handler(e);
+ };
+
+ OpenLayers.Event.observe(element, 'MSPointerDown', cb);
+
+ // Need to also listen for end events to keep the _msTouches list
+ // accurate
+ var internalCb = function(e) {
+ for (var i=0, ii=touches.length; i<ii; ++i) {
+ if (touches[i].pointerId == e.pointerId) {
+ touches.splice(i, 1);
+ break;
+ }
+ }
+ };
+ OpenLayers.Event.observe(element, 'MSPointerUp', internalCb);
+ },
+
+ /**
+ * Method: addMsTouchListenerMove
+ *
+ * Parameters:
+ * element - {DOMElement} The DOM element to register the listener on
+ * type - {String} The event type
+ * handler - {Function} the handler
+ */
+ addMsTouchListenerMove: function (element, type, handler) {
+ var touches = this._msTouches;
+ var cb = function(e) {
+
+ //Don't fire touch moves when mouse isn't down
+ if (e.pointerType == e.MSPOINTER_TYPE_MOUSE && e.buttons == 0) {
+ return;
+ }
+
+ if (touches.length == 1 && touches[0].pageX == e.pageX &&
+ touches[0].pageY == e.pageY) {
+ // don't trigger event when pointer has not moved
+ return;
+ }
+ for (var i=0, ii=touches.length; i<ii; ++i) {
+ if (touches[i].pointerId == e.pointerId) {
+ touches[i] = e;
+ break;
+ }
+ }
+
+ e.touches = touches.slice();
+ handler(e);
+ };
+
+ OpenLayers.Event.observe(element, 'MSPointerMove', cb);
+ },
+
+ /**
+ * Method: addMsTouchListenerEnd
+ *
+ * Parameters:
+ * element - {DOMElement} The DOM element to register the listener on
+ * type - {String} The event type
+ * handler - {Function} the handler
+ */
+ addMsTouchListenerEnd: function (element, type, handler) {
+ var touches = this._msTouches;
+
+ var cb = function(e) {
+
+ for (var i=0, ii=touches.length; i<ii; ++i) {
+ if (touches[i].pointerId == e.pointerId) {
+ touches.splice(i, 1);
+ break;
+ }
+ }
+
+ e.touches = touches.slice();
+ handler(e);
+ };
+
+ OpenLayers.Event.observe(element, 'MSPointerUp', cb);
+ },
+
CLASS_NAME: "OpenLayers.Events"
});
/* ======================================================================
OpenLayers/Request.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -11012,11 +11250,11 @@
})();
/* ======================================================================
OpenLayers/Projection.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -11180,13 +11418,13 @@
/**
* 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).
+ * EPSG:102113, EPSG:102100 and OSGEO:41001). 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],
@@ -11280,13 +11518,13 @@
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.
+ * OpenLayers recognizes EPSG:3857, EPSG:900913, EPSG:102113, EPSG:102100 and
+ * OSGEO:41001. OpenLayers originally started referring to EPSG:900913 as web
+ * mercator. The EPSG has declared EPSG:3857 to be web mercator.
* ArcGIS 10 recognizes the EPSG:3857, EPSG:102113, and EPSG:102100 as
* equivalent. See http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2009/11/20/ArcGIS-Online-moving-to-Google-_2F00_-Bing-tiling-scheme_3A00_-What-does-this-mean-for-you_3F00_.aspx#12084.
* For geographic, OpenLayers recognizes EPSG:4326, CRS:84 and
* urn:ogc:def:crs:EPSG:6.6:4326. OpenLayers also knows about the reverse axis
* order for EPSG:4326.
@@ -11323,11 +11561,11 @@
}
}
}
// list of equivalent codes for web mercator
- var mercator = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100"],
+ var mercator = ["EPSG:900913", "EPSG:3857", "EPSG:102113", "EPSG:102100", "OSGEO:41001"],
geographic = ["CRS:84", "urn:ogc:def:crs:EPSG:6.6:4326", "EPSG:4326"],
i;
for (i=mercator.length-1; i>=0; --i) {
map(mercator[i], geographic);
}
@@ -11338,11 +11576,11 @@
})();
/* ======================================================================
OpenLayers/Format/KML.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -12568,22 +12806,22 @@
placemarkNode.setAttribute("id", feature.fid);
}
placemarkNode.appendChild(placemarkName);
placemarkNode.appendChild(placemarkDesc);
- // Geometry node (Point, LineString, etc. nodes)
- var geometryNode = this.buildGeometryNode(feature.geometry);
- placemarkNode.appendChild(geometryNode);
-
// output attributes as extendedData
if (feature.attributes) {
var edNode = this.buildExtendedData(feature.attributes);
if (edNode) {
placemarkNode.appendChild(edNode);
}
}
+ // Geometry node (Point, LineString, etc. nodes)
+ var geometryNode = this.buildGeometryNode(feature.geometry);
+ placemarkNode.appendChild(geometryNode);
+
return placemarkNode;
},
/**
* Method: buildGeometryNode
@@ -12859,11 +13097,11 @@
});
/* ======================================================================
OpenLayers/Geometry/MultiLineString.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -13121,11 +13359,11 @@
});
/* ======================================================================
OpenLayers/Geometry/MultiPolygon.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -13167,11 +13405,11 @@
});
/* ======================================================================
OpenLayers/Format/GML.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -14094,11 +14332,11 @@
});
/* ======================================================================
OpenLayers/Format/GML/Base.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -14743,11 +14981,11 @@
});
/* ======================================================================
OpenLayers/Format/GML/v2.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -14940,11 +15178,11 @@
});
/* ======================================================================
OpenLayers/Style.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -15392,11 +15630,11 @@
'Raster'];
/* ======================================================================
OpenLayers/Rule.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -15632,11 +15870,11 @@
});
/* ======================================================================
OpenLayers/Format/OGCExceptionReport.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -15744,11 +15982,11 @@
});
/* ======================================================================
OpenLayers/Format/XML/VersionedOGC.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -15960,11 +16198,11 @@
});
/* ======================================================================
OpenLayers/Filter.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -16051,11 +16289,11 @@
});
/* ======================================================================
OpenLayers/Filter/FeatureId.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -16142,11 +16380,11 @@
});
/* ======================================================================
OpenLayers/Filter/Logical.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -16267,11 +16505,11 @@
OpenLayers.Filter.Logical.NOT = "!";
/* ======================================================================
OpenLayers/Filter/Comparison.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -16384,10 +16622,13 @@
if (context instanceof OpenLayers.Feature.Vector) {
context = context.attributes;
}
var result = false;
var got = context[this.property];
+ if (got === undefined) {
+ return false;
+ }
var exp;
switch(this.type) {
case OpenLayers.Filter.Comparison.EQUAL_TO:
exp = this.value;
if(!this.matchCase &&
@@ -16538,11 +16779,11 @@
OpenLayers.Filter.Comparison.IS_NULL = "NULL";
/* ======================================================================
OpenLayers/Filter/Spatial.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -16664,11 +16905,11 @@
OpenLayers.Filter.Spatial.CONTAINS = "CONTAINS";
/* ======================================================================
OpenLayers/Format/SLD.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -16749,11 +16990,11 @@
});
/* ======================================================================
OpenLayers/Format/Filter.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -16806,11 +17047,11 @@
});
/* ======================================================================
OpenLayers/Filter/Function.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -16859,11 +17100,11 @@
/* ======================================================================
OpenLayers/Format/Filter/v1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Format/Filter.js
@@ -17367,11 +17608,11 @@
});
/* ======================================================================
OpenLayers/Format/Filter/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -17555,11 +17796,11 @@
});
/* ======================================================================
OpenLayers/Symbolizer.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -17602,11 +17843,11 @@
* Create a copy of this symbolizer.
*
* Returns a symbolizer of the same type with the same properties.
*/
clone: function() {
- var Type = eval(this.CLASS_NAME);
+ var Type = OpenLayers.Util.getConstructor(this.CLASS_NAME);
return new Type(OpenLayers.Util.extend({}, this));
},
CLASS_NAME: "OpenLayers.Symbolizer"
@@ -17614,11 +17855,11 @@
/* ======================================================================
OpenLayers/Symbolizer/Point.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -17775,11 +18016,11 @@
/* ======================================================================
OpenLayers/Symbolizer/Line.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -17853,11 +18094,11 @@
/* ======================================================================
OpenLayers/Symbolizer/Polygon.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -17945,11 +18186,11 @@
/* ======================================================================
OpenLayers/Symbolizer/Text.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -18019,11 +18260,11 @@
/* ======================================================================
OpenLayers/Symbolizer/Raster.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -18057,16 +18298,17 @@
});
/* ======================================================================
OpenLayers/Format/SLD/v1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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.js
* @requires OpenLayers/Rule.js
* @requires OpenLayers/Format/SLD.js
* @requires OpenLayers/Format/Filter/v1_0_0.js
* @requires OpenLayers/Symbolizer/Point.js
* @requires OpenLayers/Symbolizer/Line.js
@@ -18216,11 +18458,11 @@
sld.namedLayers[layer.name] = layer;
}
},
"NamedStyle": function(node, layer) {
layer.namedStyles.push(
- this.getChildName(node.firstChild)
+ this.getChildValue(node.firstChild)
);
},
"UserStyle": function(node, layer) {
var obj = {defaultsPerSymbolizer: true, rules: []};
this.featureTypeCounter = -1;
@@ -18354,11 +18596,11 @@
}
},
"Label": function(node, symbolizer) {
var value = this.readers.ogc._expression.call(this, node);
if (value) {
- symbolizer.label = value;
+ symbolizer.label = OpenLayers.String.trim(value);
}
},
"Font": function(node, symbolizer) {
this.readChildNodes(node, symbolizer);
},
@@ -19370,11 +19612,11 @@
});
/* ======================================================================
OpenLayers/Format/SLD/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -19420,11 +19662,11 @@
});
/* ======================================================================
OpenLayers/Format/Context.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -19531,10 +19773,11 @@
}),
numZoomLevels: layerContext.numZoomLevels,
units: layerContext.units,
isBaseLayer: layerContext.isBaseLayer,
opacity: layerContext.opacity,
+ gutter: layerContext.gutter,
displayInLayerSwitcher: layerContext.displayInLayerSwitcher,
singleTile: layerContext.singleTile,
tileSize: (layerContext.tileSize) ?
new OpenLayers.Size(
layerContext.tileSize.width,
@@ -19542,11 +19785,12 @@
) : undefined,
minScale: layerContext.minScale || layerContext.maxScaleDenominator,
maxScale: layerContext.maxScale || layerContext.minScaleDenominator,
srs: layerContext.srs,
dimensions: layerContext.dimensions,
- metadataURL: layerContext.metadataURL
+ metadataURL: layerContext.metadataURL,
+ attribution: layerContext.attribution
};
if (this.layerOptions) {
OpenLayers.Util.applyDefaults(options, this.layerOptions);
}
@@ -19758,11 +20002,11 @@
};
/* ======================================================================
OpenLayers/Format/OWSContext.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -19848,11 +20092,11 @@
});
/* ======================================================================
OpenLayers/Format/OWSCommon.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -19930,11 +20174,11 @@
});
/* ======================================================================
OpenLayers/Format/OWSCommon/v1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -20063,10 +20307,13 @@
this.readChildNodes(node, contactInfo.phone);
},
"Voice": function(node, phone) {
phone.voice = this.getChildValue(node);
},
+ "Facsimile": function(node, phone) {
+ phone.facsimile = this.getChildValue(node);
+ },
"Address": function(node, contactInfo) {
contactInfo.address = {};
this.readChildNodes(node, contactInfo.address);
},
"DeliveryPoint": function(node, address) {
@@ -20252,11 +20499,11 @@
});
/* ======================================================================
OpenLayers/Format/OWSCommon/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -20318,11 +20565,11 @@
});
/* ======================================================================
OpenLayers/Format/OWSContext/v0_3_1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -20917,11 +21164,11 @@
});
/* ======================================================================
OpenLayers/Format/CSWGetRecords.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -20955,11 +21202,11 @@
};
/* ======================================================================
OpenLayers/Control.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -21256,11 +21503,11 @@
}
},
/**
* APIMethod: activate
- * Explicitly activates a control and it's associated
+ * Explicitly activates a control and its associated
* handler if one has been set. Controls can be
* deactivated by calling the deactivate() method.
*
* Returns:
* {Boolean} True if the control was successfully activated or
@@ -21284,11 +21531,11 @@
return true;
},
/**
* APIMethod: deactivate
- * Deactivates a control and it's associated handler if any. The exact
+ * Deactivates a control and its associated handler if any. The exact
* effect of this depends on the control itself.
*
* Returns:
* {Boolean} True if the control was effectively deactivated or false
* if the control was already inactive.
@@ -21330,11 +21577,11 @@
OpenLayers.Control.TYPE_TOOL = 3;
/* ======================================================================
OpenLayers/Events/buttonclick.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -21502,10 +21749,16 @@
break;
}
} else if (this.startEvt) {
if (this.completeRegEx.test(evt.type)) {
var pos = OpenLayers.Util.pagePosition(button);
+ var viewportElement = OpenLayers.Util.getViewportElement();
+ var scrollTop = window.pageYOffset || viewportElement.scrollTop;
+ var scrollLeft = window.pageXOffset || viewportElement.scrollLeft;
+ pos[0] = pos[0] - scrollLeft;
+ pos[1] = pos[1] - scrollTop;
+
this.target.triggerEvent("buttonclick", {
buttonElement: button,
buttonXY: {
x: this.startEvt.clientX - pos[0],
y: this.startEvt.clientY - pos[1]
@@ -21534,16 +21787,16 @@
});
/* ======================================================================
OpenLayers/Util/vendorPrefix.js
====================================================================== */
-/**
- * Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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.
- *
+ * full text of the license. */
+
+/**
* @requires OpenLayers/SingleFile.js
*/
OpenLayers.Util = OpenLayers.Util || {};
/**
@@ -21669,16 +21922,16 @@
}());
/* ======================================================================
OpenLayers/Animation.js
====================================================================== */
-/**
- * Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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.
- *
+ * full text of the license. */
+
+/**
* @requires OpenLayers/SingleFile.js
* @requires OpenLayers/Util/vendorPrefix.js
*/
/**
@@ -21775,11 +22028,11 @@
})(window);
/* ======================================================================
OpenLayers/Tween.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -22140,18 +22393,19 @@
};
/* ======================================================================
OpenLayers/Map.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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
*/
@@ -22211,21 +22465,25 @@
* 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 (due to resolution
- * thresholds) 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).
+ * opacity change, params change, visibility change (actual visibility,
+ * not the layer's visibility property) or attribution change (due to
+ * extent change). Listeners will receive an event object with *layer*
+ * and *property* properties. The *layer* property will be a reference
+ * to the changed layer. The *property* property will be a key to the
+ * changed property (name, order, opacity, params, visibility or
+ * attribution).
* movestart - triggered after the start of a drag, pan, or zoom. The event
* object may include a *zoomChanged* property that tells whether the
* zoom has changed.
* move - triggered after each drag, pan, or zoom
* moveend - triggered after a drag, pan, or zoom completes
+ * zoomstart - triggered when a zoom starts. Listeners receive an object
+ * with *center* and *zoom* properties, for the target center and zoom
+ * level.
* zoomend - triggered after a zoom completes
* mouseover - triggered after mouseover the map
* mouseout - triggered after mouseout the map
* mousemove - triggered after mousemove the map
* changebaselayer - triggered after the base layer changes
@@ -22512,19 +22770,20 @@
* several controls to display data to user. If this property is set,
* it will be set on any control which has a null displayProjection
* property at the time the control is added to the map.
*/
displayProjection: null,
-
+
/**
* APIProperty: tileManager
- * {<OpenLayers.TileManager>} If configured at construction time, the map
- * will use the TileManager to queue image requests and to cache tile image
- * elements. Note: make sure that OpenLayers/TileManager.js is included in
- * your build profile.
+ * {<OpenLayers.TileManager>|Object} By default, and if the build contains
+ * TileManager.js, the map will use the TileManager to queue image requests
+ * and to cache tile image elements. To create a map without a TileManager
+ * configure the map with tileManager: null. To create a TileManager with
+ * non-default options, supply the options instead or alternatively supply
+ * an instance of {<OpenLayers.TileManager>}.
*/
- tileManager: null,
/**
* 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)
@@ -22538,25 +22797,25 @@
* when the resize event is fired. Default is true.
*/
autoUpdateSize: true,
/**
- * Property: panTween
- * {<OpenLayers.Tween>} Animated panning tween object, see panTo()
- */
- panTween: null,
-
- /**
* APIProperty: eventListeners
* {Object} If set as an option at construction, the eventListeners
* object will be registered with <OpenLayers.Events.on>. Object
* structure must be a listeners object as shown in the example for
* the events.on method.
*/
eventListeners: null,
/**
+ * Property: panTween
+ * {<OpenLayers.Tween>} Animated panning tween object, see panTo()
+ */
+ panTween: null,
+
+ /**
* APIProperty: panMethod
* {Function} The Easing function to be used for tweening. Default is
* OpenLayers.Easing.Expo.easeOut. Setting this to 'null' turns off
* animated panning.
*/
@@ -22570,10 +22829,32 @@
* Default is 50.
*/
panDuration: 50,
/**
+ * Property: zoomTween
+ * {<OpenLayers.Tween>} Animated zooming tween object, see zoomTo()
+ */
+ zoomTween: null,
+
+ /**
+ * APIProperty: zoomMethod
+ * {Function} The Easing function to be used for tweening. Default is
+ * OpenLayers.Easing.Quad.easeOut. Setting this to 'null' turns off
+ * animated zooming.
+ */
+ zoomMethod: OpenLayers.Easing.Quad.easeOut,
+
+ /**
+ * Property: zoomDuration
+ * {Integer} The number of steps to be passed to the
+ * OpenLayers.Tween.start() method when the map is zoomed.
+ * Default is 20.
+ */
+ zoomDuration: 20,
+
+ /**
* Property: paddingForPopups
* {<OpenLayers.Bounds>} Outside margin of the popup. Used to prevent
* the popup from getting too close to the map border.
*/
paddingForPopups : null,
@@ -22625,14 +22906,10 @@
* zoom - {Number} The initial zoom level for the map. Only specify if
* <layers> is provided.
* Note that if an ArgParser/Permalink control is present,
* and the querystring contains a zoom level, zoom will be set
* by that, and this option will be ignored.
- * extent - {<OpenLayers.Bounds>|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 <center> and <zoom> are not provided.
*
* Examples:
* (code)
* // create a map with default options in an element with the id "map1"
* var map = new OpenLayers.Map("map1");
@@ -22731,19 +23008,23 @@
this.events = new OpenLayers.Events(
this, this.viewPortDiv, null, this.fallThrough,
{includeXY: true}
);
- if (this.tileManager) {
+ if (OpenLayers.TileManager && this.tileManager !== null) {
+ if (!(this.tileManager instanceof OpenLayers.TileManager)) {
+ this.tileManager = new OpenLayers.TileManager(this.tileManager);
+ }
this.tileManager.addMap(this);
}
// the layerContainerDiv is the one that holds all the layers
id = this.id + "_OpenLayers_Container";
this.layerContainerDiv = OpenLayers.Util.createDiv(id);
this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;
this.layerContainerOriginPx = {x: 0, y: 0};
+ this.applyTransform();
this.viewPortDiv.appendChild(this.layerContainerDiv);
this.updateSize();
if(this.eventListeners instanceof Object) {
@@ -22835,10 +23116,17 @@
if (options.center && !this.getCenter()) {
// zoom can be undefined here
this.setCenter(options.center, options.zoom);
}
}
+
+ if (this.panMethod) {
+ this.panTween = new OpenLayers.Tween(this.panMethod);
+ }
+ if (this.zoomMethod && this.applyTransform.transform) {
+ this.zoomTween = new OpenLayers.Tween(this.zoomMethod);
+ }
},
/**
* APIMethod: getViewport
* Get the DOMElement representing the view port.
@@ -22903,10 +23191,15 @@
// make sure panning doesn't continue after destruction
if(this.panTween) {
this.panTween.stop();
this.panTween = null;
}
+ // make sure zooming doesn't continue after destruction
+ if(this.zoomTween) {
+ this.zoomTween.stop();
+ this.zoomTween = null;
+ }
// map has been destroyed. dont do it again!
OpenLayers.Event.stopObserving(window, 'unload', this.unloadDestroy);
this.unloadDestroy = null;
@@ -23386,10 +23679,11 @@
// ensure newBaseLayer is already loaded
if (OpenLayers.Util.indexOf(this.layers, newBaseLayer) != -1) {
// preserve center and scale when changing base layers
var center = this.getCachedCenter();
+ var oldResolution = this.getResolution();
var newResolution = OpenLayers.Util.getResolutionFromScale(
this.getScale(), newBaseLayer.units
);
// make the old base layer invisible
@@ -23414,11 +23708,11 @@
// new zoom level derived from old scale
var newZoom = this.getZoomForResolution(
newResolution || this.resolution, true
);
// zoom and force zoom change
- this.setCenter(center, newZoom, false, true);
+ this.setCenter(center, newZoom, false, oldResolution != newResolution);
}
this.events.triggerEvent("changebaselayer", {
layer: this.baseLayer
});
@@ -23816,21 +24110,18 @@
},
/**
* APIMethod: panTo
- * Allows user to pan to a new lonlat
+ * Allows user to pan to a new lonlat.
* If the new lonlat is in the current extent the map will slide smoothly
*
* Parameters:
* lonlat - {<OpenLayers.LonLat>}
*/
panTo: function(lonlat) {
- if (this.panMethod && this.getExtent().scale(this.panRatio).containsLonLat(lonlat)) {
- if (!this.panTween) {
- this.panTween = new OpenLayers.Tween(this.panMethod);
- }
+ if (this.panTween && this.getExtent().scale(this.panRatio).containsLonLat(lonlat)) {
var center = this.getCachedCenter();
// center will not change, don't do nothing
if (lonlat.equals(center)) {
return;
@@ -23877,11 +24168,16 @@
* change events (needed on baseLayer change)
*
* TBD: reconsider forceZoomChange in 3.0
*/
setCenter: function(lonlat, zoom, dragging, forceZoomChange) {
- this.panTween && this.panTween.stop();
+ if (this.panTween) {
+ this.panTween.stop();
+ }
+ if (this.zoomTween) {
+ this.zoomTween.stop();
+ }
this.moveTo(lonlat, zoom, {
'dragging': dragging,
'forceZoomChange': forceZoomChange
});
},
@@ -23918,21 +24214,20 @@
this.dragging = true;
this.events.triggerEvent("movestart");
}
this.center = null;
if (dx) {
- this.layerContainerDiv.style.left =
- (this.layerContainerOriginPx.x -= dx) + "px";
+ this.layerContainerOriginPx.x -= dx;
this.minPx.x -= dx;
this.maxPx.x -= dx;
}
if (dy) {
- this.layerContainerDiv.style.top =
- (this.layerContainerOriginPx.y -= dy) + "px";
+ this.layerContainerOriginPx.y -= dy;
this.minPx.y -= dy;
this.maxPx.y -= dy;
}
+ this.applyTransform();
var layer, i, len;
for (i=0, len=this.layers.length; i<len; ++i) {
layer = this.layers[i];
if (layer.visibility &&
(layer === this.baseLayer || layer.inRange)) {
@@ -24088,15 +24383,13 @@
var res = zoomChanged ?
this.getResolutionForZoom(zoom) : this.getResolution();
// (re)set the layerContainerDiv's location
if (zoomChanged || this.layerContainerOrigin == null) {
this.layerContainerOrigin = this.getCachedCenter();
- var style = this.layerContainerDiv.style;
- style.left = "0px";
- style.top = "0px";
this.layerContainerOriginPx.x = 0;
this.layerContainerOriginPx.y = 0;
+ this.applyTransform();
var maxExtent = this.getMaxExtent({restricted: true});
var maxExtentCenter = maxExtent.getCenterLonLat();
var lonDelta = this.center.lon - maxExtentCenter.lon;
var latDelta = maxExtentCenter.lat - this.center.lat;
var extentWidth = Math.round(maxExtent.getWidth() / res);
@@ -24140,11 +24433,13 @@
// call below will turn on the layer.
layer.inRange = inRange;
if (!inRange) {
layer.display(false);
}
-
+ this.events.triggerEvent("changelayer", {
+ layer: layer, property: "visibility"
+ });
}
if (inRange && layer.visibility) {
layer.moveTo(bounds, zoomChanged, options.dragging);
options.dragging || layer.events.triggerEvent(
"moveend", {zoomChanged: zoomChanged}
@@ -24180,14 +24475,13 @@
if ((originPx != null) && (newPx != null)) {
var oldLeft = this.layerContainerOriginPx.x;
var oldTop = this.layerContainerOriginPx.y;
var newLeft = Math.round(originPx.x - newPx.x);
var newTop = Math.round(originPx.y - newPx.y);
- this.layerContainerDiv.style.left =
- (this.layerContainerOriginPx.x = newLeft) + "px";
- this.layerContainerDiv.style.top =
- (this.layerContainerOriginPx.y = newTop) + "px";
+ this.applyTransform(
+ (this.layerContainerOriginPx.x = newLeft),
+ (this.layerContainerOriginPx.y = newTop));
var dx = oldLeft - newLeft;
var dy = oldTop - newTop;
this.minPx.x -= dx;
this.maxPx.x -= dx;
this.minPx.y -= dy;
@@ -24482,34 +24776,90 @@
/* */
/********************************************************/
/**
* APIMethod: zoomTo
- * Zoom to a specific zoom level
+ * Zoom to a specific zoom level. Zooming will be animated unless the map
+ * is configured with {zoomMethod: null}. To zoom without animation, use
+ * <setCenter> without a lonlat argument.
*
* Parameters:
* zoom - {Integer}
*/
- zoomTo: function(zoom) {
- if (this.isValidZoomLevel(zoom)) {
- this.setCenter(null, zoom);
+ zoomTo: function(zoom, xy) {
+ // non-API arguments:
+ // xy - {<OpenLayers.Pixel>} optional zoom origin
+
+ var map = this;
+ if (map.isValidZoomLevel(zoom)) {
+ if (map.baseLayer.wrapDateLine) {
+ zoom = map.adjustZoom(zoom);
+ }
+ var center = xy ?
+ map.getZoomTargetCenter(xy, map.getResolutionForZoom(zoom)) :
+ map.getCenter();
+ if (center) {
+ map.events.triggerEvent('zoomstart', {
+ center: center,
+ zoom: zoom
+ });
+ }
+ if (map.zoomTween) {
+ map.zoomTween.stop();
+ var currentRes = map.getResolution(),
+ targetRes = map.getResolutionForZoom(zoom),
+ start = {scale: 1},
+ end = {scale: currentRes / targetRes};
+ if (!xy) {
+ var size = map.getSize();
+ xy = {x: size.w / 2, y: size.h / 2};
+ }
+ map.zoomTween.start(start, end, map.zoomDuration, {
+ minFrameRate: 50, // don't spend much time zooming
+ callbacks: {
+ eachStep: function(data) {
+ var containerOrigin = map.layerContainerOriginPx,
+ scale = data.scale,
+ dx = ((scale - 1) * (containerOrigin.x - xy.x)) | 0,
+ dy = ((scale - 1) * (containerOrigin.y - xy.y)) | 0;
+ map.applyTransform(containerOrigin.x + dx, containerOrigin.y + dy, scale);
+ },
+ done: function(data) {
+ map.applyTransform();
+ var resolution = map.getResolution() / data.scale,
+ newZoom = map.getZoomForResolution(resolution, true),
+ newCenter = data.scale === 1 ? center :
+ map.getZoomTargetCenter(xy, resolution);
+ map.moveTo(newCenter, newZoom);
+ }
+ }
+ });
+ } else {
+ map.setCenter(center, zoom);
+ }
}
},
-
+
/**
* APIMethod: zoomIn
*
*/
zoomIn: function() {
+ if (this.zoomTween) {
+ this.zoomTween.stop();
+ }
this.zoomTo(this.getZoom() + 1);
},
/**
* APIMethod: zoomOut
*
*/
zoomOut: function() {
+ if (this.zoomTween) {
+ this.zoomTween.stop();
+ }
this.zoomTo(this.getZoom() - 1);
},
/**
* APIMethod: zoomToExtent
@@ -24650,11 +25000,36 @@
px = this.baseLayer.getViewPortPxFromLonLat(lonlat);
}
return px;
},
-
+ /**
+ * Method: getZoomTargetCenter
+ *
+ * Parameters:
+ * xy - {<OpenLayers.Pixel>} The zoom origin pixel location on the screen
+ * resolution - {Float} The resolution we want to get the center for
+ *
+ * Returns:
+ * {<OpenLayers.LonLat>} The location of the map center after the
+ * transformation described by the origin xy and the target resolution.
+ */
+ getZoomTargetCenter: function (xy, resolution) {
+ var lonlat = null,
+ size = this.getSize(),
+ deltaX = size.w/2 - xy.x,
+ deltaY = xy.y - size.h/2,
+ zoomPoint = this.getLonLatFromPixel(xy);
+ if (zoomPoint) {
+ lonlat = new OpenLayers.LonLat(
+ zoomPoint.lon + deltaX * resolution,
+ zoomPoint.lat + deltaY * resolution
+ );
+ }
+ return lonlat;
+ },
+
//
// CONVENIENCE TRANSLATION FUNCTIONS FOR API
//
/**
@@ -24810,10 +25185,80 @@
//adjust for displacement of layerContainerDiv
var px = this.getPixelFromLonLat(lonlat);
return this.getLayerPxFromViewPortPx(px);
},
+ /**
+ * Method: applyTransform
+ * Applies the given transform to the <layerContainerDiv>. This method has
+ * a 2-stage fallback from translate3d/scale3d via translate/scale to plain
+ * style.left/style.top, in which case no scaling is supported.
+ *
+ * Parameters:
+ * x - {Number} x parameter for the translation. Defaults to the x value of
+ * the map's <layerContainerOriginPx>
+ * y - {Number} y parameter for the translation. Defaults to the y value of
+ * the map's <layerContainerOriginPx>
+ * scale - {Number} scale. Defaults to 1 if not provided.
+ */
+ applyTransform: function(x, y, scale) {
+ scale = scale || 1;
+ var origin = this.layerContainerOriginPx,
+ needTransform = scale !== 1;
+ x = x || origin.x;
+ y = y || origin.y;
+
+ var style = this.layerContainerDiv.style,
+ transform = this.applyTransform.transform,
+ template = this.applyTransform.template;
+
+ if (transform === undefined) {
+ transform = OpenLayers.Util.vendorPrefix.style('transform');
+ this.applyTransform.transform = transform;
+ if (transform) {
+ // Try translate3d, but only if the viewPortDiv has a transform
+ // defined in a stylesheet
+ var computedStyle = OpenLayers.Element.getStyle(this.viewPortDiv,
+ OpenLayers.Util.vendorPrefix.css('transform'));
+ if (!computedStyle || computedStyle !== 'none') {
+ template = ['translate3d(', ',0) ', 'scale3d(', ',1)'];
+ style[transform] = [template[0], '0,0', template[1]].join('');
+ }
+ // If no transform is defined in the stylesheet or translate3d
+ // does not stick, use translate and scale
+ if (!template || !~style[transform].indexOf(template[0])) {
+ template = ['translate(', ') ', 'scale(', ')'];
+ }
+ this.applyTransform.template = template;
+ }
+ }
+
+ // If we do 3d transforms, we always want to use them. If we do 2d
+ // transforms, we only use them when we need to.
+ if (transform !== null && (template[0] === 'translate3d(' || needTransform === true)) {
+ // Our 2d transforms are combined with style.left and style.top, so
+ // adjust x and y values and set the origin as left and top
+ if (needTransform === true && template[0] === 'translate(') {
+ x -= origin.x;
+ y -= origin.y;
+ style.left = origin.x + 'px';
+ style.top = origin.y + 'px';
+ }
+ style[transform] = [
+ template[0], x, 'px,', y, 'px', template[1],
+ template[2], scale, ',', scale, template[3]
+ ].join('');
+ } else {
+ style.left = x + 'px';
+ style.top = y + 'px';
+ // We previously might have had needTransform, so remove transform
+ if (transform !== null) {
+ style[transform] = '';
+ }
+ }
+ },
+
CLASS_NAME: "OpenLayers.Map"
});
/**
* Constant: TILE_WIDTH
@@ -24827,11 +25272,11 @@
OpenLayers.Map.TILE_HEIGHT = 256;
/* ======================================================================
OpenLayers/Handler.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -24914,10 +25359,18 @@
* 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.
*
@@ -25016,15 +25469,37 @@
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 <touch> 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
@@ -25126,11 +25601,11 @@
/* ======================================================================
OpenLayers/Handler/Click.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -25218,17 +25693,10 @@
/**
* Property: timerId
* {Number} The id of the timeout waiting to clear the <delayedCall>.
*/
timerId: null,
-
- /**
- * Property: touch
- * {Boolean} When a touchstart event is fired, touch will be true and all
- * mouse related listeners will do nothing.
- */
- touch: false,
/**
* Property: down
* {Object} Object that store relevant information about the last
* mousedown or touchstart. Its 'xy' OpenLayers.Pixel property gives
@@ -25283,14 +25751,11 @@
*
* Returns:
* {Boolean} Continue propagating this event.
*/
touchstart: function(evt) {
- if (!this.touch) {
- this.unregisterMouseListeners();
- this.touch = true;
- }
+ this.startTouch();
this.down = this.getEventInfo(evt);
this.last = this.getEventInfo(evt);
return true;
},
@@ -25323,24 +25788,10 @@
this.handleSingle(evt);
this.down = null;
}
return true;
},
-
- /**
- * Method: unregisterMouseListeners
- * In a touch environment, we don't want to handle mouse events.
- */
- unregisterMouseListeners: function() {
- this.map.events.un({
- mousedown: this.mousedown,
- mouseup: this.mouseup,
- click: this.click,
- dblclick: this.dblclick,
- scope: this
- });
- },
/**
* Method: mousedown
* Handle mousedown.
*
@@ -25648,11 +26099,10 @@
if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
this.clearTimer();
this.down = null;
this.first = null;
this.last = null;
- this.touch = false;
deactivated = true;
}
return deactivated;
},
@@ -25660,11 +26110,11 @@
});
/* ======================================================================
OpenLayers/Handler/Drag.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -25712,17 +26162,10 @@
* Property: dragging
* {Boolean}
*/
dragging: false,
- /**
- * Property: touch
- * {Boolean} When a touchstart event is fired, touch will be true and all
- * mouse related listeners will do nothing.
- */
- touch: false,
-
/**
* Property: last
* {<OpenLayers.Pixel>} The last pixel location of the drag.
*/
last: null,
@@ -26007,21 +26450,11 @@
*
* Returns:
* {Boolean} Let the event propagate.
*/
touchstart: function(evt) {
- if (!this.touch) {
- this.touch = true;
- // unregister mouse listeners
- this.map.events.un({
- mousedown: this.mousedown,
- mouseup: this.mouseup,
- mousemove: this.mousemove,
- click: this.click,
- scope: this
- });
- }
+ this.startTouch();
return this.dragstart(evt);
},
/**
* Method: mousemove
@@ -26171,11 +26604,10 @@
* {Boolean} The handler was successfully deactivated.
*/
deactivate: function() {
var deactivated = false;
if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
- this.touch = false;
this.started = false;
this.dragging = false;
this.start = null;
this.last = null;
deactivated = true;
@@ -26229,11 +26661,11 @@
});
/* ======================================================================
OpenLayers/Control/OverviewMap.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -26983,11 +27415,11 @@
});
/* ======================================================================
OpenLayers/Layer.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -27078,11 +27510,15 @@
* a *filter* property holding the OpenLayers.Filter used when
* calling read on the protocol.
* loadend - Triggered when layer loading ends. When using a Vector layer
* with a Fixed or BBOX strategy, the event object includes a
* *response* property holding an OpenLayers.Protocol.Response object.
- * visibilitychanged - Triggered when layer visibility is changed.
+ * visibilitychanged - Triggered when the layer's visibility property is
+ * changed, e.g. by turning the layer on or off in the layer switcher.
+ * Note that the actual visibility of the layer can also change if it
+ * gets out of range (see <calculateInRange>). If you also want to catch
+ * these cases, register for the map's 'changelayer' event instead.
* move - Triggered when layer moves (triggered with every mousemove
* during a drag).
* moveend - Triggered when layer is done moving, object passed as
* argument has a zoomChanged boolean property which tells that the
* zoom has changed.
@@ -27128,14 +27564,18 @@
*/
visibility: true,
/**
* APIProperty: attribution
- * {String} Attribution string, displayed when an
+ * {<Object>} or {<String>} Attribution information, displayed when an
* <OpenLayers.Control.Attribution> has been added to the map.
+ *
+ * An object is required to store the full attribution information
+ * from a WMS capabilities response. Example attribution object:
+ * {title:"",href:"",logo:{format:"",width:10,height:10,href:""}}
*/
- attribution: null,
+ attribution: null,
/**
* Property: inRange
* {Boolean} The current map resolution is within the layer's min/max
* range. This is set in <OpenLayers.Map.setCenter> whenever the zoom
@@ -27724,10 +28164,16 @@
setVisibility: function(visibility) {
if (visibility != this.visibility) {
this.visibility = visibility;
this.display(visibility);
this.redraw();
+ if (this.map != null) {
+ this.map.events.triggerEvent("changelayer", {
+ layer: this,
+ property: "visibility"
+ });
+ }
this.events.triggerEvent("visibilitychanged");
}
},
/**
@@ -27740,15 +28186,10 @@
* display - {Boolean}
*/
display: function(display) {
if (display != (this.div.style.display != "none")) {
this.div.style.display = (display && this.calculateInRange()) ? "block" : "none";
- if(this.map){
- this.map.events.triggerEvent("changelayer", {
- layer: this, property: "visibility"
- });
- }
}
},
/**
* APIMethod: calculateInRange
@@ -28359,11 +28800,11 @@
});
/* ======================================================================
OpenLayers/Layer/SphericalMercator.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -28509,11 +28950,11 @@
};
/* ======================================================================
OpenLayers/Layer/EventPane.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -28637,10 +29078,12 @@
// if map didn't load, display warning
if (this.mapObject == null) {
this.loadWarningMessage();
}
+
+ this.map.events.register('zoomstart', this, this.onZoomStart);
},
/**
* APIMethod: removeMap
* On being removed from the map, we'll like to remove the invisible 'pane'
@@ -28648,15 +29091,31 @@
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
removeMap: function(map) {
+ this.map.events.unregister('zoomstart', this, this.onZoomStart);
+
if (this.pane && this.pane.parentNode) {
this.pane.parentNode.removeChild(this.pane);
}
OpenLayers.Layer.prototype.removeMap.apply(this, arguments);
},
+
+ /**
+ * Method: onZoomStart
+ *
+ * Parameters:
+ * evt - zoomstart event object with center and zoom properties.
+ */
+ onZoomStart: function(evt) {
+ if (this.mapObject != null) {
+ var center = this.getMapObjectLonLatFromOLLonLat(evt.center);
+ var zoom = this.getMapObjectZoomFromOLZoom(evt.zoom);
+ this.setMapObjectCenter(center, zoom, false);
+ }
+ },
/**
* Method: loadWarningMessage
* If we can't load the map lib, then display an error message to the
* user and tell them where to go for help.
@@ -28954,11 +29413,11 @@
});
/* ======================================================================
OpenLayers/Layer/FixedZoomLevels.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -29277,11 +29736,11 @@
/* ======================================================================
OpenLayers/Layer/Google.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -29388,13 +29847,11 @@
* options - {Object} An optional object whose properties will be set
* on the layer.
*/
initialize: function(name, options) {
options = options || {};
- if(!options.version) {
- options.version = typeof GMap2 === "function" ? "2" : "3";
- }
+ options.version = "3";
var mixin = OpenLayers.Layer.Google["v" +
options.version.replace(/\./g, "_")];
if (mixin) {
OpenLayers.Util.applyDefaults(options, mixin);
} else {
@@ -29553,10 +30010,14 @@
}
var poweredBy = cache.poweredBy;
if (poweredBy && poweredBy.parentNode) {
poweredBy.parentNode.removeChild(poweredBy);
}
+ if (this.mapObject && window.google && google.maps &&
+ google.maps.event && google.maps.event.clearListeners) {
+ google.maps.event.clearListeners(this.mapObject, 'tilesloaded');
+ }
}
},
/**
* APIMethod: removeMap
@@ -29740,357 +30201,165 @@
/**
* Property: OpenLayers.Layer.Google.cache
* {Object} Cache for elements that should only be created once per map.
*/
OpenLayers.Layer.Google.cache = {};
+/* ======================================================================
+ OpenLayers/Format/TMSCapabilities.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. */
/**
- * Constant: OpenLayers.Layer.Google.v2
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/BaseTypes/Bounds.js
+ * @requires OpenLayers/BaseTypes/LonLat.js
+ */
+
+/**
+ * Class: OpenLayers.Format.TMSCapabilities
+ * Parse TMS Capabilities.
+ * See http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
*
- * Mixin providing functionality specific to the Google Maps API v2.
- *
- * This API has been deprecated by Google.
- * Developers are encouraged to migrate to v3 of the API; support for this
- * is provided by <OpenLayers.Layer.Google.v3>
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
*/
-OpenLayers.Layer.Google.v2 = {
-
- /**
- * Property: termsOfUse
- * {DOMElement} Div for Google's copyright and terms of use link
- */
- termsOfUse: null,
+OpenLayers.Format.TMSCapabilities = OpenLayers.Class(
+ OpenLayers.Format.XML, {
/**
- * Property: poweredBy
- * {DOMElement} Div for Google's powered by logo and link
+ * Property: defaultPrefix
*/
- poweredBy: null,
+ defaultPrefix: "tms",
/**
- * Property: dragObject
- * {GDraggableObject} Since 2.93, Google has exposed the ability to get
- * the maps GDraggableObject. We can now use this for smooth panning
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
*/
- dragObject: null,
-
- /**
- * Method: loadMapObject
- * Load the GMap and register appropriate event listeners. If we can't
- * load GMap2, then display a warning message.
- */
- loadMapObject:function() {
- if (!this.type) {
- this.type = G_NORMAL_MAP;
- }
- var mapObject, termsOfUse, poweredBy;
- var cache = OpenLayers.Layer.Google.cache[this.map.id];
- if (cache) {
- // there are already Google layers added to this map
- mapObject = cache.mapObject;
- termsOfUse = cache.termsOfUse;
- poweredBy = cache.poweredBy;
- // increment the layer count
- ++cache.count;
- } else {
- // this is the first Google layer for this map
-
- var container = this.map.viewPortDiv;
- var div = document.createElement("div");
- div.id = this.map.id + "_GMap2Container";
- div.style.position = "absolute";
- div.style.width = "100%";
- div.style.height = "100%";
- container.appendChild(div);
-
- // create GMap and shuffle elements
- try {
- mapObject = new GMap2(div);
-
- // move the ToS and branding stuff up to the container div
- termsOfUse = div.lastChild;
- container.appendChild(termsOfUse);
- termsOfUse.style.zIndex = "1100";
- termsOfUse.style.right = "";
- termsOfUse.style.bottom = "";
- termsOfUse.className = "olLayerGoogleCopyright";
-
- poweredBy = div.lastChild;
- container.appendChild(poweredBy);
- poweredBy.style.zIndex = "1100";
- poweredBy.style.right = "";
- poweredBy.style.bottom = "";
- poweredBy.className = "olLayerGooglePoweredBy gmnoprint";
-
- } catch (e) {
- throw(e);
- }
- // cache elements for use by any other google layers added to
- // this same map
- OpenLayers.Layer.Google.cache[this.map.id] = {
- mapObject: mapObject,
- termsOfUse: termsOfUse,
- poweredBy: poweredBy,
- count: 1
- };
- }
-
- this.mapObject = mapObject;
- this.termsOfUse = termsOfUse;
- this.poweredBy = poweredBy;
-
- // ensure this layer type is one of the mapObject types
- if (OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),
- this.type) === -1) {
- this.mapObject.addMapType(this.type);
- }
-
- //since v 2.93 getDragObject is now available.
- if(typeof mapObject.getDragObject == "function") {
- this.dragObject = mapObject.getDragObject();
- } else {
- this.dragPanMapObject = null;
- }
-
- if(this.isBaseLayer === false) {
- this.setGMapVisibility(this.div.style.display !== "none");
- }
-
- },
-
- /**
- * APIMethod: onMapResize
- */
- onMapResize: function() {
- // workaround for resizing of invisible or not yet fully loaded layers
- // where GMap2.checkResize() does not work. We need to load the GMap
- // for the old div size, then checkResize(), and then call
- // layer.moveTo() to trigger GMap.setCenter() (which will finish
- // the GMap initialization).
- if(this.visibility && this.mapObject.isLoaded()) {
- this.mapObject.checkResize();
- } else {
- if(!this._resized) {
- var layer = this;
- var handle = GEvent.addListener(this.mapObject, "load", function() {
- GEvent.removeListener(handle);
- delete layer._resized;
- layer.mapObject.checkResize();
- layer.moveTo(layer.map.getCenter(), layer.map.getZoom());
- });
- }
- this._resized = true;
- }
- },
-
- /**
- * Method: setGMapVisibility
- * Display the GMap container and associated elements.
- *
- * Parameters:
- * visible - {Boolean} Display the GMap elements.
- */
- setGMapVisibility: function(visible) {
- var cache = OpenLayers.Layer.Google.cache[this.map.id];
- if (cache) {
- var container = this.mapObject.getContainer();
- if (visible === true) {
- this.mapObject.setMapType(this.type);
- container.style.display = "";
- this.termsOfUse.style.left = "";
- this.termsOfUse.style.display = "";
- this.poweredBy.style.display = "";
- cache.displayed = this.id;
- } else {
- if (cache.displayed === this.id) {
- delete cache.displayed;
+ readers: {
+ "tms": {
+ "Services": function(node, obj) {
+ obj.services = [];
+ this.readChildNodes(node, obj);
+ },
+ "TileMapService": function(node, obj) {
+ if (obj.services) {
+ obj.services.push({
+ service: 'TMS',
+ version: node.getAttribute("version"),
+ title: node.getAttribute("title"),
+ href: node.getAttribute("href")
+ });
+ } else {
+ this.readChildNodes(node, obj);
}
- if (!cache.displayed) {
- container.style.display = "none";
- this.termsOfUse.style.display = "none";
- // move ToU far to the left in addition to setting display
- // to "none", because at the end of the GMap2 load
- // sequence, display: none will be unset and ToU would be
- // visible after loading a map with a google layer that is
- // initially hidden.
- this.termsOfUse.style.left = "-9999px";
- this.poweredBy.style.display = "none";
+ },
+ "TileMaps": function(node, obj) {
+ obj.tileMaps = [];
+ this.readChildNodes(node, obj);
+ },
+ "TileMap": function(node, obj) {
+ if (obj.tileMaps) {
+ obj.tileMaps.push({
+ href: node.getAttribute("href"),
+ srs: node.getAttribute("srs"),
+ title: node.getAttribute("title"),
+ profile: node.getAttribute("profile")
+ });
+ } else {
+ obj.version = node.getAttribute("version");
+ obj.tileMapService = node.getAttribute("tilemapservice");
+ this.readChildNodes(node, obj);
}
+ },
+ "Title": function(node, obj) {
+ obj.title = this.getChildValue(node);
+ },
+ "Abstract": function(node, obj) {
+ obj['abstract'] = this.getChildValue(node);
+ },
+ "SRS": function(node, obj) {
+ obj.srs = this.getChildValue(node);
+ },
+ "BoundingBox": function(node, obj) {
+ obj.bbox = new OpenLayers.Bounds(
+ node.getAttribute("minx"),
+ node.getAttribute("miny"),
+ node.getAttribute("maxx"),
+ node.getAttribute("maxy"));
+ },
+ "Origin": function(node, obj) {
+ obj.origin = new OpenLayers.LonLat(
+ node.getAttribute("x"),
+ node.getAttribute("y"));
+ },
+ "TileFormat": function(node, obj) {
+ obj.tileFormat = {
+ width: parseInt(node.getAttribute("width"), 10),
+ height: parseInt(node.getAttribute("height"), 10),
+ mimeType: node.getAttribute("mime-type"),
+ extension: node.getAttribute("extension")
+ };
+ },
+ "TileSets": function(node, obj) {
+ obj.tileSets = [];
+ this.readChildNodes(node, obj);
+ },
+ "TileSet": function(node, obj) {
+ obj.tileSets.push({
+ href: node.getAttribute("href"),
+ unitsPerPixel: parseFloat(node.getAttribute("units-per-pixel")),
+ order: parseInt(node.getAttribute("order"), 10)
+ });
+ },
+ "TileMapServerError": function(node, obj) {
+ obj.error = true;
+ },
+ "Message": function(node, obj) {
+ obj.message = this.getChildValue(node);
}
}
},
-
- /**
- * Method: getMapContainer
- *
- * Returns:
- * {DOMElement} the GMap container's div
- */
- getMapContainer: function() {
- return this.mapObject.getContainer();
- },
- //
- // TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds
- //
-
/**
- * APIMethod: getMapObjectBoundsFromOLBounds
+ * APIMethod: read
+ * Read TMS capabilities data from a string, and return a list of tilesets.
*
- * Parameters:
- * olBounds - {<OpenLayers.Bounds>}
- *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
* Returns:
- * {Object} A MapObject Bounds, translated from olBounds
- * Returns null if null value is passed in
+ * {Object} Information about the services served by this TMS instance.
*/
- getMapObjectBoundsFromOLBounds: function(olBounds) {
- var moBounds = null;
- if (olBounds != null) {
- var sw = this.sphericalMercator ?
- this.inverseMercator(olBounds.bottom, olBounds.left) :
- new OpenLayers.LonLat(olBounds.bottom, olBounds.left);
- var ne = this.sphericalMercator ?
- this.inverseMercator(olBounds.top, olBounds.right) :
- new OpenLayers.LonLat(olBounds.top, olBounds.right);
- moBounds = new GLatLngBounds(new GLatLng(sw.lat, sw.lon),
- new GLatLng(ne.lat, ne.lon));
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
}
- return moBounds;
- },
-
-
- /************************************
- * *
- * MapObject Interface Controls *
- * *
- ************************************/
-
-
- // Get&Set Center, Zoom
-
- /**
- * APIMethod: setMapObjectCenter
- * Set the mapObject to the specified center and zoom
- *
- * Parameters:
- * center - {Object} MapObject LonLat format
- * zoom - {int} MapObject zoom format
- */
- setMapObjectCenter: function(center, zoom) {
- this.mapObject.setCenter(center, zoom);
- },
-
- /**
- * APIMethod: dragPanMapObject
- *
- * Parameters:
- * dX - {Integer}
- * dY - {Integer}
- */
- dragPanMapObject: function(dX, dY) {
- this.dragObject.moveBy(new GSize(-dX, dY));
- },
-
-
- // LonLat - Pixel Translation
-
- /**
- * APIMethod: getMapObjectLonLatFromMapObjectPixel
- *
- * Parameters:
- * moPixel - {Object} MapObject Pixel format
- *
- * Returns:
- * {Object} MapObject LonLat translated from MapObject Pixel
- */
- getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
- return this.mapObject.fromContainerPixelToLatLng(moPixel);
- },
-
- /**
- * APIMethod: getMapObjectPixelFromMapObjectLonLat
- *
- * Parameters:
- * moLonLat - {Object} MapObject LonLat format
- *
- * Returns:
- * {Object} MapObject Pixel transtlated from MapObject LonLat
- */
- getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
- return this.mapObject.fromLatLngToContainerPixel(moLonLat);
- },
-
-
- // Bounds
-
- /**
- * APIMethod: getMapObjectZoomFromMapObjectBounds
- *
- * Parameters:
- * moBounds - {Object} MapObject Bounds format
- *
- * Returns:
- * {Object} MapObject Zoom for specified MapObject Bounds
- */
- getMapObjectZoomFromMapObjectBounds: function(moBounds) {
- return this.mapObject.getBoundsZoomLevel(moBounds);
- },
-
- /************************************
- * *
- * MapObject Primitives *
- * *
- ************************************/
-
-
- // LonLat
-
- /**
- * APIMethod: getMapObjectLonLatFromLonLat
- *
- * Parameters:
- * lon - {Float}
- * lat - {Float}
- *
- * Returns:
- * {Object} MapObject LonLat built from lon and lat params
- */
- getMapObjectLonLatFromLonLat: function(lon, lat) {
- var gLatLng;
- if(this.sphericalMercator) {
- var lonlat = this.inverseMercator(lon, lat);
- gLatLng = new GLatLng(lonlat.lat, lonlat.lon);
- } else {
- gLatLng = new GLatLng(lat, lon);
+ var raw = data;
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
}
- return gLatLng;
+ var capabilities = {};
+ this.readNode(data, capabilities);
+ return capabilities;
},
- // Pixel
-
- /**
- * APIMethod: getMapObjectPixelFromXY
- *
- * Parameters:
- * x - {Integer}
- * y - {Integer}
- *
- * Returns:
- * {Object} MapObject Pixel from x and y parameters
- */
- getMapObjectPixelFromXY: function(x, y) {
- return new GPoint(x, y);
- }
-
-};
+ CLASS_NAME: "OpenLayers.Format.TMSCapabilities"
+
+});
/* ======================================================================
OpenLayers/Format/WFST.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -30124,11 +30393,11 @@
};
/* ======================================================================
OpenLayers/Format/WFST/v1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -30314,12 +30583,12 @@
* - *modified* is not set at all: The geometry and all attributes will be
* included.
* - *modified.geometry* is set (null or a geometry): The geometry will be
* included. If *modified.attributes* is not set, all attributes will
* be included.
- * - *modified.attributes* is set: Only the attributes set (i.e. to null or
- * a value) in *modified.attributes* will be included.
+ * - *modified.attributes* is set: Only the attributes set in
+ * *modified.attributes* will be included.
* If *modified.geometry* is not set, the geometry will not be included.
*
* Valid options include:
* - *multi* {Boolean} If set to true, geometries will be casted to
* Multi geometries before writing.
@@ -30462,11 +30731,11 @@
// add in attributes
for(var key in feature.attributes) {
if(feature.attributes[key] !== undefined &&
(!modified || !modified.attributes ||
- (modified.attributes && modified.attributes[key] !== undefined))) {
+ (modified.attributes && (key in modified.attributes)))) {
this.writeNode(
"Property", {name: key, value: feature.attributes[key]}, node
);
}
}
@@ -30574,11 +30843,11 @@
});
/* ======================================================================
OpenLayers/Format/GML/v3.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -30713,11 +30982,14 @@
} else {
point = new OpenLayers.Geometry.Point(
coords[1], coords[0], coords[2]
);
}
- obj.points = [point];
+ if(!!!obj.points) {
+ obj.points = [];
+ }
+ obj.points.push(point);
},
"posList": function(node, obj) {
var str = this.getChildValue(node).replace(
this.regExes.trimSpace, ""
);
@@ -30804,10 +31076,11 @@
var obj = {points: new Array(2)};
this.readChildNodes(node, obj);
if(!container.components) {
container.components = [];
}
+
var min = obj.points[0];
var max = obj.points[1];
container.components.push(
new OpenLayers.Bounds(min.x, min.y, max.x, max.y)
);
@@ -31055,11 +31328,11 @@
});
/* ======================================================================
OpenLayers/Format/Filter/v1_1_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -31281,11 +31554,11 @@
});
/* ======================================================================
OpenLayers/Format/WFST/v1_1_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -31471,416 +31744,14 @@
},
CLASS_NAME: "OpenLayers.Format.WFST.v1_1_0"
});
/* ======================================================================
- OpenLayers/Format/JSON.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. */
-
-/**
- * Note:
- * This work draws heavily from the public domain JSON serializer/deserializer
- * at http://www.json.org/json.js. Rewritten so that it doesn't modify
- * basic data prototypes.
- */
-
-/**
- * @requires OpenLayers/Format.js
- */
-
-/**
- * Class: OpenLayers.Format.JSON
- * A parser to read/write JSON safely. Create a new instance with the
- * <OpenLayers.Format.JSON> constructor.
- *
- * Inherits from:
- * - <OpenLayers.Format>
- */
-OpenLayers.Format.JSON = OpenLayers.Class(OpenLayers.Format, {
-
- /**
- * APIProperty: indent
- * {String} For "pretty" printing, the indent string will be used once for
- * each indentation level.
- */
- indent: " ",
-
- /**
- * APIProperty: space
- * {String} For "pretty" printing, the space string will be used after
- * the ":" separating a name/value pair.
- */
- space: " ",
-
- /**
- * APIProperty: newline
- * {String} For "pretty" printing, the newline string will be used at the
- * end of each name/value pair or array item.
- */
- newline: "\n",
-
- /**
- * Property: level
- * {Integer} For "pretty" printing, this is incremented/decremented during
- * serialization.
- */
- level: 0,
-
- /**
- * Property: pretty
- * {Boolean} Serialize with extra whitespace for structure. This is set
- * by the <write> method.
- */
- pretty: false,
-
- /**
- * Property: nativeJSON
- * {Boolean} Does the browser support native json?
- */
- nativeJSON: (function() {
- return !!(window.JSON && typeof JSON.parse == "function" && typeof JSON.stringify == "function");
- })(),
-
- /**
- * Constructor: OpenLayers.Format.JSON
- * Create a new parser for JSON.
- *
- * Parameters:
- * options - {Object} An optional object whose properties will be set on
- * this instance.
- */
-
- /**
- * APIMethod: read
- * Deserialize a json string.
- *
- * Parameters:
- * json - {String} A JSON string
- * filter - {Function} A function which will be called for every key and
- * value at every level of the final result. Each value will be
- * replaced by the result of the filter function. This can be used to
- * reform generic objects into instances of classes, or to transform
- * date strings into Date objects.
- *
- * Returns:
- * {Object} An object, array, string, or number .
- */
- read: function(json, filter) {
- var object;
- if (this.nativeJSON) {
- object = JSON.parse(json, filter);
- } else try {
- /**
- * Parsing happens in three stages. In the first stage, we run the
- * text against a regular expression which looks for non-JSON
- * characters. We are especially concerned with '()' and 'new'
- * because they can cause invocation, and '=' because it can
- * cause mutation. But just to be safe, we will reject all
- * unexpected characters.
- */
- if (/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g, '@').
- replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
- replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
-
- /**
- * In the second stage we use the eval function to compile the
- * text into a JavaScript structure. The '{' operator is
- * subject to a syntactic ambiguity in JavaScript - it can
- * begin a block or an object literal. We wrap the text in
- * parens to eliminate the ambiguity.
- */
- object = eval('(' + json + ')');
-
- /**
- * In the optional third stage, we recursively walk the new
- * structure, passing each name/value pair to a filter
- * function for possible transformation.
- */
- if(typeof filter === 'function') {
- function walk(k, v) {
- if(v && typeof v === 'object') {
- for(var i in v) {
- if(v.hasOwnProperty(i)) {
- v[i] = walk(i, v[i]);
- }
- }
- }
- return filter(k, v);
- }
- object = walk('', object);
- }
- }
- } catch(e) {
- // Fall through if the regexp test fails.
- }
-
- if(this.keepData) {
- this.data = object;
- }
-
- return object;
- },
-
- /**
- * APIMethod: write
- * Serialize an object into a JSON string.
- *
- * Parameters:
- * value - {String} The object, array, string, number, boolean or date
- * to be serialized.
- * pretty - {Boolean} Structure the output with newlines and indentation.
- * Default is false.
- *
- * Returns:
- * {String} The JSON string representation of the input value.
- */
- write: function(value, pretty) {
- this.pretty = !!pretty;
- var json = null;
- var type = typeof value;
- if(this.serialize[type]) {
- try {
- json = (!this.pretty && this.nativeJSON) ?
- JSON.stringify(value) :
- this.serialize[type].apply(this, [value]);
- } catch(err) {
- OpenLayers.Console.error("Trouble serializing: " + err);
- }
- }
- return json;
- },
-
- /**
- * Method: writeIndent
- * Output an indentation string depending on the indentation level.
- *
- * Returns:
- * {String} An appropriate indentation string.
- */
- writeIndent: function() {
- var pieces = [];
- if(this.pretty) {
- for(var i=0; i<this.level; ++i) {
- pieces.push(this.indent);
- }
- }
- return pieces.join('');
- },
-
- /**
- * Method: writeNewline
- * Output a string representing a newline if in pretty printing mode.
- *
- * Returns:
- * {String} A string representing a new line.
- */
- writeNewline: function() {
- return (this.pretty) ? this.newline : '';
- },
-
- /**
- * Method: writeSpace
- * Output a string representing a space if in pretty printing mode.
- *
- * Returns:
- * {String} A space.
- */
- writeSpace: function() {
- return (this.pretty) ? this.space : '';
- },
-
- /**
- * Property: serialize
- * Object with properties corresponding to the serializable data types.
- * Property values are functions that do the actual serializing.
- */
- serialize: {
- /**
- * Method: serialize.object
- * Transform an object into a JSON string.
- *
- * Parameters:
- * object - {Object} The object to be serialized.
- *
- * Returns:
- * {String} A JSON string representing the object.
- */
- 'object': function(object) {
- // three special objects that we want to treat differently
- if(object == null) {
- return "null";
- }
- if(object.constructor == Date) {
- return this.serialize.date.apply(this, [object]);
- }
- if(object.constructor == Array) {
- return this.serialize.array.apply(this, [object]);
- }
- var pieces = ['{'];
- this.level += 1;
- var key, keyJSON, valueJSON;
-
- var addComma = false;
- for(key in object) {
- if(object.hasOwnProperty(key)) {
- // recursive calls need to allow for sub-classing
- keyJSON = OpenLayers.Format.JSON.prototype.write.apply(this,
- [key, this.pretty]);
- valueJSON = OpenLayers.Format.JSON.prototype.write.apply(this,
- [object[key], this.pretty]);
- if(keyJSON != null && valueJSON != null) {
- if(addComma) {
- pieces.push(',');
- }
- pieces.push(this.writeNewline(), this.writeIndent(),
- keyJSON, ':', this.writeSpace(), valueJSON);
- addComma = true;
- }
- }
- }
-
- this.level -= 1;
- pieces.push(this.writeNewline(), this.writeIndent(), '}');
- return pieces.join('');
- },
-
- /**
- * Method: serialize.array
- * Transform an array into a JSON string.
- *
- * Parameters:
- * array - {Array} The array to be serialized
- *
- * Returns:
- * {String} A JSON string representing the array.
- */
- 'array': function(array) {
- var json;
- var pieces = ['['];
- this.level += 1;
-
- for(var i=0, len=array.length; i<len; ++i) {
- // recursive calls need to allow for sub-classing
- json = OpenLayers.Format.JSON.prototype.write.apply(this,
- [array[i], this.pretty]);
- if(json != null) {
- if(i > 0) {
- pieces.push(',');
- }
- pieces.push(this.writeNewline(), this.writeIndent(), json);
- }
- }
-
- this.level -= 1;
- pieces.push(this.writeNewline(), this.writeIndent(), ']');
- return pieces.join('');
- },
-
- /**
- * Method: serialize.string
- * Transform a string into a JSON string.
- *
- * Parameters:
- * string - {String} The string to be serialized
- *
- * Returns:
- * {String} A JSON string representing the string.
- */
- 'string': function(string) {
- // If the string contains no control characters, no quote characters, and no
- // backslash characters, then we can simply slap some quotes around it.
- // Otherwise we must also replace the offending characters with safe
- // sequences.
- var m = {
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '"' : '\\"',
- '\\': '\\\\'
- };
- if(/["\\\x00-\x1f]/.test(string)) {
- return '"' + string.replace(/([\x00-\x1f\\"])/g, function(a, b) {
- var c = m[b];
- if(c) {
- return c;
- }
- c = b.charCodeAt();
- return '\\u00' +
- Math.floor(c / 16).toString(16) +
- (c % 16).toString(16);
- }) + '"';
- }
- return '"' + string + '"';
- },
-
- /**
- * Method: serialize.number
- * Transform a number into a JSON string.
- *
- * Parameters:
- * number - {Number} The number to be serialized.
- *
- * Returns:
- * {String} A JSON string representing the number.
- */
- 'number': function(number) {
- return isFinite(number) ? String(number) : "null";
- },
-
- /**
- * Method: serialize.boolean
- * Transform a boolean into a JSON string.
- *
- * Parameters:
- * bool - {Boolean} The boolean to be serialized.
- *
- * Returns:
- * {String} A JSON string representing the boolean.
- */
- 'boolean': function(bool) {
- return String(bool);
- },
-
- /**
- * Method: serialize.object
- * Transform a date into a JSON string.
- *
- * Parameters:
- * date - {Date} The date to be serialized.
- *
- * Returns:
- * {String} A JSON string representing the date.
- */
- 'date': function(date) {
- function format(number) {
- // Format integers to have at least two digits.
- return (number < 10) ? '0' + number : number;
- }
- return '"' + date.getFullYear() + '-' +
- format(date.getMonth() + 1) + '-' +
- format(date.getDate()) + 'T' +
- format(date.getHours()) + ':' +
- format(date.getMinutes()) + ':' +
- format(date.getSeconds()) + '"';
- }
- },
-
- CLASS_NAME: "OpenLayers.Format.JSON"
-
-});
-/* ======================================================================
OpenLayers/Format/WFSCapabilities.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -31927,11 +31798,11 @@
});
/* ======================================================================
OpenLayers/Format/WFSCapabilities/v1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -32124,19 +31995,20 @@
else if (this.geometryType == "multipoint")
geomType = OpenLayers.Geometry.MultiPoint;
else if (this.geometryType != "point" && this.geometryType != "polygon")
return null;
- var points = this.decode(encoded, 2);
- var pointGeometries = new Array();
- for (var i in points) {
- var point = points[i];
- pointGeometries.push(
- new OpenLayers.Geometry.Point(point[1] * 1e-5, point[0] * 1e-5)
- );
+ var flatPoints = this.decodeDeltas(encoded, 2);
+ var flatPointsLength = flatPoints.length;
+
+ var pointGeometries = [];
+ for (var i = 0; i + 1 < flatPointsLength;) {
+ var y = flatPoints[i++], x = flatPoints[i++];
+ pointGeometries.push(new OpenLayers.Geometry.Point(x, y));
}
+
if (this.geometryType == "point")
return new OpenLayers.Feature.Vector(
pointGeometries[0]
);
@@ -32163,34 +32035,24 @@
*
* Returns:
* {Array(Array(int))} An array containing n-dimensional arrays of
* coordinates.
*/
- decode: function(encoded, dims) {
- var points = new Array();
- var point = new Array(dims);
+ decode: function(encoded, dims, opt_factor) {
+ var factor = opt_factor || 1e5;
+ var flatPoints = this.decodeDeltas(encoded, dims, factor);
+ var flatPointsLength = flatPoints.length;
- // Reset the point array
- for (var i = 0; i < point.length; ++i)
- point[i] = 0;
+ var points = [];
+ for (var i = 0; i + (dims - 1) < flatPointsLength;) {
+ var point = [];
- for (var i = 0; i < encoded.length;) {
for (var dim = 0; dim < dims; ++dim) {
- var result = 0;
- var shift = 0;
-
- var b;
- do {
- b = encoded.charCodeAt(i++) - 63;
- result |= (b & 0x1f) << shift;
- shift += 5;
- } while (b >= 0x20);
-
- point[dim] += ((result & 1) ? ~(result >> 1) : (result >> 1));
+ point.push(flatPoints[i++])
}
- points.push(point.slice(0));
+ points.push(point);
}
return points;
},
@@ -32225,20 +32087,20 @@
else if (type == "polygon")
pointGeometries = geometry.components[0].components;
else
return null;
- var points = new Array();
- for (var i in pointGeometries) {
+ var flatPoints = [];
+
+ var pointGeometriesLength = pointGeometries.length;
+ for (var i = 0; i < pointGeometriesLength; ++i) {
var pointGeometry = pointGeometries[i];
- var point = [Math.round(pointGeometry.y * 1e5),
- Math.round(pointGeometry.x * 1e5)];
- points.push(point);
+ flatPoints.push(pointGeometry.y);
+ flatPoints.push(pointGeometry.x);
}
- var result = this.encode(points, 2);
- return result;
+ return this.encodeDeltas(flatPoints, 2);
},
/**
* APIMethod: encode
* Serialize an array of n-dimensional points and return an encoded string
@@ -32249,80 +32111,392 @@
* dims - {int} The dimension of the points that should be read
*
* Returns:
* {String} An encoded string
*/
- encode: function (points, dims) {
- var encoded_points = "";
+ encode: function (points, dims, opt_factor) {
+ var factor = opt_factor || 1e5;
+ var flatPoints = [];
- var lastPoint = new Array(dims);
- for (var i = 0; i < lastPoint.length; ++i)
- lastPoint[i] = 0;
-
- for (var i = 0; i < points.length; i++) {
+ var pointsLength = points.length;
+ for (var i = 0; i < pointsLength; ++i) {
var point = points[i];
- for (var dim = 0; dim < lastPoint.length; ++dim) {
- var delta = point[dim] - lastPoint[dim];
- encoded_points += this.encodeSignedNumber(delta);
+ for (var dim = 0; dim < dims; ++dim) {
+ flatPoints.push(point[dim]);
}
+ }
- lastPoint = point;
+ return this.encodeDeltas(flatPoints, dims, factor);
+ },
+
+ /**
+ * APIMethod: encodeDeltas
+ * Encode a list of n-dimensional points and return an encoded string
+ *
+ * Attention: This function will modify the passed array!
+ *
+ * Parameters:
+ * numbers - {Array.<number>} A list of n-dimensional points.
+ * dimension - {number} The dimension of the points in the list.
+ * opt_factor - {number=} The factor by which the numbers will be
+ * multiplied. The remaining decimal places will get rounded away.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeDeltas: function(numbers, dimension, opt_factor) {
+ var factor = opt_factor || 1e5;
+ var d;
+
+ var lastNumbers = new Array(dimension);
+ for (d = 0; d < dimension; ++d) {
+ lastNumbers[d] = 0;
+ }
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength;) {
+ for (d = 0; d < dimension; ++d, ++i) {
+ var num = numbers[i];
+ var delta = num - lastNumbers[d];
+ lastNumbers[d] = num;
+
+ numbers[i] = delta;
}
- return encoded_points;
+ }
+
+ return this.encodeFloats(numbers, factor);
},
+
/**
- * Method: encodeSignedNumber
+ * APIMethod: decodeDeltas
+ * Decode a list of n-dimensional points from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ * dimension - {number} The dimension of the points in the encoded string.
+ * opt_factor - {number=} The factor by which the resulting numbers will
+ * be divided.
+ *
+ * Returns:
+ * {Array.<number>} A list of n-dimensional points.
+ */
+ decodeDeltas: function(encoded, dimension, opt_factor) {
+ var factor = opt_factor || 1e5;
+ var d;
+
+ var lastNumbers = new Array(dimension);
+ for (d = 0; d < dimension; ++d) {
+ lastNumbers[d] = 0;
+ }
+
+ var numbers = this.decodeFloats(encoded, factor);
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength;) {
+ for (d = 0; d < dimension; ++d, ++i) {
+ lastNumbers[d] += numbers[i];
+
+ numbers[i] = lastNumbers[d];
+ }
+ }
+
+ return numbers;
+ },
+
+
+ /**
+ * APIMethod: encodeFloats
+ * Encode a list of floating point numbers and return an encoded string
+ *
+ * Attention: This function will modify the passed array!
+ *
+ * Parameters:
+ * numbers - {Array.<number>} A list of floating point numbers.
+ * opt_factor - {number=} The factor by which the numbers will be
+ * multiplied. The remaining decimal places will get rounded away.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeFloats: function(numbers, opt_factor) {
+ var factor = opt_factor || 1e5;
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength; ++i) {
+ numbers[i] = Math.round(numbers[i] * factor);
+ }
+
+ return this.encodeSignedIntegers(numbers);
+ },
+
+
+ /**
+ * APIMethod: decodeFloats
+ * Decode a list of floating point numbers from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ * opt_factor - {number=} The factor by which the result will be divided.
+ *
+ * Returns:
+ * {Array.<number>} A list of floating point numbers.
+ */
+ decodeFloats: function(encoded, opt_factor) {
+ var factor = opt_factor || 1e5;
+
+ var numbers = this.decodeSignedIntegers(encoded);
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength; ++i) {
+ numbers[i] /= factor;
+ }
+
+ return numbers;
+ },
+
+
+ /**
+ * APIMethod: encodeSignedIntegers
+ * Encode a list of signed integers and return an encoded string
+ *
+ * Attention: This function will modify the passed array!
+ *
+ * Parameters:
+ * numbers - {Array.<number>} A list of signed integers.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeSignedIntegers: function(numbers) {
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength; ++i) {
+ var num = numbers[i];
+
+ var signedNum = num << 1;
+ if (num < 0) {
+ signedNum = ~(signedNum);
+ }
+
+ numbers[i] = signedNum;
+ }
+
+ return this.encodeUnsignedIntegers(numbers);
+ },
+
+
+ /**
+ * APIMethod: decodeSignedIntegers
+ * Decode a list of signed integers from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ *
+ * Returns:
+ * {Array.<number>} A list of signed integers.
+ */
+ decodeSignedIntegers: function(encoded) {
+ var numbers = this.decodeUnsignedIntegers(encoded);
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength; ++i) {
+ var num = numbers[i];
+ numbers[i] = (num & 1) ? ~(num >> 1) : (num >> 1);
+ }
+
+ return numbers;
+ },
+
+
+ /**
+ * APIMethod: encodeUnsignedIntegers
+ * Encode a list of unsigned integers and return an encoded string
+ *
+ * Parameters:
+ * numbers - {Array.<number>} A list of unsigned integers.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeUnsignedIntegers: function(numbers) {
+ var encoded = '';
+
+ var numbersLength = numbers.length;
+ for (var i = 0; i < numbersLength; ++i) {
+ encoded += this.encodeUnsignedInteger(numbers[i]);
+ }
+
+ return encoded;
+ },
+
+
+ /**
+ * APIMethod: decodeUnsignedIntegers
+ * Decode a list of unsigned integers from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ *
+ * Returns:
+ * {Array.<number>} A list of unsigned integers.
+ */
+ decodeUnsignedIntegers: function(encoded) {
+ var numbers = [];
+
+ var current = 0;
+ var shift = 0;
+
+ var encodedLength = encoded.length;
+ for (var i = 0; i < encodedLength; ++i) {
+ var b = encoded.charCodeAt(i) - 63;
+
+ current |= (b & 0x1f) << shift;
+
+ if (b < 0x20) {
+ numbers.push(current);
+ current = 0;
+ shift = 0;
+ } else {
+ shift += 5;
+ }
+ }
+
+ return numbers;
+ },
+
+
+ /**
+ * Method: encodeFloat
+ * Encode one single floating point number and return an encoded string
+ *
+ * Parameters:
+ * num - {number} Floating point number that should be encoded.
+ * opt_factor - {number=} The factor by which num will be multiplied.
+ * The remaining decimal places will get rounded away.
+ *
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeFloat: function(num, opt_factor) {
+ num = Math.round(num * (opt_factor || 1e5));
+ return this.encodeSignedInteger(num);
+ },
+
+
+ /**
+ * Method: decodeFloat
+ * Decode one single floating point number from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ * opt_factor - {number=} The factor by which the result will be divided.
+ *
+ * Returns:
+ * {number} The decoded floating point number.
+ */
+ decodeFloat: function(encoded, opt_factor) {
+ var result = this.decodeSignedInteger(encoded);
+ return result / (opt_factor || 1e5);
+ },
+
+
+ /**
+ * Method: encodeSignedInteger
* Encode one single signed integer and return an encoded string
*
* Parameters:
- * num - {int} A signed integer that should be encoded
+ * num - {number} Signed integer that should be encoded.
*
* Returns:
- * {String} An encoded string
+ * {string} The encoded string.
*/
- encodeSignedNumber: function (num) {
- var sgn_num = num << 1;
- if (num < 0)
- sgn_num = ~(sgn_num);
+ encodeSignedInteger: function(num) {
+ var signedNum = num << 1;
+ if (num < 0) {
+ signedNum = ~(signedNum);
+ }
- return this.encodeNumber(sgn_num);
+ return this.encodeUnsignedInteger(signedNum);
},
+
/**
- * Method: encodeNumber
+ * Method: decodeSignedInteger
+ * Decode one single signed integer from an encoded string
+ *
+ * Parameters:
+ * encoded - {string} An encoded string.
+ *
+ * Returns:
+ * {number} The decoded signed integer.
+ */
+ decodeSignedInteger: function(encoded) {
+ var result = this.decodeUnsignedInteger(encoded);
+ return ((result & 1) ? ~(result >> 1) : (result >> 1));
+ },
+
+
+ /**
+ * Method: encodeUnsignedInteger
* Encode one single unsigned integer and return an encoded string
*
- * encodeSignedNumber should be used instead of using this method directly!
+ * Parameters:
+ * num - {number} Unsigned integer that should be encoded.
*
+ * Returns:
+ * {string} The encoded string.
+ */
+ encodeUnsignedInteger: function(num) {
+ var value, encoded = '';
+ while (num >= 0x20) {
+ value = (0x20 | (num & 0x1f)) + 63;
+ encoded += (String.fromCharCode(value));
+ num >>= 5;
+ }
+ value = num + 63;
+ encoded += (String.fromCharCode(value));
+ return encoded;
+ },
+
+
+ /**
+ * Method: decodeUnsignedInteger
+ * Decode one single unsigned integer from an encoded string
+ *
* Parameters:
- * num - {int} An unsigned integer that should be encoded
+ * encoded - {string} An encoded string.
*
* Returns:
- * {String} An encoded string
+ * {number} The decoded unsigned integer.
*/
- encodeNumber: function (num) {
- var encodeString = "";
- var value;
- while (num >= 0x20) {
- value = (0x20 | (num & 0x1f)) + 63;
- encodeString += (String.fromCharCode(value));
- num >>= 5;
- }
- value = num + 63;
- encodeString += (String.fromCharCode(value));
- return encodeString;
+ decodeUnsignedInteger: function(encoded) {
+ var result = 0;
+ var shift = 0;
+
+ var encodedLength = encoded.length;
+ for (var i = 0; i < encodedLength; ++i) {
+ var b = encoded.charCodeAt(i) - 63;
+
+ result |= (b & 0x1f) << shift;
+
+ if (b < 0x20)
+ break;
+
+ shift += 5;
+ }
+
+ return result;
},
CLASS_NAME: "OpenLayers.Format.EncodedPolyline"
});
/* ======================================================================
OpenLayers/Control/Panel.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -32753,11 +32927,11 @@
/* ======================================================================
OpenLayers/Control/Button.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -32801,11 +32975,11 @@
});
/* ======================================================================
OpenLayers/Control/ZoomIn.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -32834,11 +33008,11 @@
});
/* ======================================================================
OpenLayers/Control/ZoomOut.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -32867,11 +33041,11 @@
});
/* ======================================================================
OpenLayers/Control/ZoomToMaxExtent.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -32906,11 +33080,11 @@
});
/* ======================================================================
OpenLayers/Control/ZoomPanel.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -32964,11 +33138,11 @@
});
/* ======================================================================
OpenLayers/Layer/HTTPRequest.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -32982,10 +33156,19 @@
* Inherits from:
* - <OpenLayers.Layer>
*/
OpenLayers.Layer.HTTPRequest = OpenLayers.Class(OpenLayers.Layer, {
+ /**
+ * APIProperty: events
+ * {<OpenLayers.Events>}
+ *
+ * Supported event types (in addition to those from <OpenLayers.Layer.events>):
+ * refresh - Triggered when a redraw is forced, to re-fetch data from the
+ * server.
+ */
+
/**
* Constant: URL_HASH_FACTOR
* {Float} Used to hash URL param strings for multi-WMS server selection.
* Set to the Golden Ratio per Knuth's recommendation.
*/
@@ -33110,10 +33293,11 @@
* Returns:
* {Boolean} The layer was redrawn.
*/
redraw: function(force) {
if (force) {
+ this.events.triggerEvent('refresh');
return this.mergeNewParams({"_olSalt": Math.random()});
} else {
return OpenLayers.Layer.prototype.redraw.apply(this, []);
}
},
@@ -33198,11 +33382,11 @@
});
/* ======================================================================
OpenLayers/Tile.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -33494,19 +33678,20 @@
});
/* ======================================================================
OpenLayers/Tile/Image.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Tile.js
* @requires OpenLayers/Animation.js
+ * @requires OpenLayers/Util.js
*/
/**
* Class: OpenLayers.Tile.Image
* Instances of OpenLayers.Tile.Image are used to manage the image tiles
@@ -33809,15 +33994,21 @@
/**
* Method: initImage
* Creates the content for the frame on the tile.
*/
initImage: function() {
+ if (!this.url && !this.imgDiv) {
+ // fast path out - if there is no tile url and no previous image
+ this.isLoading = false;
+ return;
+ }
this.events.triggerEvent('beforeload');
this.layer.div.appendChild(this.getTile());
this.events.triggerEvent(this._loadEvent);
var img = this.getImage();
- if (this.url && img.getAttribute("src") == this.url) {
+ var src = img.getAttribute('src') || '';
+ if (this.url && OpenLayers.Util.isEquivalentUrl(src, this.url)) {
this._loadTimeout = window.setTimeout(
OpenLayers.Function.bind(this.onImageLoad, this), 0
);
} else {
this.stopLoading();
@@ -34001,11 +34192,11 @@
/* ======================================================================
OpenLayers/Layer/Grid.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -34080,17 +34271,18 @@
singleTile: false,
/** APIProperty: ratio
* {Float} Used only when in single-tile mode, this specifies the
* ratio of the size of the single tile to the size of the map.
+ * Default value is 1.5.
*/
ratio: 1.5,
/**
* APIProperty: buffer
* {Integer} Used only when in gridded mode, this specifies the number of
- * extra rows and colums of tiles on each side which will
+ * extra rows and columns of tiles on each side which will
* surround the minimum grid tiles to cover the map.
* For very slow loading layers, a larger value may increase
* performance somewhat when dragging, but will increase bandwidth
* use significantly.
*/
@@ -34099,20 +34291,25 @@
/**
* APIProperty: transitionEffect
* {String} The transition effect to use when the map is zoomed.
* Two posible values:
*
- * null - No transition effect (the default).
* "resize" - Existing tiles are resized on zoom to provide a visual
- * effect of the zoom having taken place immediately. As the
- * new tiles become available, they are drawn over top of the
- * resized tiles.
+ * effect of the zoom having taken place immediately. As the
+ * new tiles become available, they are drawn on top of the
+ * resized tiles (this is the default setting).
+ * "map-resize" - Existing tiles are resized on zoom and placed below the
+ * base layer. New tiles for the base layer will cover existing tiles.
+ * This setting is recommended when having an overlay duplicated during
+ * the transition is undesirable (e.g. street labels or big transparent
+ * fills).
+ * null - No transition effect.
*
* Using "resize" on non-opaque layers can cause undesired visual
- * effects. This is therefore discouraged.
+ * effects. Set transitionEffect to null in this case.
*/
- transitionEffect: null,
+ transitionEffect: "resize",
/**
* APIProperty: numLoadingTiles
* {Integer} How many tiles are still loading?
*/
@@ -34653,11 +34850,15 @@
if(!backBuffer) {
backBuffer = this.createBackBuffer();
if(!backBuffer) {
return;
}
- this.div.insertBefore(backBuffer, this.div.firstChild);
+ if (resolution === this.gridResolution) {
+ this.div.insertBefore(backBuffer, this.div.firstChild);
+ } else {
+ this.map.baseLayer.div.parentNode.insertBefore(backBuffer, this.map.baseLayer.div);
+ }
this.backBuffer = backBuffer;
// set some information in the instance for subsequent
// calls to applyBackBuffer where the same back buffer
// is reused
@@ -34673,12 +34874,12 @@
// scale the tiles inside the back buffer
var tiles = backBuffer.childNodes, tile;
for (var i=tiles.length-1; i>=0; --i) {
tile = tiles[i];
- tile.style.top = ((ratio * tile._i * tile._h) | 0) + 'px';
- tile.style.left = ((ratio * tile._j * tile._w) | 0) + 'px';
+ tile.style.top = ((ratio * tile._i * backBuffer._th) | 0) + 'px';
+ tile.style.left = ((ratio * tile._j * backBuffer._tw) | 0) + 'px';
tile.style.width = Math.round(ratio * tile._w) + 'px';
tile.style.height = Math.round(ratio * tile._h) + 'px';
}
// and position it (based on the grid's top-left corner)
@@ -34703,24 +34904,33 @@
if(this.grid.length > 0) {
backBuffer = document.createElement('div');
backBuffer.id = this.div.id + '_bb';
backBuffer.className = 'olBackBuffer';
backBuffer.style.position = 'absolute';
+ var map = this.map;
+ backBuffer.style.zIndex = this.transitionEffect === 'resize' ?
+ this.getZIndex() - 1 :
+ // 'map-resize':
+ map.Z_INDEX_BASE.BaseLayer -
+ (map.getNumLayers() - map.getLayerIndex(this));
for(var i=0, lenI=this.grid.length; i<lenI; i++) {
for(var j=0, lenJ=this.grid[i].length; j<lenJ; j++) {
var tile = this.grid[i][j],
markup = this.grid[i][j].createBackBuffer();
if (markup) {
markup._i = i;
markup._j = j;
- markup._w = tile.size.w;
+ markup._w = this.singleTile ?
+ this.getImageSize(tile.bounds).w : tile.size.w;
markup._h = tile.size.h;
markup.id = tile.id + '_bb';
backBuffer.appendChild(markup);
}
}
}
+ backBuffer._tw = this.tileSize.w;
+ backBuffer._th = this.tileSize.h;
}
return backBuffer;
},
/**
@@ -34734,11 +34944,13 @@
this.transitionendEvents[i], this._removeBackBuffer);
}
delete this._transitionElement;
}
if(this.backBuffer) {
- this.div.removeChild(this.backBuffer);
+ if (this.backBuffer.parentNode) {
+ this.backBuffer.parentNode.removeChild(this.backBuffer);
+ }
this.backBuffer = null;
this.backBufferResolution = null;
if(this.backBufferTimerId !== null) {
window.clearTimeout(this.backBufferTimerId);
this.backBufferTimerId = null;
@@ -34820,11 +35032,23 @@
var tileBounds =
new OpenLayers.Bounds(center.lon - (tileWidth/2),
center.lat - (tileHeight/2),
center.lon + (tileWidth/2),
center.lat + (tileHeight/2));
+
+ // store the resolution of the grid
+ this.gridResolution = this.getServerResolution();
+ // same logic as OpenLayers.Tile#shouldDraw
+ var maxExtent = this.maxExtent;
+ if (maxExtent && (!this.displayOutsideMaxExtent ||
+ (this.map.baseLayer.wrapDateLine &&
+ this.maxExtent.equals(this.map.getMaxExtent())))) {
+ tileBounds.left = Math.max(tileBounds.left, maxExtent.left);
+ tileBounds.right = Math.min(tileBounds.right, maxExtent.right);
+ }
+
var px = this.map.getLayerPxFromLonLat({
lon: tileBounds.left,
lat: tileBounds.top
});
@@ -34833,23 +35057,20 @@
}
var tile = this.grid[0][0];
if (!tile) {
tile = this.addTile(tileBounds, px);
-
+
this.addTileMonitoringHooks(tile);
tile.draw();
this.grid[0][0] = tile;
} else {
tile.moveTo(tileBounds, px);
}
//remove all but our single tile
this.removeExcessTiles(1,1);
-
- // store the resolution of the grid
- this.gridResolution = this.getServerResolution();
},
/**
* Method: calculateGridLayout
* Generate parameters for the grid layout.
@@ -34881,11 +35102,22 @@
tilelon: tilelon, tilelat: tilelat,
startcol: tilecol, startrow: tilerow
};
},
-
+
+ getImageSize: function(bounds) {
+ var tileSize = OpenLayers.Layer.HTTPRequest.prototype.getImageSize.apply(this, arguments);
+ if (this.singleTile) {
+ tileSize = new OpenLayers.Size(
+ Math.round(bounds.getWidth() / this.gridResolution),
+ tileSize.h
+ );
+ }
+ return tileSize;
+ },
+
/**
* Method: getTileOrigin
* Determine the origin for aligning the grid of tiles. If a <tileOrigin>
* property is supplied, that will be returned. Otherwise, the origin
* will be derived from the layer's <maxExtent> property. In this case,
@@ -35017,11 +35249,11 @@
rowidx += 1;
} while((tileBounds.bottom >= bounds.bottom - tilelat * this.buffer)
|| rowidx < minRows);
- //shave off exceess rows and colums
+ //shave off excess rows and columns
this.removeExcessTiles(rowidx, colidx);
var resolution = this.getServerResolution();
// store the resolution of the grid
this.gridResolution = resolution;
@@ -35044,11 +35276,11 @@
* {<OpenLayers.Bounds>}
*/
getMaxExtent: function() {
return this.maxExtent;
},
-
+
/**
* APIMethod: addTile
* Create a tile, initialize it, and add it to the layer div.
*
* Parameters
@@ -35085,11 +35317,11 @@
this.events.triggerEvent("loadstart");
}
this.events.triggerEvent("tileloadstart", {tile: tile});
this.numLoadingTiles++;
if (!this.singleTile && this.backBuffer && this.gridResolution === this.backBufferResolution) {
- OpenLayers.Element.addClass(tile.imgDiv, replacingCls);
+ OpenLayers.Element.addClass(tile.getTile(), replacingCls);
}
};
tile.onLoadEnd = function(evt) {
this.numLoadingTiles--;
@@ -35097,32 +35329,41 @@
this.events.triggerEvent("tileloaded", {
tile: tile,
aborted: aborted
});
if (!this.singleTile && !aborted && this.backBuffer && this.gridResolution === this.backBufferResolution) {
- if (OpenLayers.Element.getStyle(tile.imgDiv, 'display') === 'none') {
+ var tileDiv = tile.getTile();
+ if (OpenLayers.Element.getStyle(tileDiv, 'display') === 'none') {
var bufferTile = document.getElementById(tile.id + '_bb');
if (bufferTile) {
bufferTile.parentNode.removeChild(bufferTile);
}
}
- OpenLayers.Element.removeClass(tile.imgDiv, replacingCls);
+ OpenLayers.Element.removeClass(tileDiv, replacingCls);
}
//if that was the last tile, then trigger a 'loadend' on the layer
if (this.numLoadingTiles === 0) {
- if(this.backBuffer) {
- this._transitionElement = tile.imgDiv;
- for (var i=this.transitionendEvents.length-1; i>=0; --i) {
- OpenLayers.Event.observe(this._transitionElement,
- this.transitionendEvents[i],
- this._removeBackBuffer);
+ if (this.backBuffer) {
+ if (this.backBuffer.childNodes.length === 0) {
+ // no tiles transitioning, remove immediately
+ this.removeBackBuffer();
+ } else {
+ // wait until transition has ended or delay has passed
+ this._transitionElement = aborted ?
+ this.div.lastChild : tile.imgDiv;
+ var transitionendEvents = this.transitionendEvents;
+ for (var i=transitionendEvents.length-1; i>=0; --i) {
+ OpenLayers.Event.observe(this._transitionElement,
+ transitionendEvents[i],
+ this._removeBackBuffer);
+ }
+ // the removal of the back buffer is delayed to prevent
+ // flash effects due to the animation of tile displaying
+ this.backBufferTimerId = window.setTimeout(
+ this._removeBackBuffer, this.removeBackBufferDelay
+ );
}
- // the removal of the back buffer is delayed to prevent
- // flash effects due to the animation of tile displaying
- this.backBufferTimerId = window.setTimeout(
- this._removeBackBuffer, this.removeBackBufferDelay
- );
}
this.loading = false;
this.events.triggerEvent("loadend");
}
};
@@ -35321,11 +35562,11 @@
});
/* ======================================================================
OpenLayers/Format/ArcXML.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -36353,11 +36594,11 @@
});
/* ======================================================================
OpenLayers/Layer/ArcIMS.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -36782,11 +37023,11 @@
});
/* ======================================================================
OpenLayers/Control/PanZoom.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -36849,11 +37090,11 @@
/**
* APIMethod: destroy
*/
destroy: function() {
- if (this.map) {
+ if (this.map && !this.outsideViewport) {
this.map.events.unregister("buttonclick", this, this.onButtonClick);
}
this.removeButtons();
this.buttons = null;
this.position = null;
@@ -36866,11 +37107,18 @@
* Properties:
* map - {<OpenLayers.Map>}
*/
setMap: function(map) {
OpenLayers.Control.prototype.setMap.apply(this, arguments);
- this.map.events.register("buttonclick", this, this.onButtonClick);
+ var target;
+ if (this.outsideViewport) {
+ this.events.attachToElement(this.div);
+ target = this;
+ } else {
+ target = this.map;
+ }
+ target.events.register('buttonclick', this, this.onButtonClick);
},
/**
* Method: draw
*
@@ -37019,11 +37267,11 @@
OpenLayers.Control.PanZoom.Y = 4;
/* ======================================================================
OpenLayers/Control/PanZoomBar.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -37138,10 +37386,15 @@
* Parameters:
* map - {<OpenLayers.Map>}
*/
setMap: function(map) {
OpenLayers.Control.PanZoom.prototype.setMap.apply(this, arguments);
+
+ if (this.outsideViewport) {
+ this.events.attachToElement(this.div);
+ }
+
this.map.events.on({
"changebaselayer": this.redraw,
"updatesize": this.redraw,
scope: this
});
@@ -37337,16 +37590,18 @@
*/
zoomBarDown:function(evt) {
if (!OpenLayers.Event.isLeftClick(evt) && !OpenLayers.Event.isSingleTouch(evt)) {
return;
}
- this.map.events.on({
- "touchmove": this.passEventToSlider,
- "mousemove": this.passEventToSlider,
- "mouseup": this.passEventToSlider,
+ var target = this.outsideViewport ? this : this.map;
+ target.events.on({
+ touchmove: this.passEventToSlider,
+ mousemove: this.passEventToSlider,
+ mouseup: this.passEventToSlider,
scope: this
});
+
this.mouseDragStart = evt.xy.clone();
this.zoomStart = evt.xy.clone();
this.div.style.cursor = "move";
// reset the div offsets just in case the div moved
this.zoombarDiv.offsets = null;
@@ -37391,11 +37646,12 @@
if (!OpenLayers.Event.isLeftClick(evt) && evt.type !== "touchend") {
return;
}
if (this.mouseDragStart) {
this.div.style.cursor="";
- this.map.events.un({
+ var target = this.outsideViewport ? this : this.map;
+ target.events.un({
"touchmove": this.passEventToSlider,
"mouseup": this.passEventToSlider,
"mousemove": this.passEventToSlider,
scope: this
});
@@ -37431,11 +37687,11 @@
});
/* ======================================================================
OpenLayers/Format/WFSCapabilities/v1_1_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -37498,11 +37754,11 @@
});
/* ======================================================================
OpenLayers/Layer/Image.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -37761,11 +38017,11 @@
});
/* ======================================================================
OpenLayers/Strategy.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -37886,11 +38142,11 @@
});
/* ======================================================================
OpenLayers/Strategy/Save.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -38118,14 +38374,339 @@
},
CLASS_NAME: "OpenLayers.Strategy.Save"
});
/* ======================================================================
+ OpenLayers/Events/featureclick.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/Events.js
+ */
+
+/**
+ * Class: OpenLayers.Events.featureclick
+ *
+ * Extension event type for handling feature click events, including overlapping
+ * features.
+ *
+ * Event types provided by this extension:
+ * - featureclick
+ */
+OpenLayers.Events.featureclick = OpenLayers.Class({
+
+ /**
+ * Property: cache
+ * {Object} A cache of features under the mouse.
+ */
+ cache: null,
+
+ /**
+ * Property: map
+ * {<OpenLayers.Map>} The map to register browser events on.
+ */
+ map: null,
+
+ /**
+ * Property: provides
+ * {Array(String)} The event types provided by this extension.
+ */
+ provides: ["featureclick", "nofeatureclick", "featureover", "featureout"],
+
+ /**
+ * Constructor: OpenLayers.Events.featureclick
+ * Create a new featureclick event type.
+ *
+ * Parameters:
+ * target - {<OpenLayers.Events>} The events instance to create the events
+ * for.
+ */
+ initialize: function(target) {
+ this.target = target;
+ if (target.object instanceof OpenLayers.Map) {
+ this.setMap(target.object);
+ } else if (target.object instanceof OpenLayers.Layer.Vector) {
+ if (target.object.map) {
+ this.setMap(target.object.map);
+ } else {
+ target.object.events.register("added", this, function(evt) {
+ this.setMap(target.object.map);
+ });
+ }
+ } else {
+ throw("Listeners for '" + this.provides.join("', '") +
+ "' events can only be registered for OpenLayers.Layer.Vector " +
+ "or OpenLayers.Map instances");
+ }
+ for (var i=this.provides.length-1; i>=0; --i) {
+ target.extensions[this.provides[i]] = true;
+ }
+ },
+
+ /**
+ * Method: setMap
+ *
+ * Parameters:
+ * map - {<OpenLayers.Map>} The map to register browser events on.
+ */
+ setMap: function(map) {
+ this.map = map;
+ this.cache = {};
+ map.events.register("mousedown", this, this.start, {extension: true});
+ map.events.register("mouseup", this, this.onClick, {extension: true});
+ map.events.register("touchstart", this, this.start, {extension: true});
+ map.events.register("touchmove", this, this.cancel, {extension: true});
+ map.events.register("touchend", this, this.onClick, {extension: true});
+ map.events.register("mousemove", this, this.onMousemove, {extension: true});
+ },
+
+ /**
+ * Method: start
+ * Sets startEvt = evt.
+ *
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ */
+ start: function(evt) {
+ this.startEvt = evt;
+ },
+
+ /**
+ * Method: cancel
+ * Deletes the start event.
+ *
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ */
+ cancel: function(evt) {
+ delete this.startEvt;
+ },
+
+ /**
+ * Method: onClick
+ * Listener for the click event.
+ *
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ */
+ onClick: function(evt) {
+ if (!this.startEvt || evt.type !== "touchend" &&
+ !OpenLayers.Event.isLeftClick(evt)) {
+ return;
+ }
+ var features = this.getFeatures(this.startEvt);
+ delete this.startEvt;
+ // fire featureclick events
+ var feature, layer, more, clicked = {};
+ for (var i=0, len=features.length; i<len; ++i) {
+ feature = features[i];
+ layer = feature.layer;
+ clicked[layer.id] = true;
+ more = this.triggerEvent("featureclick", {feature: feature});
+ if (more === false) {
+ break;
+ }
+ }
+ // fire nofeatureclick events on all vector layers with no targets
+ for (i=0, len=this.map.layers.length; i<len; ++i) {
+ layer = this.map.layers[i];
+ if (layer instanceof OpenLayers.Layer.Vector && !clicked[layer.id]) {
+ this.triggerEvent("nofeatureclick", {layer: layer});
+ }
+ }
+ },
+
+ /**
+ * Method: onMousemove
+ * Listener for the mousemove event.
+ *
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ */
+ onMousemove: function(evt) {
+ delete this.startEvt;
+ var features = this.getFeatures(evt);
+ var over = {}, newly = [], feature;
+ for (var i=0, len=features.length; i<len; ++i) {
+ feature = features[i];
+ over[feature.id] = feature;
+ if (!this.cache[feature.id]) {
+ newly.push(feature);
+ }
+ }
+ // check if already over features
+ var out = [];
+ for (var id in this.cache) {
+ feature = this.cache[id];
+ if (feature.layer && feature.layer.map) {
+ if (!over[feature.id]) {
+ out.push(feature);
+ }
+ } else {
+ // removed
+ delete this.cache[id];
+ }
+ }
+ // fire featureover events
+ var more;
+ for (i=0, len=newly.length; i<len; ++i) {
+ feature = newly[i];
+ this.cache[feature.id] = feature;
+ more = this.triggerEvent("featureover", {feature: feature});
+ if (more === false) {
+ break;
+ }
+ }
+ // fire featureout events
+ for (i=0, len=out.length; i<len; ++i) {
+ feature = out[i];
+ delete this.cache[feature.id];
+ more = this.triggerEvent("featureout", {feature: feature});
+ if (more === false) {
+ break;
+ }
+ }
+ },
+
+ /**
+ * Method: triggerEvent
+ * Determines where to trigger the event and triggers it.
+ *
+ * Parameters:
+ * type - {String} The event type to trigger
+ * evt - {Object} The listener argument
+ *
+ * Returns:
+ * {Boolean} The last listener return.
+ */
+ triggerEvent: function(type, evt) {
+ var layer = evt.feature ? evt.feature.layer : evt.layer,
+ object = this.target.object;
+ if (object instanceof OpenLayers.Map || object === layer) {
+ return this.target.triggerEvent(type, evt);
+ }
+ },
+
+ /**
+ * Method: getFeatures
+ * Get all features at the given screen location.
+ *
+ * Parameters:
+ * evt - {Object} Event object.
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} List of features at the given point.
+ */
+ getFeatures: function(evt) {
+ var x = evt.clientX, y = evt.clientY,
+ features = [], targets = [], layers = [],
+ layer, target, feature, i, len;
+ // go through all layers looking for targets
+ for (i=this.map.layers.length-1; i>=0; --i) {
+ layer = this.map.layers[i];
+ if (layer.div.style.display !== "none") {
+ if (layer.renderer instanceof OpenLayers.Renderer.Elements) {
+ if (layer instanceof OpenLayers.Layer.Vector) {
+ target = document.elementFromPoint(x, y);
+ while (target && target._featureId) {
+ feature = layer.getFeatureById(target._featureId);
+ if (feature) {
+ features.push(feature);
+ target.style.display = "none";
+ targets.push(target);
+ target = document.elementFromPoint(x, y);
+ } else {
+ // sketch, all bets off
+ target = false;
+ }
+ }
+ }
+ layers.push(layer);
+ layer.div.style.display = "none";
+ } else if (layer.renderer instanceof OpenLayers.Renderer.Canvas) {
+ feature = layer.renderer.getFeatureIdFromEvent(evt);
+ if (feature) {
+ features.push(feature);
+ layers.push(layer);
+ }
+ }
+ }
+ }
+ // restore feature visibility
+ for (i=0, len=targets.length; i<len; ++i) {
+ targets[i].style.display = "";
+ }
+ // restore layer visibility
+ for (i=layers.length-1; i>=0; --i) {
+ layers[i].div.style.display = "block";
+ }
+ return features;
+ },
+
+ /**
+ * APIMethod: destroy
+ * Clean up.
+ */
+ destroy: function() {
+ for (var i=this.provides.length-1; i>=0; --i) {
+ delete this.target.extensions[this.provides[i]];
+ }
+ this.map.events.un({
+ mousemove: this.onMousemove,
+ mousedown: this.start,
+ mouseup: this.onClick,
+ touchstart: this.start,
+ touchmove: this.cancel,
+ touchend: this.onClick,
+ scope: this
+ });
+ delete this.cache;
+ delete this.map;
+ delete this.target;
+ }
+
+});
+
+/**
+ * Class: OpenLayers.Events.nofeatureclick
+ *
+ * Extension event type for handling click events that do not hit a feature.
+ *
+ * Event types provided by this extension:
+ * - nofeatureclick
+ */
+OpenLayers.Events.nofeatureclick = OpenLayers.Events.featureclick;
+
+/**
+ * Class: OpenLayers.Events.featureover
+ *
+ * Extension event type for handling hovering over a feature.
+ *
+ * Event types provided by this extension:
+ * - featureover
+ */
+OpenLayers.Events.featureover = OpenLayers.Events.featureclick;
+
+/**
+ * Class: OpenLayers.Events.featureout
+ *
+ * Extension event type for handling leaving a feature.
+ *
+ * Event types provided by this extension:
+ * - featureout
+ */
+OpenLayers.Events.featureout = OpenLayers.Events.featureclick;
+/* ======================================================================
OpenLayers/Format/GPX.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -38373,15 +38954,15 @@
* Returns:
* {DOMElement}
*/
buildMetadataNode: function(metadata) {
var types = ['name', 'desc', 'author'],
- node = this.createElementNSPlus('gpx:metadata');
+ node = this.createElementNS(this.namespaces.gpx, 'metadata');
for (var i=0; i < types.length; i++) {
var type = types[i];
if (metadata[type]) {
- var n = this.createElementNSPlus("gpx:" + type);
+ var n = this.createElementNS(this.namespaces.gpx, type);
n.appendChild(this.createTextNode(metadata[type]));
node.appendChild(n);
}
}
return node;
@@ -38407,11 +38988,11 @@
if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
var wpt = this.buildWptNode(geometry);
this.appendAttributesNode(wpt, feature);
return wpt;
} else {
- var trkNode = this.createElementNSPlus("gpx:trk");
+ var trkNode = this.createElementNS(this.namespaces.gpx, "trk");
this.appendAttributesNode(trkNode, feature);
var trkSegNodes = this.buildTrkSegNode(geometry);
trkSegNodes = OpenLayers.Util.isArray(trkSegNodes) ?
trkSegNodes : [trkSegNodes];
for (var i = 0, len = trkSegNodes.length; i < len; i++) {
@@ -38435,11 +39016,11 @@
len,
point,
nodes;
if (geometry.CLASS_NAME == "OpenLayers.Geometry.LineString" ||
geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
- node = this.createElementNSPlus("gpx:trkseg");
+ node = this.createElementNS(this.namespaces.gpx, "trkseg");
for (i = 0, len=geometry.components.length; i < len; i++) {
point = geometry.components[i];
node.appendChild(this.buildTrkPtNode(point));
}
return node;
@@ -38461,11 +39042,11 @@
*
* Returns:
* {DOMElement} A trkpt node
*/
buildTrkPtNode: function(point) {
- var node = this.createElementNSPlus("gpx:trkpt");
+ var node = this.createElementNS(this.namespaces.gpx, "trkpt");
node.setAttribute("lon", point.x);
node.setAttribute("lat", point.y);
return node;
},
@@ -38478,11 +39059,11 @@
*
* Returns:
* {DOMElement} A wpt node
*/
buildWptNode: function(geometry) {
- var node = this.createElementNSPlus("gpx:wpt");
+ var node = this.createElementNS(this.namespaces.gpx, "wpt");
node.setAttribute("lon", geometry.x);
node.setAttribute("lat", geometry.y);
return node;
},
@@ -38493,15 +39074,15 @@
* Parameters:
* node - {DOMElement} the node to append the attribute nodes to.
* feature - {<OpenLayers.Feature.Vector>}
*/
appendAttributesNode: function(node, feature) {
- var name = this.createElementNSPlus('gpx:name');
+ var name = this.createElementNS(this.namespaces.gpx, 'name');
name.appendChild(this.createTextNode(
feature.attributes.name || feature.id));
node.appendChild(name);
- var desc = this.createElementNSPlus('gpx:desc');
+ var desc = this.createElementNS(this.namespaces.gpx, 'desc');
desc.appendChild(this.createTextNode(
feature.attributes.description || this.defaultDesc));
node.appendChild(desc);
// TBD - deal with remaining (non name/description) attributes.
},
@@ -38510,11 +39091,11 @@
});
/* ======================================================================
OpenLayers/Format/WFSDescribeFeatureType.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -38748,11 +39329,11 @@
});
/* ======================================================================
OpenLayers/Renderer.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -39184,11 +39765,11 @@
};
/* ======================================================================
OpenLayers/Renderer/Canvas.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -39255,10 +39836,11 @@
initialize: function(containerID, options) {
OpenLayers.Renderer.prototype.initialize.apply(this, arguments);
this.root = document.createElement("canvas");
this.container.appendChild(this.root);
this.canvas = this.root.getContext("2d");
+ this._clearRectId = OpenLayers.Util.createUniqueID();
this.features = {};
if (this.hitDetection) {
this.hitCanvas = document.createElement("canvas");
this.hitContext = this.hitCanvas.getContext("2d");
}
@@ -39440,15 +40022,17 @@
height = height ? height : style.pointRadius * 2;
var xOffset = (style.graphicXOffset != undefined) ?
style.graphicXOffset : -(0.5 * width);
var yOffset = (style.graphicYOffset != undefined) ?
style.graphicYOffset : -(0.5 * height);
+ var _clearRectId = this._clearRectId;
var opacity = style.graphicOpacity || style.fillOpacity;
var onLoad = function() {
- if(!this.features[featureId]) {
+ if(!this.features[featureId] ||
+ _clearRectId !== this._clearRectId) {
return;
}
var pt = this.getLocalXY(geometry);
var p0 = pt[0];
var p1 = pt[1];
@@ -39471,13 +40055,16 @@
this.setHitContextStyle("fill", featureId);
this.hitContext.fillRect(x, y, width, height);
}
}
};
-
img.onload = OpenLayers.Function.bind(onLoad, this);
img.src = style.externalGraphic;
+ if (img.complete) {
+ img.onload();
+ img.onload = null;
+ }
},
/**
* Method: drawNamedSymbol
* Called to draw Well Known Graphic Symbol Name.
@@ -39898,10 +40485,11 @@
this.canvas.measureText('xx').width;
pt[1] += lineHeight*vfactor*(numRows-1);
for (var i = 0; i < numRows; i++) {
if (style.labelOutlineWidth) {
this.canvas.save();
+ this.canvas.globalAlpha = style.labelOutlineOpacity || style.fontOpacity || 1.0;
this.canvas.strokeStyle = style.labelOutlineColor;
this.canvas.lineWidth = style.labelOutlineWidth;
this.canvas.strokeText(labelRows[i], pt[0], pt[1] + (lineHeight*i) + 1);
this.canvas.restore();
}
@@ -39952,14 +40540,23 @@
/**
* Method: clear
* Clear all vectors from the renderer.
*/
clear: function() {
+ this.clearCanvas();
+ this.features = {};
+ },
+
+ /**
+ * Method: clearCanvas
+ * Clear the canvas element of the renderer.
+ */
+ clearCanvas: function() {
var height = this.root.height;
var width = this.root.width;
this.canvas.clearRect(0, 0, width, height);
- this.features = {};
+ this._clearRectId = OpenLayers.Util.createUniqueID();
if (this.hitDetection) {
this.hitContext.clearRect(0, 0, width, height);
}
},
@@ -40029,16 +40626,11 @@
* with things once they're drawn, to remove them, for example, so
* instead we have to just clear everything and draw from scratch.
*/
redraw: function() {
if (!this.locked) {
- var height = this.root.height;
- var width = this.root.width;
- this.canvas.clearRect(0, 0, width, height);
- if (this.hitDetection) {
- this.hitContext.clearRect(0, 0, width, height);
- }
+ this.clearCanvas();
var labelMap = [];
var feature, geometry, style;
var worldBounds = (this.map.baseLayer && this.map.baseLayer.wrapDateLine) && this.map.getMaxExtent();
for (var id in this.features) {
if (!this.features.hasOwnProperty(id)) { continue; }
@@ -40090,250 +40682,991 @@
* is always 1 except for Android 2.1 devices, to work around
* http://code.google.com/p/android/issues/detail?id=5141.
*/
OpenLayers.Renderer.Canvas.drawImageScaleFactor = null;
/* ======================================================================
- OpenLayers/Format/OSM.js
+ OpenLayers/Format/WCSDescribeCoverage.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/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSDescribeCoverage
+ * Parse results from WCS DescribeCoverage request.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WCSDescribeCoverage = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.1.0".
+ */
+ defaultVersion: "1.1.0",
+
+ /**
+ * Constructor: OpenLayers.Format.WCSDescribeCoverage
+ * Create a new parser for WCS DescribeCoverage response.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read response data from a string, and return a list of coverage descriptions.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of coverage descriptions.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.WCSDescribeCoverage"
+
+});
+/* ======================================================================
+ OpenLayers/Format/WCSDescribeCoverage/v1.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/Format/WCSDescribeCoverage.js
* @requires OpenLayers/Format/XML.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSDescribeCoverage.v1
+ * Abstract class not to be instantiated directly.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WCSDescribeCoverage.v1 = OpenLayers.Class(
+ OpenLayers.Format.XML, {
+
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ splitSpace: (/\s+/)
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "wcs",
+
+ /**
+ * APIMethod: read
+ *
+ * Parameters:
+ * data - {DOMElement|String} A WCS DescribeCoverage document.
+ *
+ * Returns:
+ * {Object} An object representing the WCS DescribeCoverage response.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var schema = {};
+ if (data.nodeName.split(":").pop() === 'ExceptionReport') {
+ // an exception must have occurred, so parse it
+ var parser = new OpenLayers.Format.OGCExceptionReport();
+ schema.error = parser.read(data);
+ } else {
+ this.readNode(data, schema);
+ }
+ return schema;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WCSDescribeCoverage.v1"
+
+});
+/* ======================================================================
+ OpenLayers/Format/WCSCapabilities.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/Format/XML/VersionedOGC.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSCapabilities
+ * Read WCS Capabilities.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML.VersionedOGC>
+ */
+OpenLayers.Format.WCSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
+
+ /**
+ * APIProperty: defaultVersion
+ * {String} Version number to assume if none found. Default is "1.1.0".
+ */
+ defaultVersion: "1.1.0",
+
+ /**
+ * Constructor: OpenLayers.Format.WCSCapabilities
+ * Create a new parser for WCS capabilities.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return a list of coverages.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of named coverages.
+ */
+
+ CLASS_NAME: "OpenLayers.Format.WCSCapabilities"
+
+});
+/* ======================================================================
+ OpenLayers/Format/WCSCapabilities/v1.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/Format/WCSCapabilities.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSCapabilities.v1
+ * Abstract class not to be instantiated directly.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WCSCapabilities.v1 = OpenLayers.Class(
+ OpenLayers.Format.XML, {
+
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ splitSpace: (/\s+/)
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "wcs",
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return a list of coverages.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of named coverages.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var raw = data;
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var capabilities = {};
+ this.readNode(data, capabilities);
+ return capabilities;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WCSCapabilities.v1"
+
+});
+/* ======================================================================
+ OpenLayers/Format/WCSCapabilities/v1_0_0.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/Format/WCSCapabilities/v1.js
+ * @requires OpenLayers/Format/GML/v3.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSCapabilities/v1_0_0
+ * Read WCS Capabilities version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WCSCapabilities.v1>
+ * - <OpenLayers.Format.GML.v3>
+ */
+OpenLayers.Format.WCSCapabilities.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.GML.v3, OpenLayers.Format.WCSCapabilities.v1, {
+
+ /**
+ * Constructor: OpenLayers.Format.WCSCapabilities.v1_0_0
+ * Create a new parser for WCS capabilities version 1.0.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ wcs: "http://www.opengis.net/wcs",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ ows: "http://www.opengis.net/ows"
+ },
+
+ /**
+ * Property: errorProperty
+ * {String} Which property of the returned object to check for in order to
+ * determine whether or not parsing has failed. In the case that the
+ * errorProperty is undefined on the returned object, the document will be
+ * run through an OGCExceptionReport parser.
+ */
+ errorProperty: "serviceIdentification",
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent. Where possible, the 1.0.0 readers attempt to make
+ * their output compatible with 1.1.0 to reduce client complexity.
+ */
+ readers: {
+ "wcs": {
+ "WCS_Capabilities": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Service": function(node, obj) {
+ var children = {};
+ this.readChildNodes(node, children);
+
+ // Rearrange things a little to get a tree that is
+ // compatible with 1.1.0
+ var providerName = children.serviceContact.providerName;
+ delete children.serviceContact.providerName;
+
+ obj.serviceProvider = {
+ providerName: providerName,
+ serviceContact: children.serviceContact };
+ children.serviceContact = undefined;
+ obj.serviceIdentification = children;
+ },
+ "keywords": function(node, serviceIdentification) {
+ serviceIdentification.keywords = [];
+ this.readChildNodes(node, serviceIdentification.keywords);
+ },
+ "keyword": function(node, keywords) {
+ // Append the keyword to the keywords list
+ keywords.push(this.getChildValue(node));
+ },
+ "responsibleParty": function(node, serviceIdentification) {
+ serviceIdentification.serviceContact = {};
+ this.readChildNodes(node, serviceIdentification.serviceContact);
+ },
+ "individualName": function(node, serviceContact) {
+ serviceContact.individualName = this.getChildValue(node);
+ },
+ "organisationName": function(node, serviceContact) {
+ serviceContact.providerName = this.getChildValue(node);
+ },
+ "positionName": function(node, serviceContact) {
+ serviceContact.positionName = this.getChildValue(node);
+ },
+ "contactInfo": function(node, serviceContact) {
+ serviceContact.contactInfo = {};
+ this.readChildNodes(node, serviceContact.contactInfo);
+ },
+ "phone": function(node, contactInfo) {
+ contactInfo.phone = {};
+ this.readChildNodes(node, contactInfo.phone);
+ },
+ "voice": function(node, phone) {
+ phone.voice = this.getChildValue(node);
+ },
+ "facsimile": function(node, phone) {
+ phone.facsimile = this.getChildValue(node);
+ },
+ "address": function(node, contactInfo) {
+ contactInfo.address = {};
+ this.readChildNodes(node, contactInfo.address);
+ },
+ "deliveryPoint": function(node, address) {
+ address.deliveryPoint = this.getChildValue(node);
+ },
+ "city": function(node, address) {
+ address.city = this.getChildValue(node);
+ },
+ "postalCode": function(node, address) {
+ address.postalCode = this.getChildValue(node);
+ },
+ "country": function(node, address) {
+ address.country = this.getChildValue(node);
+ },
+ "electronicMailAddress": function(node, address) {
+ address.electronicMailAddress = this.getChildValue(node);
+ },
+ "fees": function(node, serviceIdentification) {
+ serviceIdentification.fees = this.getChildValue(node);
+ },
+ "accessConstraints": function(node, serviceIdentification) {
+ serviceIdentification.accessConstraints = this.getChildValue(node);
+ },
+ "ContentMetadata": function(node, obj) {
+ obj.contentMetadata = [];
+ this.readChildNodes(node, obj.contentMetadata);
+ },
+ "CoverageOfferingBrief": function(node, contentMetadata) {
+ var coverageOfferingBrief = {};
+ this.readChildNodes(node, coverageOfferingBrief);
+ contentMetadata.push(coverageOfferingBrief);
+ },
+ "name": function(node, serviceOrCoverageOfferingBrief) {
+ // split/pop used to strip off any namespace prefixes
+ if(node.parentNode.nodeName.split(':').pop() === "Service") {
+ // We're parsing a service description
+ serviceOrCoverageOfferingBrief.title = this.getChildValue(node);
+ }
+ else { // node.parentNode.nodeName === "CoverageOfferingBrief"
+ // We're parsing a dataset
+ serviceOrCoverageOfferingBrief.identifier = this.getChildValue(node);
+ }
+ },
+ "label": function(node, serviceOrCoverageOfferingBrief) {
+ // split/pop used to strip off any namespace prefixes
+ if(node.parentNode.nodeName.split(':').pop() === "Service") {
+ // We're parsing a service description
+ serviceOrCoverageOfferingBrief['abstract'] = this.getChildValue(node);
+ }
+ else { // node.parentNode.nodeName === "CoverageOfferingBrief"
+ // We"re parsing a dataset
+ serviceOrCoverageOfferingBrief.title = this.getChildValue(node);
+ }
+ },
+ "lonLatEnvelope": function(node, coverageOfferingBrief) {
+ var nodeList = this.getElementsByTagNameNS(node, "http://www.opengis.net/gml", "pos");
+
+ // We expect two nodes here, to create the corners of a bounding box
+ if(nodeList.length == 2) {
+ var min = {};
+ var max = {};
+
+ this.xy = true; // Affirm we don't want our coordinates switched around
+ this.readers.gml.pos.apply(this, [nodeList[0], min]);
+ this.readers.gml.pos.apply(this, [nodeList[1], max]);
+
+ coverageOfferingBrief.lonLatEnvelope = {};
+ coverageOfferingBrief.lonLatEnvelope.srsName = node.getAttribute("srsName");
+ coverageOfferingBrief.lonLatEnvelope.min = min.points[0];
+ coverageOfferingBrief.lonLatEnvelope.max = max.points[0];
+ }
+ }
+ },
+ "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WCSCapabilities.v1_0_0"
+
+});
+/* ======================================================================
+ OpenLayers/Format/WCSDescribeCoverage/v1_0_0.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/Format/WCSDescribeCoverage/v1.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ * @requires OpenLayers/Format/GML/v3.js
+ * @requires OpenLayers/Format/WCSCapabilities/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WCSDescribeCoverage/v1_0_0
+ * Read WCS DescribeCoverage version 1.0.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WCSDescribeCoverage.v1>
+ */
+OpenLayers.Format.WCSDescribeCoverage.v1_0_0 = OpenLayers.Class(
+ OpenLayers.Format.WCSDescribeCoverage.v1, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ wcs: "http://www.opengis.net/wcs",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ ows: "http://www.opengis.net/ows",
+ gml: "http://www.opengis.net/gml"
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WCSDescribeCoverage.v1_0_0
+ * Create a new parser for WCS DescribeCoverage version 1.0.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wcs": {
+ // Root object, contains one or more CoverageDecription entries
+ // In 1.0.0, this is CoverageDescription, in 1.1.0,
+ // it will be CoverageDescriptions (plural)
+ "CoverageDescription": function(node, obj) {
+ obj.coverageDescriptions = {};
+ this.readChildNodes(node, obj.coverageDescriptions);
+
+ // Make a list of keys for easy access
+ obj.coverageDescriptionKeys = [];
+ for(var key in obj.coverageDescriptions) {
+ obj.coverageDescriptionKeys.push(key);
+ }
+ },
+ // In 1.1.0, this element is called CoverageDescription. We'll use
+ // that name because it's... better.
+ "CoverageOffering": function(node, descriptions) {
+ var description = {};
+ this.readChildNodes(node, description);
+ descriptions[description.identifier] = description;
+
+ // Provide a consistent handle on the native CRS
+ description.nativeCRS = description.supportedCRSs.nativeCRSs[0];
+ },
+ // As with GetCapabilities, we'll use the 1.1.0 element name
+ // (identifier) because it is less ambiguous
+ "name": function(node, description) {
+ description.identifier = this.getChildValue(node);
+ },
+ // As with GetCapabilities, we'll use the 1.1.0 element name
+ // (title) because it is less ambiguous
+ "label": function(node, description) {
+ description.title = this.getChildValue(node);
+ },
+ // This format is the same as that used by GetCapabilities 1.0.0,
+ // so we can reuse that reader
+ "lonLatEnvelope": function(node, description) {
+ OpenLayers.Format.WCSCapabilities.v1_0_0.prototype.readers.wcs.lonLatEnvelope.call(this, node, description);
+ },
+ // Essentially the same as domain in 1.1.0
+ "domainSet": function(node, description) {
+ description.domain = {};
+ this.readChildNodes(node, description.domain);
+ },
+ "spatialDomain": function(node, domain) {
+ domain.spatialDomain = { boundingBoxes: {} };
+ this.readChildNodes(node, domain.spatialDomain);
+ },
+ "nativeCRSs": function(node, description) {
+ if(!description.nativeCRSs) {
+ description.nativeCRSs = [];
+ }
+ var crs = this.getChildValue(node);
+ description.nativeCRSs.push(crs);
+ },
+ "supportedCRSs": function(node, description) {
+ if(!description.supportedCRSs) {
+ description.supportedCRSs = [];
+ }
+ this.readChildNodes(node, description.supportedCRSs)
+ },
+ // There will be several of these within the supportedCRSs tag
+ "requestResponseCRSs" : function(node, supportedCRSs) {
+ supportedCRSs.push(this.getChildValue(node));
+ },
+ "supportedFormats": function(node, description) {
+ if(!description.supportedFormats) {
+ description.supportedFormats = [];
+ }
+ this.readChildNodes(node, description.supportedFormats)
+ },
+ // There will be several of these within the supportedFormats tag
+ "formats" : function(node, supportedFormats) {
+ supportedFormats.push(this.getChildValue(node));
+ }
+ },
+
+ "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"],
+ "gml": OpenLayers.Util.applyDefaults({
+ // Use custom Envelope reader that understands the srsName attribute
+ "Envelope": function(node, spatialDomain) {
+ var srsName = node.getAttribute("srsName");
+ if(!srsName) { // No SRS? What does this envelope mean?!?
+ return;
+ }
+
+ var obj = {points: []};
+ this.readChildNodes(node, obj);
+
+ var min = obj.points[0];
+ var max = obj.points[1];
+ var bounds = new OpenLayers.Bounds(min.x, min.y, max.x, max.y);
+ spatialDomain.boundingBoxes[srsName] = bounds;
+ }
+ }, OpenLayers.Format.GML.v3.prototype.readers["gml"])
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WCSDescribeCoverage.v1_0_0"
+
+});
+/* ======================================================================
+ OpenLayers/Format/OSM.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/Format/XML.js
* @requires OpenLayers/Feature/Vector.js
* @requires OpenLayers/Geometry/Point.js
* @requires OpenLayers/Geometry/LineString.js
* @requires OpenLayers/Geometry/Polygon.js
* @requires OpenLayers/Projection.js
*/
-/**
+/**
* Class: OpenLayers.Format.OSM
- * OSM parser. Create a new instance with the
+ * OSM parser. Create a new instance with the
* <OpenLayers.Format.OSM> constructor.
*
* Inherits from:
* - <OpenLayers.Format.XML>
*/
OpenLayers.Format.OSM = OpenLayers.Class(OpenLayers.Format.XML, {
-
+
/**
* APIProperty: checkTags
* {Boolean} Should tags be checked to determine whether something
* should be treated as a seperate node. Will slow down parsing.
* Default is false.
*/
checkTags: false,
/**
+ * APIProperty: shareNode
+ * {Boolean} Should nodes be shared between geometries.
+ */
+ shareNode: false,
+
+ /**
* Property: interestingTagsExclude
* {Array} List of tags to exclude from 'interesting' checks on nodes.
* Must be set when creating the format. Will only be used if checkTags
* is set.
*/
- interestingTagsExclude: null,
-
+ interestingTagsExclude: null,
+
/**
* APIProperty: areaTags
- * {Array} List of tags indicating that something is an area.
- * Must be set when creating the format. Will only be used if
+ * {Array} List of tags indicating that something is an area.
+ * Must be set when creating the format. Will only be used if
* checkTags is true.
*/
- areaTags: null,
-
+ areaTags: null,
+
/**
+ * APIProperty: relationsParsers
+ * {Map({String, Function})} Map relation type to a functions that parce the relation.
+ * This can be set for example to:
+ * {
+ * multipolygon: OpenLayers.Format.OSM.multipolygonParser,
+ * boundary: OpenLayers.Format.OSM.multipolygonParser,
+ * route: OpenLayers.Format.OSM.routeParser
+ * }
+ */
+ relationsParsers: {},
+
+ /**
* Constructor: OpenLayers.Format.OSM
* Create a new parser for OSM.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*/
initialize: function(options) {
var layer_defaults = {
- 'interestingTagsExclude': ['source', 'source_ref',
+ 'interestingTagsExclude': ['source', 'source_ref',
'source:ref', 'history', 'attribution', 'created_by'],
'areaTags': ['area', 'building', 'leisure', 'tourism', 'ruins',
- 'historic', 'landuse', 'military', 'natural', 'sport']
+ 'historic', 'landuse', 'military', 'natural', 'sport']
};
-
+ options = options ? options : {};
+
layer_defaults = OpenLayers.Util.extend(layer_defaults, options);
-
+
var interesting = {};
for (var i = 0; i < layer_defaults.interestingTagsExclude.length; i++) {
interesting[layer_defaults.interestingTagsExclude[i]] = true;
}
layer_defaults.interestingTagsExclude = interesting;
-
+
var area = {};
for (var i = 0; i < layer_defaults.areaTags.length; i++) {
area[layer_defaults.areaTags[i]] = true;
}
layer_defaults.areaTags = area;
// OSM coordinates are always in longlat WGS84
this.externalProjection = new OpenLayers.Projection("EPSG:4326");
-
+
OpenLayers.Format.XML.prototype.initialize.apply(this, [layer_defaults]);
},
-
+
/**
* APIMethod: read
* Return a list of features from a OSM doc
-
+
* Parameters:
* doc - {Element}
*
* Returns:
* Array({<OpenLayers.Feature.Vector>})
*/
read: function(doc) {
- if (typeof doc == "string") {
+ if (typeof doc == "string") {
doc = OpenLayers.Format.XML.prototype.read.apply(this, [doc]);
}
var nodes = this.getNodes(doc);
var ways = this.getWays(doc);
-
+ var relations = this.getRelations(doc);
+
// Geoms will contain at least ways.length entries.
- var feat_list = new Array(ways.length);
-
- for (var i = 0; i < ways.length; i++) {
- // We know the minimal of this one ahead of time. (Could be -1
- // due to areas/polygons)
- var point_list = new Array(ways[i].nodes.length);
-
- var poly = this.isWayArea(ways[i]) ? 1 : 0;
- for (var j = 0; j < ways[i].nodes.length; j++) {
- var node = nodes[ways[i].nodes[j]];
-
- var point = new OpenLayers.Geometry.Point(node.lon, node.lat);
-
- // Since OSM is topological, we stash the node ID internally.
- point.osm_id = parseInt(ways[i].nodes[j]);
- point_list[j] = point;
-
- // We don't display nodes if they're used inside other
- // elements.
- node.used = true;
+ var feat_list = [];
+
+ for (var relation_id in relations) {
+ var relation = relations[relation_id];
+ if (this.relationsParsers[relation.tags.type]) {
+ var features = this.relationsParsers[relation.tags.type](relation, this, nodes, ways, relations);
+ for (var i = 0, len = features.length ; i < len ; i++) {
+ feat_list.push(features[i]);
+ }
}
- var geometry = null;
- if (poly) {
- geometry = new OpenLayers.Geometry.Polygon(
- new OpenLayers.Geometry.LinearRing(point_list));
- } else {
- geometry = new OpenLayers.Geometry.LineString(point_list);
+ }
+
+ for (var way_id in ways) {
+ var way = ways[way_id];
+
+ if (way.interesting) {
+ var poly = this.isWayArea(way) ? 1 : 0;
+ var point_list = this.getPointList(way, nodes);
+ var geometry = null;
+ if (poly) {
+ geometry = new OpenLayers.Geometry.Polygon(
+ new OpenLayers.Geometry.LinearRing(point_list));
+ }
+ else {
+ geometry = new OpenLayers.Geometry.LineString(point_list);
+ }
+ var feat = new OpenLayers.Feature.Vector(geometry,
+ way.tags);
+ feat.osm_id = parseInt(way.id);
+ feat.osm_version = parseInt(way.version);
+ // Since OSM is topological, we stash the node ID internally.
+ feat.geometry.osm_id = feat.osm_id;
+ feat.type = "way";
+ feat.fid = "way." + feat.osm_id;
+ feat_list.push(feat);
}
- if (this.internalProjection && this.externalProjection) {
- geometry.transform(this.externalProjection,
- this.internalProjection);
- }
- var feat = new OpenLayers.Feature.Vector(geometry,
- ways[i].tags);
- feat.osm_id = parseInt(ways[i].id);
- feat.fid = "way." + feat.osm_id;
- feat_list[i] = feat;
- }
+ }
for (var node_id in nodes) {
var node = nodes[node_id];
- if (!node.used || this.checkTags) {
- var tags = null;
-
- if (this.checkTags) {
- var result = this.getTags(node.node, true);
- if (node.used && !result[1]) {
- continue;
- }
- tags = result[0];
- } else {
- tags = this.getTags(node.node);
- }
-
- var feat = new OpenLayers.Feature.Vector(
- new OpenLayers.Geometry.Point(node['lon'], node['lat']),
- tags);
- if (this.internalProjection && this.externalProjection) {
- feat.geometry.transform(this.externalProjection,
- this.internalProjection);
- }
- feat.osm_id = parseInt(node_id);
- feat.fid = "node." + feat.osm_id;
- feat_list.push(feat);
- }
- // Memory cleanup
- node.node = null;
- }
+ if (!node.used || !this.checkTags || Object.keys(node.attributes).length > 1) {
+ feat_list.push(node);
+ }
+ }
return feat_list;
},
/**
- * Method: getNodes
- * Return the node items from a doc.
+ * Method: getPointList
+ * Return a list of points corresponds with with the way.
*
* Parameters:
+ * way - way where we can find the nodes id.
+ * nodes - nodes the nodes map where we can find the nodes by id.
+ */
+ getPointList: function(way, nodes) {
+ if (!way) {
+ // the way will not be on the bbox
+ return [];
+ }
+ // We know the minimal of this one ahead of time. (Could be -1
+ // due to areas/polygons)
+ var point_list = new Array(way.nodes.length);
+ for (var j = 0; j < way.nodes.length; j++) {
+ var node = nodes[way.nodes[j]];
+ node.used = true;
+
+ var point = node.geometry;
+ if (!this.shareNode) {
+ point = new OpenLayers.Geometry.Point(node.geometry.x, node.geometry.y);
+ // Since OSM is topological, we stash the node ID internally.
+ point.osm_id = node.osm_id;
+ }
+
+ point_list[j] = point;
+ }
+ return point_list;
+ },
+
+ /**
+ * Method: concatPathsIfLinear
+ * Return result.succed if pass are linear, result.lastPointList with the new way.
+ *
+ * Parameters:
+ * lastPointList - array of <OpenLayer.Geometry.Points>, the old concanated path
+ * pointList - array of <OpenLayer.Geometry.Points>, the new path
+ */
+ concatPathsIfLinear: function(lastPointList, pointList) {
+ var result = {};
+ if (lastPointList.length == 0) {
+ result.succed = true;
+ result.lastPointList = pointList;
+ return result;
+ }
+ if (pointList.length == 0) {
+ result.succed = true;
+ result.lastPointList = lastPointList;
+ return result;
+ }
+ if (lastPointList[lastPointList.length-1].x == pointList[0].x
+ && lastPointList[lastPointList.length-1].y == pointList[0].y) {
+ pointList = pointList.slice(1, pointList.length);
+ lastPointList = lastPointList.concat(pointList);
+ result.succed = true;
+ result.lastPointList = lastPointList;
+ return result;
+ }
+ else if (lastPointList[0].x == pointList[pointList.length-1].x
+ && lastPointList[0].y == pointList[pointList.length-1].y) {
+ lastPointList = lastPointList.slice(1, lastPointList.length);
+ lastPointList = pointList.concat(lastPointList);
+ result.succed = true;
+ result.lastPointList = lastPointList;
+ return result;
+ }
+ else if (lastPointList[0].x == pointList[0].x
+ && lastPointList[0].y == pointList[0].y) {
+ if (lastPointList.length > pointList.length) {
+ pointList = pointList.slice(1, pointList.length);
+ lastPointList = pointList.reverse().concat(lastPointList);
+ }
+ else {
+ lastPointList = lastPointList.slice(1, lastPointList.length);
+ lastPointList = lastPointList.reverse().concat(pointList);
+ }
+ result.succed = true;
+ result.lastPointList = lastPointList;
+ return result;
+ }
+ else if (lastPointList[lastPointList.length-1].x == pointList[pointList.length-1].x
+ && lastPointList[lastPointList.length-1].y == pointList[pointList.length-1].y) {
+ if (lastPointList.length > pointList.length) {
+ pointList = pointList.slice(0, pointList.length - 1);
+ lastPointList = lastPointList.concat(pointList.reverse());
+ }
+ else {
+ lastPointList = lastPointList.slice(0, lastPointList.length - 1);
+ lastPointList = pointList.concat(lastPointList.reverse());
+ }
+ result.succed = true;
+ result.lastPointList = lastPointList;
+ return result;
+ }
+ result.succed = false;
+ return result;
+ },
+
+ /**
+ * Method: gets
+ * Return the node items from a doc.
+ *
+ * Parameters:
* doc - {DOMElement} node to parse tags from
*/
getNodes: function(doc) {
var node_list = doc.getElementsByTagName("node");
var nodes = {};
for (var i = 0; i < node_list.length; i++) {
var node = node_list[i];
var id = node.getAttribute("id");
- nodes[id] = {
- 'lat': node.getAttribute("lat"),
- 'lon': node.getAttribute("lon"),
- 'node': node
- };
+ var geom = new OpenLayers.Geometry.Point(
+ node.getAttribute("lon"),
+ node.getAttribute("lat"))
+ if (this.internalProjection && this.externalProjection) {
+ geom.transform(this.externalProjection,
+ this.internalProjection);
+ }
+ var feat = new OpenLayers.Feature.Vector(geom, this.getTags(node));
+ feat.osm_id = parseInt(id);
+ feat.osm_version = parseInt(node.getAttribute("version"));
+ feat.type = "node";
+ feat.fid = "node." + feat.osm_id;
+
+ // Since OSM is topological, we stash the node ID internally.
+ feat.geometry.osm_id = feat.osm_id;
+
+ nodes[id] = feat;
}
return nodes;
},
/**
+ * Method: getRelations
+ * Return the relation items from a doc.
+ *
+ * Parameters:
+ * node - {DOMElement} node to parse tags from
+ */
+ getRelations: function(doc) {
+ var relation_list = doc.getElementsByTagName("relation");
+ var return_relations = {};
+ for (var i = 0; i < relation_list.length; i++) {
+ var relation = relation_list[i];
+ var id = relation.getAttribute("id");
+ var relation_object = {
+ id: id,
+ version: relation.getAttribute("version")
+ };
+
+ relation_object.tags = this.getTags(relation);
+ relation_object.nodes = [];
+ relation_object.ways = [];
+ relation_object.relations = [];
+
+ var member_list = relation.getElementsByTagName("member");
+
+ for (var j = 0; j < member_list.length; j++) {
+ var member = member_list[j];
+ var type = member.getAttribute("type");
+ if (type == 'node') {
+ relation_object.nodes[relation_object.nodes.length] = member;
+ }
+ else if (type == 'way') {
+ relation_object.ways[relation_object.ways.length] = member;
+ }
+ else if (type == 'relation') {
+ relation_object.relations[relation_object.relations.length] = member;
+ }
+ }
+ return_relations[id] = relation_object;
+ }
+ return return_relations;
+
+ },
+
+ /**
* Method: getWays
- * Return the way items from a doc.
+ * Return the way items from a doc.
*
* Parameters:
* doc - {DOMElement} node to parse tags from
*/
getWays: function(doc) {
var way_list = doc.getElementsByTagName("way");
- var return_ways = [];
+ var return_ways = {};
for (var i = 0; i < way_list.length; i++) {
var way = way_list[i];
+ var id = way.getAttribute("id");
var way_object = {
- id: way.getAttribute("id")
+ id: id,
+ version: way.getAttribute("version")
};
-
- way_object.tags = this.getTags(way);
-
+
+ if (this.checkTags) {
+ var result = this.getTags(way, true);
+ way_object.interesting = result[1];
+ way_object.tags = result[0];
+ } else {
+ way_object.interesting = true;
+ way_object.tags = this.getTags(way);
+ }
+
var node_list = way.getElementsByTagName("nd");
-
+
way_object.nodes = new Array(node_list.length);
-
+
for (var j = 0; j < node_list.length; j++) {
way_object.nodes[j] = node_list[j].getAttribute("ref");
- }
- return_ways.push(way_object);
+ }
+ return_ways[id] = way_object;
}
- return return_ways;
-
- },
-
+ return return_ways;
+
+ },
+
/**
* Method: getTags
* Return the tags list attached to a specific DOM element.
*
* Parameters:
* dom_node - {DOMElement} node to parse tags from
* interesting_tags - {Boolean} whether the return from this function should
- * return a boolean indicating that it has 'interesting tags' --
+ * return a boolean indicating that it has 'interesting tags' --
* tags like attribution and source are ignored. (To change the list
* of tags, see interestingTagsExclude)
- *
+ *
* Returns:
* tags - {Object} hash of tags
* interesting - {Boolean} if interesting_tags is passed, returns
* whether there are any interesting tags on this element.
*/
@@ -40341,72 +41674,72 @@
var tag_list = dom_node.getElementsByTagName("tag");
var tags = {};
var interesting = false;
for (var j = 0; j < tag_list.length; j++) {
var key = tag_list[j].getAttribute("k");
- tags[key] = tag_list[j].getAttribute("v");
- if (interesting_tags) {
- if (!this.interestingTagsExclude[key]) {
- interesting = true;
- }
- }
- }
- return interesting_tags ? [tags, interesting] : tags;
+ if (!this.checkTags || !this.interestingTagsExclude[key]) {
+ tags[key] = tag_list[j].getAttribute("v");
+ }
+ if (interesting_tags && !this.interestingTagsExclude[key]) {
+ interesting = true;
+ }
+ }
+ return interesting_tags ? [tags, interesting] : tags;
},
- /**
+ /**
* Method: isWayArea
* Given a way object from getWays, check whether the tags and geometry
* indicate something is an area.
*
* Returns:
* {Boolean}
*/
- isWayArea: function(way) {
+ isWayArea: function(way) {
var poly_shaped = false;
var poly_tags = false;
-
+
if (way.nodes[0] == way.nodes[way.nodes.length - 1]) {
poly_shaped = true;
}
if (this.checkTags) {
for(var key in way.tags) {
if (this.areaTags[key]) {
poly_tags = true;
break;
}
}
- }
- return poly_shaped && (this.checkTags ? poly_tags : true);
- },
+ }
+ return poly_shaped && (this.checkTags ? poly_tags : true);
+ },
/**
- * APIMethod: write
+ * APIMethod: write
* Takes a list of features, returns a serialized OSM format file for use
* in tools like JOSM.
*
* Parameters:
* features - {Array(<OpenLayers.Feature.Vector>)}
*/
- write: function(features) {
+ write: function(features) {
if (!(OpenLayers.Util.isArray(features))) {
features = [features];
}
-
+
this.osm_id = 1;
this.created_nodes = {};
var root_node = this.createElementNS(null, "osm");
root_node.setAttribute("version", "0.5");
root_node.setAttribute("generator", "OpenLayers "+ OpenLayers.VERSION_NUMBER);
- // Loop backwards, because the deserializer puts nodes last, and
+ // Loop backwards, because the deserializer puts nodes last, and
// we want them first if possible
for(var i = features.length - 1; i >= 0; i--) {
var nodes = this.createFeatureNodes(features[i]);
for (var j = 0; j < nodes.length; j++) {
root_node.appendChild(nodes[j]);
- }
+ }
}
return OpenLayers.Format.XML.prototype.write.apply(this, [root_node]);
},
/**
@@ -40428,11 +41761,11 @@
if (builder) {
nodes = builder.apply(this, [feature]);
}
return nodes;
},
-
+
/**
* Method: createXML
* Takes a feature, returns a list of nodes from size 0->n.
* Will include all pieces of the serialization that are required which
* have not already been created.
@@ -40442,52 +41775,52 @@
*/
createXML: {
'point': function(point) {
var id = null;
var geometry = point.geometry ? point.geometry : point;
-
+
if (this.internalProjection && this.externalProjection) {
geometry = geometry.clone();
- geometry.transform(this.internalProjection,
+ geometry.transform(this.internalProjection,
this.externalProjection);
- }
-
+ }
+
var already_exists = false; // We don't return anything if the node
// has already been created
if (point.osm_id) {
id = point.osm_id;
if (this.created_nodes[id]) {
already_exists = true;
- }
+ }
} else {
id = -this.osm_id;
- this.osm_id++;
+ this.osm_id++;
}
if (already_exists) {
node = this.created_nodes[id];
- } else {
+ } else {
var node = this.createElementNS(null, "node");
}
this.created_nodes[id] = node;
node.setAttribute("id", id);
- node.setAttribute("lon", geometry.x);
+ node.setAttribute("lon", geometry.x);
node.setAttribute("lat", geometry.y);
if (point.attributes) {
this.serializeTags(point, node);
}
this.setState(point, node);
return already_exists ? [] : [node];
- },
+ },
linestring: function(feature) {
var id;
var nodes = [];
var geometry = feature.geometry;
if (feature.osm_id) {
id = feature.osm_id;
} else {
id = -this.osm_id;
- this.osm_id++;
+ this.osm_id++;
}
var way = this.createElementNS(null, "way");
way.setAttribute("id", id);
for (var i = 0; i < geometry.components.length; i++) {
var node = this.createXML['point'].apply(this, [geometry.components[i]]);
@@ -40504,17 +41837,19 @@
nd_dom.setAttribute("ref", node_ref);
way.appendChild(nd_dom);
}
this.serializeTags(feature, way);
nodes.push(way);
-
+
return nodes;
},
polygon: function(feature) {
var attrs = OpenLayers.Util.extend({'area':'yes'}, feature.attributes);
- var feat = new OpenLayers.Feature.Vector(feature.geometry.components[0], attrs);
+ var feat = new OpenLayers.Feature.Vector(feature.geometry.components[0], attrs);
feat.osm_id = feature.osm_id;
+ // Since OSM is topological, we stash the node ID internally.
+ feat.geometry.osm_id = feat.osm_id;
return this.createXML['linestring'].apply(this, [feat]);
}
},
/**
@@ -40533,11 +41868,11 @@
node.appendChild(tag);
}
},
/**
- * Method: setState
+ * Method: setState
* OpenStreetMap has a convention that 'state' is stored for modification or deletion.
* This allows the file to be uploaded via JOSM or the bulk uploader tool.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
@@ -40553,2822 +41888,258 @@
state = "delete";
}
if (state) {
node.setAttribute("action", state);
}
- }
- },
-
- CLASS_NAME: "OpenLayers.Format.OSM"
-});
-/* ======================================================================
- OpenLayers/Handler/Feature.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/Handler.js
- */
-
-/**
- * Class: OpenLayers.Handler.Feature
- * Handler to respond to mouse events related to a drawn feature. Callbacks
- * with the following keys will be notified of the following events
- * associated with features: click, clickout, over, out, and dblclick.
- *
- * This handler stops event propagation for mousedown and mouseup if those
- * browser events target features that can be selected.
- *
- * Inherits from:
- * - <OpenLayers.Handler>
- */
-OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
-
- /**
- * Property: EVENTMAP
- * {Object} A object mapping the browser events to objects with callback
- * keys for in and out.
- */
- EVENTMAP: {
- 'click': {'in': 'click', 'out': 'clickout'},
- 'mousemove': {'in': 'over', 'out': 'out'},
- 'dblclick': {'in': 'dblclick', 'out': null},
- 'mousedown': {'in': null, 'out': null},
- 'mouseup': {'in': null, 'out': null},
- 'touchstart': {'in': 'click', 'out': 'clickout'}
- },
-
- /**
- * Property: feature
- * {<OpenLayers.Feature.Vector>} The last feature that was hovered.
- */
- feature: null,
-
- /**
- * Property: lastFeature
- * {<OpenLayers.Feature.Vector>} The last feature that was handled.
- */
- lastFeature: null,
-
- /**
- * Property: down
- * {<OpenLayers.Pixel>} The location of the last mousedown.
- */
- down: null,
-
- /**
- * Property: up
- * {<OpenLayers.Pixel>} The location of the last mouseup.
- */
- up: null,
-
- /**
- * Property: touch
- * {Boolean} When a touchstart event is fired, touch will be true and all
- * mouse related listeners will do nothing.
- */
- touch: false,
-
- /**
- * Property: clickTolerance
- * {Number} The number of pixels the mouse can move between mousedown
- * and mouseup for the event to still be considered a click.
- * Dragging the map should not trigger the click and clickout callbacks
- * unless the map is moved by less than this tolerance. Defaults to 4.
- */
- clickTolerance: 4,
-
- /**
- * Property: geometryTypes
- * To restrict dragging to a limited set of geometry types, send a list
- * of strings corresponding to the geometry class names.
- *
- * @type Array(String)
- */
- geometryTypes: null,
-
- /**
- * Property: stopClick
- * {Boolean} If stopClick is set to true, handled clicks do not
- * propagate to other click listeners. Otherwise, handled clicks
- * do propagate. Unhandled clicks always propagate, whatever the
- * value of stopClick. Defaults to true.
- */
- stopClick: true,
-
- /**
- * Property: stopDown
- * {Boolean} If stopDown is set to true, handled mousedowns do not
- * propagate to other mousedown listeners. Otherwise, handled
- * mousedowns do propagate. Unhandled mousedowns always propagate,
- * whatever the value of stopDown. Defaults to true.
- */
- stopDown: true,
-
- /**
- * Property: stopUp
- * {Boolean} If stopUp is set to true, handled mouseups do not
- * propagate to other mouseup listeners. Otherwise, handled mouseups
- * do propagate. Unhandled mouseups always propagate, whatever the
- * value of stopUp. Defaults to false.
- */
- stopUp: false,
-
- /**
- * Constructor: OpenLayers.Handler.Feature
- *
- * Parameters:
- * control - {<OpenLayers.Control>}
- * layer - {<OpenLayers.Layer.Vector>}
- * callbacks - {Object} An object with a 'over' property whos value is
- * a function to be called when the mouse is over a feature. The
- * callback should expect to recieve a single argument, the feature.
- * options - {Object}
- */
- initialize: function(control, layer, callbacks, options) {
- OpenLayers.Handler.prototype.initialize.apply(this, [control, callbacks, options]);
- this.layer = layer;
- },
-
- /**
- * Method: touchstart
- * Handle touchstart events
- *
- * Parameters:
- * evt - {Event}
- *
- * Returns:
- * {Boolean} Let the event propagate.
- */
- touchstart: function(evt) {
- if(!this.touch) {
- this.touch = true;
- this.map.events.un({
- mousedown: this.mousedown,
- mouseup: this.mouseup,
- mousemove: this.mousemove,
- click: this.click,
- dblclick: this.dblclick,
- scope: this
- });
}
- return OpenLayers.Event.isMultiTouch(evt) ?
- true : this.mousedown(evt);
},
- /**
- * Method: touchmove
- * Handle touchmove events. We just prevent the browser default behavior,
- * for Android Webkit not to select text when moving the finger after
- * selecting a feature.
- *
- * Parameters:
- * evt - {Event}
- */
- touchmove: function(evt) {
- OpenLayers.Event.stop(evt);
- },
-
- /**
- * Method: mousedown
- * Handle mouse down. Stop propagation if a feature is targeted by this
- * event (stops map dragging during feature selection).
- *
- * Parameters:
- * evt - {Event}
- */
- mousedown: function(evt) {
- // Feature selection is only done with a left click. Other handlers may stop the
- // propagation of left-click mousedown events but not right-click mousedown events.
- // This mismatch causes problems when comparing the location of the down and up
- // events in the click function so it is important ignore right-clicks.
- if (OpenLayers.Event.isLeftClick(evt) || OpenLayers.Event.isSingleTouch(evt)) {
- this.down = evt.xy;
- }
- return this.handle(evt) ? !this.stopDown : true;
- },
-
- /**
- * Method: mouseup
- * Handle mouse up. Stop propagation if a feature is targeted by this
- * event.
- *
- * Parameters:
- * evt - {Event}
- */
- mouseup: function(evt) {
- this.up = evt.xy;
- return this.handle(evt) ? !this.stopUp : true;
- },
-
- /**
- * Method: click
- * Handle click. Call the "click" callback if click on a feature,
- * or the "clickout" callback if click outside any feature.
- *
- * Parameters:
- * evt - {Event}
- *
- * Returns:
- * {Boolean}
- */
- click: function(evt) {
- return this.handle(evt) ? !this.stopClick : true;
- },
-
- /**
- * Method: mousemove
- * Handle mouse moves. Call the "over" callback if moving in to a feature,
- * or the "out" callback if moving out of a feature.
- *
- * Parameters:
- * evt - {Event}
- *
- * Returns:
- * {Boolean}
- */
- mousemove: function(evt) {
- if (!this.callbacks['over'] && !this.callbacks['out']) {
- return true;
- }
- this.handle(evt);
- return true;
- },
-
- /**
- * Method: dblclick
- * Handle dblclick. Call the "dblclick" callback if dblclick on a feature.
- *
- * Parameters:
- * evt - {Event}
- *
- * Returns:
- * {Boolean}
- */
- dblclick: function(evt) {
- return !this.handle(evt);
- },
-
- /**
- * Method: geometryTypeMatches
- * Return true if the geometry type of the passed feature matches
- * one of the geometry types in the geometryTypes array.
- *
- * Parameters:
- * feature - {<OpenLayers.Vector.Feature>}
- *
- * Returns:
- * {Boolean}
- */
- geometryTypeMatches: function(feature) {
- return this.geometryTypes == null ||
- OpenLayers.Util.indexOf(this.geometryTypes,
- feature.geometry.CLASS_NAME) > -1;
- },
-
- /**
- * Method: handle
- *
- * Parameters:
- * evt - {Event}
- *
- * Returns:
- * {Boolean} The event occurred over a relevant feature.
- */
- handle: function(evt) {
- if(this.feature && !this.feature.layer) {
- // feature has been destroyed
- this.feature = null;
- }
- var type = evt.type;
- var handled = false;
- var previouslyIn = !!(this.feature); // previously in a feature
- var click = (type == "click" || type == "dblclick" || type == "touchstart");
- this.feature = this.layer.getFeatureFromEvent(evt);
- if(this.feature && !this.feature.layer) {
- // feature has been destroyed
- this.feature = null;
- }
- if(this.lastFeature && !this.lastFeature.layer) {
- // last feature has been destroyed
- this.lastFeature = null;
- }
- if(this.feature) {
- if(type === "touchstart") {
- // stop the event to prevent Android Webkit from
- // "flashing" the map div
- OpenLayers.Event.stop(evt);
- }
- var inNew = (this.feature != this.lastFeature);
- if(this.geometryTypeMatches(this.feature)) {
- // in to a feature
- if(previouslyIn && inNew) {
- // out of last feature and in to another
- if(this.lastFeature) {
- this.triggerCallback(type, 'out', [this.lastFeature]);
- }
- this.triggerCallback(type, 'in', [this.feature]);
- } else if(!previouslyIn || click) {
- // in feature for the first time
- this.triggerCallback(type, 'in', [this.feature]);
- }
- this.lastFeature = this.feature;
- handled = true;
- } else {
- // not in to a feature
- if(this.lastFeature && (previouslyIn && inNew || click)) {
- // out of last feature for the first time
- this.triggerCallback(type, 'out', [this.lastFeature]);
- }
- // next time the mouse goes in a feature whose geometry type
- // doesn't match we don't want to call the 'out' callback
- // again, so let's set this.feature to null so that
- // previouslyIn will evaluate to false the next time
- // we enter handle. Yes, a bit hackish...
- this.feature = null;
- }
- } else if(this.lastFeature && (previouslyIn || click)) {
- this.triggerCallback(type, 'out', [this.lastFeature]);
- }
- return handled;
- },
-
- /**
- * Method: triggerCallback
- * Call the callback keyed in the event map with the supplied arguments.
- * For click and clickout, the <clickTolerance> is checked first.
- *
- * Parameters:
- * type - {String}
- */
- triggerCallback: function(type, mode, args) {
- var key = this.EVENTMAP[type][mode];
- if(key) {
- if(type == 'click' && this.up && this.down) {
- // for click/clickout, only trigger callback if tolerance is met
- var dpx = Math.sqrt(
- Math.pow(this.up.x - this.down.x, 2) +
- Math.pow(this.up.y - this.down.y, 2)
- );
- if(dpx <= this.clickTolerance) {
- this.callback(key, args);
- }
- } else {
- this.callback(key, args);
- }
- }
- },
-
- /**
- * Method: activate
- * Turn on the handler. Returns false if the handler was already active.
- *
- * Returns:
- * {Boolean}
- */
- activate: function() {
- var activated = false;
- if(OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
- this.moveLayerToTop();
- this.map.events.on({
- "removelayer": this.handleMapEvents,
- "changelayer": this.handleMapEvents,
- scope: this
- });
- activated = true;
- }
- return activated;
- },
-
- /**
- * Method: deactivate
- * Turn off the handler. Returns false if the handler was already active.
- *
- * Returns:
- * {Boolean}
- */
- deactivate: function() {
- var deactivated = false;
- if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
- this.moveLayerBack();
- this.feature = null;
- this.lastFeature = null;
- this.down = null;
- this.up = null;
- this.touch = false;
- this.map.events.un({
- "removelayer": this.handleMapEvents,
- "changelayer": this.handleMapEvents,
- scope: this
- });
- deactivated = true;
- }
- return deactivated;
- },
-
- /**
- * Method: handleMapEvents
- *
- * Parameters:
- * evt - {Object}
- */
- handleMapEvents: function(evt) {
- if (evt.type == "removelayer" || evt.property == "order") {
- this.moveLayerToTop();
- }
- },
-
- /**
- * Method: moveLayerToTop
- * Moves the layer for this handler to the top, so mouse events can reach
- * it.
- */
- moveLayerToTop: function() {
- var index = Math.max(this.map.Z_INDEX_BASE['Feature'] - 1,
- this.layer.getZIndex()) + 1;
- this.layer.setZIndex(index);
-
- },
-
- /**
- * Method: moveLayerBack
- * Moves the layer back to the position determined by the map's layers
- * array.
- */
- moveLayerBack: function() {
- var index = this.layer.getZIndex() - 1;
- if (index >= this.map.Z_INDEX_BASE['Feature']) {
- this.layer.setZIndex(index);
- } else {
- this.map.setLayerZIndex(this.layer,
- this.map.getLayerIndex(this.layer));
- }
- },
-
- CLASS_NAME: "OpenLayers.Handler.Feature"
+ CLASS_NAME: "OpenLayers.Format.OSM"
});
-/* ======================================================================
- OpenLayers/Control/DragFeature.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/Control.js
- * @requires OpenLayers/Handler/Drag.js
- * @requires OpenLayers/Handler/Feature.js
- */
-
-/**
- * Class: OpenLayers.Control.DragFeature
- * The DragFeature control moves a feature with a drag of the mouse. Create a
- * new control with the <OpenLayers.Control.DragFeature> constructor.
+ * Function that parse a multypolygone. Use the roles inner and enclave
+ * for inner border. all others will be considère as outer border.
*
- * Inherits From:
- * - <OpenLayers.Control>
- */
-OpenLayers.Control.DragFeature = OpenLayers.Class(OpenLayers.Control, {
-
- /**
- * APIProperty: geometryTypes
- * {Array(String)} To restrict dragging to a limited set of geometry types,
- * send a list of strings corresponding to the geometry class names.
- */
- geometryTypes: null,
-
- /**
- * APIProperty: onStart
- * {Function} Define this function if you want to know when a drag starts.
- * The function should expect to receive two arguments: the feature
- * that is about to be dragged and the pixel location of the mouse.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>} The feature that is about to be
- * dragged.
- * pixel - {<OpenLayers.Pixel>} The pixel location of the mouse.
- */
- onStart: function(feature, pixel) {},
-
- /**
- * APIProperty: onDrag
- * {Function} Define this function if you want to know about each move of a
- * feature. The function should expect to receive two arguments: the
- * feature that is being dragged and the pixel location of the mouse.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>} The feature that was dragged.
- * pixel - {<OpenLayers.Pixel>} The pixel location of the mouse.
- */
- onDrag: function(feature, pixel) {},
-
- /**
- * APIProperty: onComplete
- * {Function} Define this function if you want to know when a feature is
- * done dragging. The function should expect to receive two arguments:
- * the feature that is being dragged and the pixel location of the
- * mouse.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>} The feature that was dragged.
- * pixel - {<OpenLayers.Pixel>} The pixel location of the mouse.
- */
- onComplete: function(feature, pixel) {},
-
- /**
- * APIProperty: onEnter
- * {Function} Define this function if you want to know when the mouse
- * goes over a feature and thereby makes this feature a candidate
- * for dragging.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>} The feature that is ready
- * to be dragged.
- */
- onEnter: function(feature) {},
-
- /**
- * APIProperty: onLeave
- * {Function} Define this function if you want to know when the mouse
- * goes out of the feature that was dragged.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>} The feature that was dragged.
- */
- onLeave: function(feature) {},
-
- /**
- * APIProperty: documentDrag
- * {Boolean} If set to true, mouse dragging will continue even if the
- * mouse cursor leaves the map viewport. Default is false.
- */
- documentDrag: false,
-
- /**
- * Property: layer
- * {<OpenLayers.Layer.Vector>}
- */
- layer: null,
-
- /**
- * Property: feature
- * {<OpenLayers.Feature.Vector>}
- */
- feature: null,
-
- /**
- * Property: dragCallbacks
- * {Object} The functions that are sent to the drag handler for callback.
- */
- dragCallbacks: {},
-
- /**
- * Property: featureCallbacks
- * {Object} The functions that are sent to the feature handler for callback.
- */
- featureCallbacks: {},
-
- /**
- * Property: lastPixel
- * {<OpenLayers.Pixel>}
- */
- lastPixel: null,
-
- /**
- * Constructor: OpenLayers.Control.DragFeature
- * Create a new control to drag features.
- *
- * Parameters:
- * layer - {<OpenLayers.Layer.Vector>} The layer containing features to be
- * dragged.
- * options - {Object} Optional object whose properties will be set on the
- * control.
- */
- initialize: function(layer, options) {
- OpenLayers.Control.prototype.initialize.apply(this, [options]);
- this.layer = layer;
- this.handlers = {
- drag: new OpenLayers.Handler.Drag(
- this, OpenLayers.Util.extend({
- down: this.downFeature,
- move: this.moveFeature,
- up: this.upFeature,
- out: this.cancel,
- done: this.doneDragging
- }, this.dragCallbacks), {
- documentDrag: this.documentDrag
- }
- ),
- feature: new OpenLayers.Handler.Feature(
- this, this.layer, OpenLayers.Util.extend({
- // 'click' and 'clickout' callback are for the mobile
- // support: no 'over' or 'out' in touch based browsers.
- click: this.clickFeature,
- clickout: this.clickoutFeature,
- over: this.overFeature,
- out: this.outFeature
- }, this.featureCallbacks),
- {geometryTypes: this.geometryTypes}
- )
- };
- },
-
- /**
- * Method: clickFeature
- * Called when the feature handler detects a click-in on a feature.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- clickFeature: function(feature) {
- if (this.handlers.feature.touch && !this.over && this.overFeature(feature)) {
- this.handlers.drag.dragstart(this.handlers.feature.evt);
- // to let the events propagate to the feature handler (click callback)
- this.handlers.drag.stopDown = false;
- }
- },
-
- /**
- * Method: clickoutFeature
- * Called when the feature handler detects a click-out on a feature.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- clickoutFeature: function(feature) {
- if (this.handlers.feature.touch && this.over) {
- this.outFeature(feature);
- this.handlers.drag.stopDown = true;
- }
- },
-
- /**
- * APIMethod: destroy
- * Take care of things that are not handled in superclass
- */
- destroy: function() {
- this.layer = null;
- OpenLayers.Control.prototype.destroy.apply(this, []);
- },
-
- /**
- * APIMethod: activate
- * Activate the control and the feature handler.
- *
- * Returns:
- * {Boolean} Successfully activated the control and feature handler.
- */
- activate: function() {
- return (this.handlers.feature.activate() &&
- OpenLayers.Control.prototype.activate.apply(this, arguments));
- },
-
- /**
- * APIMethod: deactivate
- * Deactivate the control and all handlers.
- *
- * Returns:
- * {Boolean} Successfully deactivated the control.
- */
- deactivate: function() {
- // the return from the handlers is unimportant in this case
- this.handlers.drag.deactivate();
- this.handlers.feature.deactivate();
- this.feature = null;
- this.dragging = false;
- this.lastPixel = null;
- OpenLayers.Element.removeClass(
- this.map.viewPortDiv, this.displayClass + "Over"
- );
- return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
- },
-
- /**
- * Method: overFeature
- * Called when the feature handler detects a mouse-over on a feature.
- * This activates the drag handler.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>} The selected feature.
- *
- * Returns:
- * {Boolean} Successfully activated the drag handler.
- */
- overFeature: function(feature) {
- var activated = false;
- if(!this.handlers.drag.dragging) {
- this.feature = feature;
- this.handlers.drag.activate();
- activated = true;
- this.over = true;
- OpenLayers.Element.addClass(this.map.viewPortDiv, this.displayClass + "Over");
- this.onEnter(feature);
- } else {
- if(this.feature.id == feature.id) {
- this.over = true;
- } else {
- this.over = false;
- }
- }
- return activated;
- },
-
- /**
- * Method: downFeature
- * Called when the drag handler detects a mouse-down.
- *
- * Parameters:
- * pixel - {<OpenLayers.Pixel>} Location of the mouse event.
- */
- downFeature: function(pixel) {
- this.lastPixel = pixel;
- this.onStart(this.feature, pixel);
- },
-
- /**
- * Method: moveFeature
- * Called when the drag handler detects a mouse-move. Also calls the
- * optional onDrag method.
- *
- * Parameters:
- * pixel - {<OpenLayers.Pixel>} Location of the mouse event.
- */
- moveFeature: function(pixel) {
- var res = this.map.getResolution();
- this.feature.geometry.move(res * (pixel.x - this.lastPixel.x),
- res * (this.lastPixel.y - pixel.y));
- this.layer.drawFeature(this.feature);
- this.lastPixel = pixel;
- this.onDrag(this.feature, pixel);
- },
-
- /**
- * Method: upFeature
- * Called when the drag handler detects a mouse-up.
- *
- * Parameters:
- * pixel - {<OpenLayers.Pixel>} Location of the mouse event.
- */
- upFeature: function(pixel) {
- if(!this.over) {
- this.handlers.drag.deactivate();
- }
- },
-
- /**
- * Method: doneDragging
- * Called when the drag handler is done dragging.
- *
- * Parameters:
- * pixel - {<OpenLayers.Pixel>} The last event pixel location. If this event
- * came from a mouseout, this may not be in the map viewport.
- */
- doneDragging: function(pixel) {
- this.onComplete(this.feature, pixel);
- },
-
- /**
- * Method: outFeature
- * Called when the feature handler detects a mouse-out on a feature.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>} The feature that the mouse left.
- */
- outFeature: function(feature) {
- if(!this.handlers.drag.dragging) {
- this.over = false;
- this.handlers.drag.deactivate();
- OpenLayers.Element.removeClass(
- this.map.viewPortDiv, this.displayClass + "Over"
- );
- this.onLeave(feature);
- this.feature = null;
- } else {
- if(this.feature.id == feature.id) {
- this.over = false;
- }
- }
- },
-
- /**
- * Method: cancel
- * Called when the drag handler detects a mouse-out (from the map viewport).
- */
- cancel: function() {
- this.handlers.drag.deactivate();
- this.over = false;
- },
-
- /**
- * Method: setMap
- * Set the map property for the control and all handlers.
- *
- * Parameters:
- * map - {<OpenLayers.Map>} The control's map.
- */
- setMap: function(map) {
- this.handlers.drag.setMap(map);
- this.handlers.feature.setMap(map);
- OpenLayers.Control.prototype.setMap.apply(this, arguments);
- },
-
- CLASS_NAME: "OpenLayers.Control.DragFeature"
-});
-/* ======================================================================
- 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 {<OpenLayers.Style>}, 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 - {<OpenLayers.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/Layer/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. */
-
-/**
- * @requires OpenLayers/Layer.js
- * @requires OpenLayers/Renderer.js
- * @requires OpenLayers/StyleMap.js
- * @requires OpenLayers/Feature/Vector.js
- * @requires OpenLayers/Console.js
- * @requires OpenLayers/Lang.js
- */
-
-/**
- * Class: OpenLayers.Layer.Vector
- * Instances of OpenLayers.Layer.Vector are used to render vector data from
- * a variety of sources. Create a new vector layer with the
- * <OpenLayers.Layer.Vector> constructor.
+ * Parameters:
+ * relation - {DOMElement} the relation to parse
+ * parser - <OpenLayers.parser.OSM> the parser
+ * nodes - {Array({DOMElement})} all the available nodes
+ * ways - {Array({DOMElement})} all the available ways
+ * relations - {Array({DOMElement})} all the available relations
*
- * Inherits from:
- * - <OpenLayers.Layer>
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} a list of one element that represent the multypolygone
*/
-OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
+OpenLayers.Format.OSM.multipolygonParser = function(relation, parser, nodes, ways, relations) {
+ var lastRole = '';
+ var lastPointList = [];
+ var innerLignes = [];
+ var outerLignes = [];
- /**
- * APIProperty: events
- * {<OpenLayers.Events>}
- *
- * Register a listener for a particular event with the following syntax:
- * (code)
- * layer.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 layer.events.object.
- * element - {DOMElement} A reference to layer.events.element.
- *
- * Supported map event types (in addition to those from <OpenLayers.Layer.events>):
- * beforefeatureadded - Triggered before a feature is added. Listeners
- * will receive an object with a *feature* property referencing the
- * feature to be added. To stop the feature from being added, a
- * listener should return false.
- * beforefeaturesadded - Triggered before an array of features is added.
- * Listeners will receive an object with a *features* property
- * referencing the feature to be added. To stop the features from
- * being added, a listener should return false.
- * featureadded - Triggered after a feature is added. The event
- * object passed to listeners will have a *feature* property with a
- * reference to the added feature.
- * featuresadded - Triggered after features are added. The event
- * object passed to listeners will have a *features* property with a
- * reference to an array of added features.
- * beforefeatureremoved - Triggered before a feature is removed. Listeners
- * will receive an object with a *feature* property referencing the
- * feature to be removed.
- * beforefeaturesremoved - Triggered before multiple features are removed.
- * Listeners will receive an object with a *features* property
- * referencing the features to be removed.
- * featureremoved - Triggerd after a feature is removed. The event
- * object passed to listeners will have a *feature* property with a
- * reference to the removed feature.
- * featuresremoved - Triggered after features are removed. The event
- * object passed to listeners will have a *features* property with a
- * reference to an array of removed features.
- * beforefeatureselected - Triggered before a feature is selected. Listeners
- * will receive an object with a *feature* property referencing the
- * feature to be selected. To stop the feature from being selectd, a
- * listener should return false.
- * featureselected - Triggered after a feature is selected. Listeners
- * will receive an object with a *feature* property referencing the
- * selected feature.
- * featureunselected - Triggered after a feature is unselected.
- * Listeners will receive an object with a *feature* property
- * referencing the unselected feature.
- * beforefeaturemodified - Triggered when a feature is selected to
- * be modified. Listeners will receive an object with a *feature*
- * property referencing the selected feature.
- * featuremodified - Triggered when a feature has been modified.
- * Listeners will receive an object with a *feature* property referencing
- * the modified feature.
- * afterfeaturemodified - Triggered when a feature is finished being modified.
- * Listeners will receive an object with a *feature* property referencing
- * the modified feature.
- * vertexmodified - Triggered when a vertex within any feature geometry
- * has been modified. Listeners will receive an object with a
- * *feature* property referencing the modified feature, a *vertex*
- * property referencing the vertex modified (always a point geometry),
- * and a *pixel* property referencing the pixel location of the
- * modification.
- * vertexremoved - Triggered when a vertex within any feature geometry
- * has been deleted. Listeners will receive an object with a
- * *feature* property referencing the modified feature, a *vertex*
- * property referencing the vertex modified (always a point geometry),
- * and a *pixel* property referencing the pixel location of the
- * removal.
- * sketchstarted - Triggered when a feature sketch bound for this layer
- * is started. Listeners will receive an object with a *feature*
- * property referencing the new sketch feature and a *vertex* property
- * referencing the creation point.
- * sketchmodified - Triggered when a feature sketch bound for this layer
- * is modified. Listeners will receive an object with a *vertex*
- * property referencing the modified vertex and a *feature* property
- * referencing the sketch feature.
- * sketchcomplete - Triggered when a feature sketch bound for this layer
- * is complete. Listeners will receive an object with a *feature*
- * property referencing the sketch feature. By returning false, a
- * listener can stop the sketch feature from being added to the layer.
- * refresh - Triggered when something wants a strategy to ask the protocol
- * for a new set of features.
- */
+ for (var j = 0; j < relation.ways.length; j++) {
+ var way = relation.ways[j]
+ var ref = way.getAttribute("ref");
+ var role = way.getAttribute("role");
- /**
- * APIProperty: isBaseLayer
- * {Boolean} The layer is a base layer. Default is false. Set this property
- * in the layer options.
- */
- isBaseLayer: false,
-
- /**
- * APIProperty: isFixed
- * {Boolean} Whether the layer remains in one place while dragging the
- * map. Note that setting this to true will move the layer to the bottom
- * of the layer stack.
- */
- isFixed: false,
-
- /**
- * APIProperty: features
- * {Array(<OpenLayers.Feature.Vector>)}
- */
- features: null,
-
- /**
- * Property: filter
- * {<OpenLayers.Filter>} The filter set in this layer,
- * a strategy launching read requests can combined
- * this filter with its own filter.
- */
- filter: null,
-
- /**
- * Property: selectedFeatures
- * {Array(<OpenLayers.Feature.Vector>)}
- */
- selectedFeatures: null,
-
- /**
- * Property: unrenderedFeatures
- * {Object} hash of features, keyed by feature.id, that the renderer
- * failed to draw
- */
- unrenderedFeatures: null,
-
- /**
- * APIProperty: reportError
- * {Boolean} report friendly error message when loading of renderer
- * fails.
- */
- reportError: true,
-
- /**
- * APIProperty: style
- * {Object} Default style for the layer
- */
- style: null,
-
- /**
- * Property: styleMap
- * {<OpenLayers.StyleMap>}
- */
- styleMap: null,
-
- /**
- * Property: strategies
- * {Array(<OpenLayers.Strategy>})} Optional list of strategies for the layer.
- */
- strategies: null,
-
- /**
- * Property: protocol
- * {<OpenLayers.Protocol>} Optional protocol for the layer.
- */
- protocol: null,
-
- /**
- * Property: renderers
- * {Array(String)} List of supported Renderer classes. Add to this list to
- * add support for additional renderers. This list is ordered:
- * the first renderer which returns true for the 'supported()'
- * method will be used, if not defined in the 'renderer' option.
- */
- renderers: ['SVG', 'VML', 'Canvas'],
-
- /**
- * Property: renderer
- * {<OpenLayers.Renderer>}
- */
- renderer: null,
-
- /**
- * APIProperty: rendererOptions
- * {Object} Options for the renderer. See {<OpenLayers.Renderer>} for
- * supported options.
- */
- rendererOptions: null,
-
- /**
- * APIProperty: geometryType
- * {String} geometryType allows you to limit the types of geometries this
- * layer supports. This should be set to something like
- * "OpenLayers.Geometry.Point" to limit types.
- */
- geometryType: null,
-
- /**
- * Property: drawn
- * {Boolean} Whether the Vector Layer features have been drawn yet.
- */
- drawn: false,
-
- /**
- * APIProperty: ratio
- * {Float} This specifies the ratio of the size of the visiblity of the Vector Layer features to the size of the map.
- */
- ratio: 1,
-
- /**
- * Constructor: OpenLayers.Layer.Vector
- * Create a new vector layer
- *
- * Parameters:
- * name - {String} A name for the layer
- * options - {Object} Optional object with non-default properties to set on
- * the layer.
- *
- * Returns:
- * {<OpenLayers.Layer.Vector>} A new vector layer
- */
- initialize: function(name, options) {
- OpenLayers.Layer.prototype.initialize.apply(this, arguments);
-
- // allow user-set renderer, otherwise assign one
- if (!this.renderer || !this.renderer.supported()) {
- this.assignRenderer();
+ var pointList = parser.getPointList(ways[ref], nodes);
+ if (pointList.length == 0) {
+ continue;
}
-
- // if no valid renderer found, display error
- if (!this.renderer || !this.renderer.supported()) {
- this.renderer = null;
- this.displayError();
- }
-
- if (!this.styleMap) {
- this.styleMap = new OpenLayers.StyleMap();
+ var newPath = true;
+ if (lastRole == '') {
+ lastRole = role;
}
-
- this.features = [];
- this.selectedFeatures = [];
- this.unrenderedFeatures = {};
-
- // Allow for custom layer behavior
- if(this.strategies){
- for(var i=0, len=this.strategies.length; i<len; i++) {
- this.strategies[i].setLayer(this);
+ if (lastRole == role) {
+ var result = parser.concatPathsIfLinear(lastPointList, pointList);
+ if (result.succed) {
+ newPath = false;
+ lastPointList = result.lastPointList;
}
}
- },
-
- /**
- * APIMethod: destroy
- * Destroy this layer
- */
- destroy: function() {
- if (this.strategies) {
- var strategy, i, len;
- for(i=0, len=this.strategies.length; i<len; i++) {
- strategy = this.strategies[i];
- if(strategy.autoDestroy) {
- strategy.destroy();
+ if (newPath) {
+ if (lastPointList.length > 0) {
+ if (lastRole == 'inner' || lastRole == 'enclave') {
+ var geometry = new OpenLayers.Geometry.LinearRing(lastPointList)
+ innerLignes.push(geometry);
}
- }
- this.strategies = null;
- }
- if (this.protocol) {
- if(this.protocol.autoDestroy) {
- this.protocol.destroy();
- }
- this.protocol = null;
- }
- this.destroyFeatures();
- this.features = null;
- this.selectedFeatures = null;
- this.unrenderedFeatures = null;
- if (this.renderer) {
- this.renderer.destroy();
- }
- this.renderer = null;
- this.geometryType = null;
- this.drawn = null;
- OpenLayers.Layer.prototype.destroy.apply(this, arguments);
- },
-
- /**
- * Method: clone
- * Create a clone of this layer.
- *
- * Note: Features of the layer are also cloned.
- *
- * Returns:
- * {<OpenLayers.Layer.Vector>} An exact clone of this layer
- */
- clone: function (obj) {
-
- if (obj == null) {
- obj = new OpenLayers.Layer.Vector(this.name, this.getOptions());
- }
-
- //get all additions from superclasses
- obj = OpenLayers.Layer.prototype.clone.apply(this, [obj]);
-
- // copy/set any non-init, non-simple values here
- var features = this.features;
- var len = features.length;
- var clonedFeatures = new Array(len);
- for(var i=0; i<len; ++i) {
- clonedFeatures[i] = features[i].clone();
- }
- obj.features = clonedFeatures;
-
- return obj;
- },
-
- /**
- * Method: refresh
- * Ask the layer to request features again and redraw them. Triggers
- * the refresh event if the layer is in range and visible.
- *
- * Parameters:
- * obj - {Object} Optional object with properties for any listener of
- * the refresh event.
- */
- refresh: function(obj) {
- if(this.calculateInRange() && this.visibility) {
- this.events.triggerEvent("refresh", obj);
- }
- },
-
- /**
- * Method: assignRenderer
- * Iterates through the available renderer implementations and selects
- * and assigns the first one whose "supported()" function returns true.
- */
- assignRenderer: function() {
- for (var i=0, len=this.renderers.length; i<len; i++) {
- var rendererClass = this.renderers[i];
- var renderer = (typeof rendererClass == "function") ?
- rendererClass :
- OpenLayers.Renderer[rendererClass];
- if (renderer && renderer.prototype.supported()) {
- this.renderer = new renderer(this.div, this.rendererOptions);
- break;
- }
- }
- },
-
- /**
- * Method: displayError
- * Let the user know their browser isn't supported.
- */
- displayError: function() {
- if (this.reportError) {
- OpenLayers.Console.userError(OpenLayers.i18n("browserNotSupported",
- {renderers: this. renderers.join('\n')}));
- }
- },
-
- /**
- * Method: setMap
- * The layer has been added to the map.
- *
- * If there is no renderer set, the layer can't be used. Remove it.
- * Otherwise, give the renderer a reference to the map and set its size.
- *
- * Parameters:
- * map - {<OpenLayers.Map>}
- */
- setMap: function(map) {
- OpenLayers.Layer.prototype.setMap.apply(this, arguments);
-
- if (!this.renderer) {
- this.map.removeLayer(this);
- } else {
- this.renderer.map = this.map;
-
- var newSize = this.map.getSize();
- newSize.w = newSize.w * this.ratio;
- newSize.h = newSize.h * this.ratio;
- this.renderer.setSize(newSize);
- }
- },
-
- /**
- * Method: afterAdd
- * Called at the end of the map.addLayer sequence. At this point, the map
- * will have a base layer. Any autoActivate strategies will be
- * activated here.
- */
- afterAdd: function() {
- if(this.strategies) {
- var strategy, i, len;
- for(i=0, len=this.strategies.length; i<len; i++) {
- strategy = this.strategies[i];
- if(strategy.autoActivate) {
- strategy.activate();
+ else { // if (lastRole == 'outer') {
+ var geometry = new OpenLayers.Geometry.LinearRing(lastPointList)
+ outerLignes.push(geometry);
}
}
+ lastPointList = pointList;
+ lastRole = role;
}
- },
-
- /**
- * Method: removeMap
- * The layer has been removed from the map.
- *
- * Parameters:
- * map - {<OpenLayers.Map>}
- */
- removeMap: function(map) {
- this.drawn = false;
- if(this.strategies) {
- var strategy, i, len;
- for(i=0, len=this.strategies.length; i<len; i++) {
- strategy = this.strategies[i];
- if(strategy.autoActivate) {
- strategy.deactivate();
- }
- }
+ }
+ if (lastPointList.length > 0) {
+ if (lastRole == 'inner' || lastRole == 'enclave') {
+ var geometry = new OpenLayers.Geometry.LinearRing(lastPointList)
+ innerLignes.push(geometry);
}
- },
-
- /**
- * Method: onMapResize
- * Notify the renderer of the change in size.
- *
- */
- onMapResize: function() {
- OpenLayers.Layer.prototype.onMapResize.apply(this, arguments);
-
- var newSize = this.map.getSize();
- newSize.w = newSize.w * this.ratio;
- newSize.h = newSize.h * this.ratio;
- this.renderer.setSize(newSize);
- },
-
- /**
- * Method: moveTo
- * Reset the vector layer's div so that it once again is lined up with
- * the map. Notify the renderer of the change of extent, and in the
- * case of a change of zoom level (resolution), have the
- * renderer redraw features.
- *
- * If the layer has not yet been drawn, cycle through the layer's
- * features and draw each one.
- *
- * Parameters:
- * bounds - {<OpenLayers.Bounds>}
- * zoomChanged - {Boolean}
- * dragging - {Boolean}
- */
- moveTo: function(bounds, zoomChanged, dragging) {
- OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
-
- var coordSysUnchanged = true;
- if (!dragging) {
- this.renderer.root.style.visibility = 'hidden';
-
- var viewSize = this.map.getSize(),
- viewWidth = viewSize.w,
- viewHeight = viewSize.h,
- offsetLeft = (viewWidth / 2 * this.ratio) - viewWidth / 2,
- offsetTop = (viewHeight / 2 * this.ratio) - viewHeight / 2;
- offsetLeft += this.map.layerContainerOriginPx.x;
- offsetLeft = -Math.round(offsetLeft);
- offsetTop += this.map.layerContainerOriginPx.y;
- offsetTop = -Math.round(offsetTop);
-
- this.div.style.left = offsetLeft + 'px';
- this.div.style.top = offsetTop + 'px';
-
- var extent = this.map.getExtent().scale(this.ratio);
- coordSysUnchanged = this.renderer.setExtent(extent, zoomChanged);
-
- this.renderer.root.style.visibility = 'visible';
-
- // Force a reflow on gecko based browsers to prevent jump/flicker.
- // This seems to happen on only certain configurations; it was originally
- // noticed in FF 2.0 and Linux.
- if (OpenLayers.IS_GECKO === true) {
- this.div.scrollLeft = this.div.scrollLeft;
- }
-
- if (!zoomChanged && coordSysUnchanged) {
- for (var i in this.unrenderedFeatures) {
- var feature = this.unrenderedFeatures[i];
- this.drawFeature(feature);
- }
- }
+ else { // if (lastRole == 'outer') {
+ var geometry = new OpenLayers.Geometry.LinearRing(lastPointList)
+ outerLignes.push(geometry);
}
- if (!this.drawn || zoomChanged || !coordSysUnchanged) {
- this.drawn = true;
- var feature;
- for(var i=0, len=this.features.length; i<len; i++) {
- this.renderer.locked = (i !== (len - 1));
- feature = this.features[i];
- this.drawFeature(feature);
- }
- }
- },
-
- /**
- * APIMethod: display
- * Hide or show the Layer
- *
- * Parameters:
- * display - {Boolean}
- */
- display: function(display) {
- OpenLayers.Layer.prototype.display.apply(this, arguments);
- // we need to set the display style of the root in case it is attached
- // to a foreign layer
- var currentDisplay = this.div.style.display;
- if(currentDisplay != this.renderer.root.style.display) {
- this.renderer.root.style.display = currentDisplay;
- }
- },
+ }
- /**
- * APIMethod: addFeatures
- * Add Features to the layer.
- *
- * Parameters:
- * features - {Array(<OpenLayers.Feature.Vector>)}
- * options - {Object}
- */
- addFeatures: function(features, options) {
- if (!(OpenLayers.Util.isArray(features))) {
- features = [features];
+ var polygons = [];
+ for (var j = 0 ; j < outerLignes.length ; j++) {
+ if (innerLignes.length == 0) {
+ polygons.push(new OpenLayers.Geometry.Polygon([outerLignes[j]]));
}
-
- var notify = !options || !options.silent;
- if(notify) {
- var event = {features: features};
- var ret = this.events.triggerEvent("beforefeaturesadded", event);
- if(ret === false) {
- return;
- }
- features = event.features;
- }
-
- // Track successfully added features for featuresadded event, since
- // beforefeatureadded can veto single features.
- var featuresAdded = [];
- for (var i=0, len=features.length; i<len; i++) {
- if (i != (features.length - 1)) {
- this.renderer.locked = true;
- } else {
- this.renderer.locked = false;
- }
- var feature = features[i];
-
- if (this.geometryType &&
- !(feature.geometry instanceof this.geometryType)) {
- throw new TypeError('addFeatures: component should be an ' +
- this.geometryType.prototype.CLASS_NAME);
- }
-
- //give feature reference to its layer
- feature.layer = this;
-
- if (!feature.style && this.style) {
- feature.style = OpenLayers.Util.extend({}, this.style);
- }
-
- if (notify) {
- if(this.events.triggerEvent("beforefeatureadded",
- {feature: feature}) === false) {
- continue;
+ else {
+ var currentInners = [];
+ for (var k = 0 ; k < innerLignes.length ; k++) {
+ var inner = innerLignes[k];
+ if (outerLignes[j].containsPoint(inner.getCentroid())) {
+ currentInners.push(inner);
}
- this.preFeatureInsert(feature);
}
-
- featuresAdded.push(feature);
- this.features.push(feature);
- this.drawFeature(feature);
-
- if (notify) {
- this.events.triggerEvent("featureadded", {
- feature: feature
- });
- this.onFeatureInsert(feature);
- }
+ polygons.push(new OpenLayers.Geometry.Polygon(
+ [outerLignes[j]].concat(currentInners)));
}
-
- if(notify) {
- this.events.triggerEvent("featuresadded", {features: featuresAdded});
- }
- },
+ }
+ var geometry = new OpenLayers.Geometry.MultiPolygon(polygons);
+ var feat = new OpenLayers.Feature.Vector(geometry, relation.tags);
+ feat.osm_id = parseInt(relation.id);
+ feat.type = "relation";
+ feat.fid = "relation." + feat.osm_id;
+ return [feat];
+},
+/**
+ * Function that convert all the ways of a relation into a LineStrings.
+ *
+ * Parameters:
+ * relation - {DOMElement} the relation to parse
+ * parser - <OpenLayers.parser.OSM> the parser
+ * nodes - {Array({DOMElement})} all the available nodes
+ * ways - {Array({DOMElement})} all the available ways
+ *
+ * Returns:
+ * {Array(<OpenLayers.Geometry.LineString>)}
+ */
+OpenLayers.Format.OSM.getLineStrings = function(relation, parser, nodes, ways) {
+ var geometries = [];
+ for (var j = 0; j < relation.ways.length; j++) {
+ var way = relation.ways[j]
+ var ref = way.getAttribute("ref");
- /**
- * APIMethod: removeFeatures
- * Remove features from the layer. This erases any drawn features and
- * removes them from the layer's control. The beforefeatureremoved
- * and featureremoved events will be triggered for each feature. The
- * featuresremoved event will be triggered after all features have
- * been removed. To supress event triggering, use the silent option.
- *
- * Parameters:
- * features - {Array(<OpenLayers.Feature.Vector>)} List of features to be
- * removed.
- * options - {Object} Optional properties for changing behavior of the
- * removal.
- *
- * Valid options:
- * silent - {Boolean} Supress event triggering. Default is false.
- */
- removeFeatures: function(features, options) {
- if(!features || features.length === 0) {
- return;
+ // TODO considere to create some area
+ var pointList = parser.getPointList(ways[ref], nodes);
+ if (pointList.length == 0) {
+ continue;
}
- if (features === this.features) {
- return this.removeAllFeatures(options);
- }
- if (!(OpenLayers.Util.isArray(features))) {
- features = [features];
- }
- if (features === this.selectedFeatures) {
- features = features.slice();
- }
- var notify = !options || !options.silent;
-
- if (notify) {
- this.events.triggerEvent(
- "beforefeaturesremoved", {features: features}
- );
- }
+ geometries.push(new OpenLayers.Geometry.LineString(pointList));
+ }
+ return geometries;
+}
- for (var i = features.length - 1; i >= 0; i--) {
- // We remain locked so long as we're not at 0
- // and the 'next' feature has a geometry. We do the geometry check
- // because if all the features after the current one are 'null', we
- // won't call eraseGeometry, so we break the 'renderer functions
- // will always be called with locked=false *last*' rule. The end result
- // is a possible gratiutious unlocking to save a loop through the rest
- // of the list checking the remaining features every time. So long as
- // null geoms are rare, this is probably okay.
- if (i != 0 && features[i-1].geometry) {
- this.renderer.locked = true;
- } else {
- this.renderer.locked = false;
- }
-
- var feature = features[i];
- delete this.unrenderedFeatures[feature.id];
-
- if (notify) {
- this.events.triggerEvent("beforefeatureremoved", {
- feature: feature
- });
- }
-
- this.features = OpenLayers.Util.removeItem(this.features, feature);
- // feature has no layer at this point
- feature.layer = null;
-
- if (feature.geometry) {
- this.renderer.eraseFeatures(feature);
- }
-
- //in the case that this feature is one of the selected features,
- // remove it from that array as well.
- if (OpenLayers.Util.indexOf(this.selectedFeatures, feature) != -1){
- OpenLayers.Util.removeItem(this.selectedFeatures, feature);
- }
-
- if (notify) {
- this.events.triggerEvent("featureremoved", {
- feature: feature
- });
- }
- }
-
- if (notify) {
- this.events.triggerEvent("featuresremoved", {features: features});
- }
- },
-
- /**
- * APIMethod: removeAllFeatures
- * Remove all features from the layer.
- *
- * Parameters:
- * options - {Object} Optional properties for changing behavior of the
- * removal.
- *
- * Valid options:
- * silent - {Boolean} Supress event triggering. Default is false.
- */
- removeAllFeatures: function(options) {
- var notify = !options || !options.silent;
- var features = this.features;
- if (notify) {
- this.events.triggerEvent(
- "beforefeaturesremoved", {features: features}
- );
- }
- var feature;
- for (var i = features.length-1; i >= 0; i--) {
- feature = features[i];
- if (notify) {
- this.events.triggerEvent("beforefeatureremoved", {
- feature: feature
- });
- }
- feature.layer = null;
- if (notify) {
- this.events.triggerEvent("featureremoved", {
- feature: feature
- });
- }
- }
- this.renderer.clear();
- this.features = [];
- this.unrenderedFeatures = {};
- this.selectedFeatures = [];
- if (notify) {
- this.events.triggerEvent("featuresremoved", {features: features});
- }
- },
-
- /**
- * APIMethod: destroyFeatures
- * Erase and destroy features on the layer.
- *
- * Parameters:
- * features - {Array(<OpenLayers.Feature.Vector>)} An optional array of
- * features to destroy. If not supplied, all features on the layer
- * will be destroyed.
- * options - {Object}
- */
- destroyFeatures: function(features, options) {
- var all = (features == undefined); // evaluates to true if
- // features is null
- if(all) {
- features = this.features;
- }
- if(features) {
- this.removeFeatures(features, options);
- for(var i=features.length-1; i>=0; i--) {
- features[i].destroy();
- }
- }
- },
-
- /**
- * APIMethod: drawFeature
- * Draw (or redraw) a feature on the layer. If the optional style argument
- * is included, this style will be used. If no style is included, the
- * feature's style will be used. If the feature doesn't have a style,
- * the layer's style will be used.
- *
- * This function is not designed to be used when adding features to
- * the layer (use addFeatures instead). It is meant to be used when
- * the style of a feature has changed, or in some other way needs to
- * visually updated *after* it has already been added to a layer. You
- * must add the feature to the layer for most layer-related events to
- * happen.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- * style - {String | Object} Named render intent or full symbolizer object.
- */
- drawFeature: function(feature, style) {
- // don't try to draw the feature with the renderer if the layer is not
- // drawn itself
- if (!this.drawn) {
- return;
- }
- if (typeof style != "object") {
- if(!style && feature.state === OpenLayers.State.DELETE) {
- style = "delete";
- }
- var renderIntent = style || feature.renderIntent;
- style = feature.style || this.style;
- if (!style) {
- style = this.styleMap.createSymbolizer(feature, renderIntent);
- }
- }
-
- var drawn = this.renderer.drawFeature(feature, style);
- //TODO remove the check for null when we get rid of Renderer.SVG
- if (drawn === false || drawn === null) {
- this.unrenderedFeatures[feature.id] = feature;
- } else {
- delete this.unrenderedFeatures[feature.id];
- }
- },
-
- /**
- * Method: eraseFeatures
- * Erase features from the layer.
- *
- * Parameters:
- * features - {Array(<OpenLayers.Feature.Vector>)}
- */
- eraseFeatures: function(features) {
- this.renderer.eraseFeatures(features);
- },
-
- /**
- * Method: getFeatureFromEvent
- * Given an event, return a feature if the event occurred over one.
- * Otherwise, return null.
- *
- * Parameters:
- * evt - {Event}
- *
- * Returns:
- * {<OpenLayers.Feature.Vector>} A feature if one was under the event.
- */
- getFeatureFromEvent: function(evt) {
- if (!this.renderer) {
- throw new Error('getFeatureFromEvent called on layer with no ' +
- 'renderer. This usually means you destroyed a ' +
- 'layer, but not some handler which is associated ' +
- 'with it.');
- }
- var feature = null;
- var featureId = this.renderer.getFeatureIdFromEvent(evt);
- if (featureId) {
- if (typeof featureId === "string") {
- feature = this.getFeatureById(featureId);
- } else {
- feature = featureId;
- }
- }
- return feature;
- },
-
- /**
- * APIMethod: getFeatureBy
- * Given a property value, return the feature if it exists in the features array
- *
- * Parameters:
- * property - {String}
- * value - {String}
- *
- * Returns:
- * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
- * property value or null if there is no such feature.
- */
- getFeatureBy: function(property, value) {
- //TBD - would it be more efficient to use a hash for this.features?
- var feature = null;
- for(var i=0, len=this.features.length; i<len; ++i) {
- if(this.features[i][property] == value) {
- feature = this.features[i];
- break;
- }
- }
- return feature;
- },
-
- /**
- * APIMethod: getFeatureById
- * Given a feature id, return the feature if it exists in the features array
- *
- * Parameters:
- * featureId - {String}
- *
- * Returns:
- * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
- * featureId or null if there is no such feature.
- */
- getFeatureById: function(featureId) {
- return this.getFeatureBy('id', featureId);
- },
-
- /**
- * APIMethod: getFeatureByFid
- * Given a feature fid, return the feature if it exists in the features array
- *
- * Parameters:
- * featureFid - {String}
- *
- * Returns:
- * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
- * featureFid or null if there is no such feature.
- */
- getFeatureByFid: function(featureFid) {
- return this.getFeatureBy('fid', featureFid);
- },
-
- /**
- * APIMethod: getFeaturesByAttribute
- * Returns an array of features that have the given attribute key set to the
- * given value. Comparison of attribute values takes care of datatypes, e.g.
- * the string '1234' is not equal to the number 1234.
- *
- * Parameters:
- * attrName - {String}
- * attrValue - {Mixed}
- *
- * Returns:
- * Array({<OpenLayers.Feature.Vector>}) An array of features that have the
- * passed named attribute set to the given value.
- */
- getFeaturesByAttribute: function(attrName, attrValue) {
- var i,
- feature,
- len = this.features.length,
- foundFeatures = [];
- for(i = 0; i < len; i++) {
- feature = this.features[i];
- if(feature && feature.attributes) {
- if (feature.attributes[attrName] === attrValue) {
- foundFeatures.push(feature);
- }
- }
- }
- return foundFeatures;
- },
-
- /**
- * Unselect the selected features
- * i.e. clears the featureSelection array
- * change the style back
- clearSelection: function() {
-
- var vectorLayer = this.map.vectorLayer;
- for (var i = 0; i < this.map.featureSelection.length; i++) {
- var featureSelection = this.map.featureSelection[i];
- vectorLayer.drawFeature(featureSelection, vectorLayer.style);
- }
- this.map.featureSelection = [];
- },
- */
-
-
- /**
- * APIMethod: onFeatureInsert
- * method called after a feature is inserted.
- * Does nothing by default. Override this if you
- * need to do something on feature updates.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- onFeatureInsert: function(feature) {
- },
-
- /**
- * APIMethod: preFeatureInsert
- * method called before a feature is inserted.
- * Does nothing by default. Override this if you
- * need to do something when features are first added to the
- * layer, but before they are drawn, such as adjust the style.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- preFeatureInsert: function(feature) {
- },
-
- /**
- * APIMethod: getDataExtent
- * Calculates the max extent which includes all of the features.
- *
- * Returns:
- * {<OpenLayers.Bounds>} or null if the layer has no features with
- * geometries.
- */
- getDataExtent: function () {
- var maxExtent = null;
- var features = this.features;
- if(features && (features.length > 0)) {
- var geometry = null;
- for(var i=0, len=features.length; i<len; i++) {
- geometry = features[i].geometry;
- if (geometry) {
- if (maxExtent === null) {
- maxExtent = new OpenLayers.Bounds();
- }
- maxExtent.extend(geometry.getBounds());
- }
- }
- }
- return maxExtent;
- },
-
- CLASS_NAME: "OpenLayers.Layer.Vector"
-});
-/* ======================================================================
- OpenLayers/Layer/Vector/RootContainer.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/Layer/Vector.js
+ * Function that parse a route. All the inner ways will be converted into a MultiLineString.
+ *
+ * Parameters:
+ * relation - {DOMElement} the relation to parse
+ * parser - <OpenLayers.parser.OSM> the parser
+ * nodes - {Array({DOMElement})} all the available nodes
+ * ways - {Array({DOMElement})} all the available ways
+ * relations - {Array({DOMElement})} all the available relations
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} a list of one element that represent the route.
*/
+OpenLayers.Format.OSM.routeParser = function(relation, parser, nodes, ways, relations) {
+ var geometries = OpenLayers.Format.OSM.getLineStrings(relation, parser, nodes, ways);
+ var geometry = new OpenLayers.Geometry.MultiLineString(geometries);
+ var feat = new OpenLayers.Feature.Vector(geometry, relation.tags);
+ feat.osm_id = parseInt(relation.id);
+ feat.type = "relation";
+ feat.fid = "relation." + feat.osm_id;
+ return [feat];
+}
/**
- * Class: OpenLayers.Layer.Vector.RootContainer
- * A special layer type to combine multiple vector layers inside a single
- * renderer root container. This class is not supposed to be instantiated
- * from user space, it is a helper class for controls that require event
- * processing for multiple vector layers.
+ * Function that parse a relation. All inerr way will be converten into LineLtrings,
+ * and all inner nodes into Points.
*
- * Inherits from:
- * - <OpenLayers.Layer.Vector>
+ * Parameters:
+ * relation - {DOMElement} the relation to parse
+ * parser - <OpenLayers.parser.OSM> the parser
+ * nodes - {Array({DOMElement})} all the available nodes
+ * ways - {Array({DOMElement})} all the available ways
+ * relations - {Array({DOMElement})} all the available relations
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} a lint of one element that represent the relation.
*/
-OpenLayers.Layer.Vector.RootContainer = OpenLayers.Class(OpenLayers.Layer.Vector, {
-
- /**
- * Property: displayInLayerSwitcher
- * Set to false for this layer type
- */
- displayInLayerSwitcher: false,
-
- /**
- * APIProperty: layers
- * Layers that are attached to this container. Required config option.
- */
- layers: null,
-
- /**
- * Constructor: OpenLayers.Layer.Vector.RootContainer
- * Create a new root container for multiple vector layer. This constructor
- * is not supposed to be used from user space, it is only to be used by
- * controls that need feature selection across multiple vector layers.
- *
- * Parameters:
- * name - {String} A name for the layer
- * options - {Object} Optional object with non-default properties to set on
- * the layer.
- *
- * Required options properties:
- * layers - {Array(<OpenLayers.Layer.Vector>)} The layers managed by this
- * container
- *
- * Returns:
- * {<OpenLayers.Layer.Vector.RootContainer>} A new vector layer root
- * container
- */
-
- /**
- * Method: display
- */
- display: function() {},
-
- /**
- * Method: getFeatureFromEvent
- * walk through the layers to find the feature returned by the event
- *
- * Parameters:
- * evt - {Object} event object with a feature property
- *
- * Returns:
- * {<OpenLayers.Feature.Vector>}
- */
- getFeatureFromEvent: function(evt) {
- var layers = this.layers;
- var feature;
- for(var i=0; i<layers.length; i++) {
- feature = layers[i].getFeatureFromEvent(evt);
- if(feature) {
- return feature;
- }
- }
- },
-
- /**
- * Method: setMap
- *
- * Parameters:
- * map - {<OpenLayers.Map>}
- */
- setMap: function(map) {
- OpenLayers.Layer.Vector.prototype.setMap.apply(this, arguments);
- this.collectRoots();
- map.events.register("changelayer", this, this.handleChangeLayer);
- },
-
- /**
- * Method: removeMap
- *
- * Parameters:
- * map - {<OpenLayers.Map>}
- */
- removeMap: function(map) {
- map.events.unregister("changelayer", this, this.handleChangeLayer);
- this.resetRoots();
- OpenLayers.Layer.Vector.prototype.removeMap.apply(this, arguments);
- },
-
- /**
- * Method: collectRoots
- * Collects the root nodes of all layers this control is configured with
- * and moveswien the nodes to this control's layer
- */
- collectRoots: function() {
- var layer;
- // walk through all map layers, because we want to keep the order
- for(var i=0; i<this.map.layers.length; ++i) {
- layer = this.map.layers[i];
- if(OpenLayers.Util.indexOf(this.layers, layer) != -1) {
- layer.renderer.moveRoot(this.renderer);
- }
- }
- },
-
- /**
- * Method: resetRoots
- * Resets the root nodes back into the layers they belong to.
- */
- resetRoots: function() {
- var layer;
- for(var i=0; i<this.layers.length; ++i) {
- layer = this.layers[i];
- if(this.renderer && layer.renderer.getRenderLayerId() == this.id) {
- this.renderer.moveRoot(layer.renderer);
- }
- }
- },
-
- /**
- * Method: handleChangeLayer
- * Event handler for the map's changelayer event. We need to rebuild
- * this container's layer dom if order of one of its layers changes.
- * This handler is added with the setMap method, and removed with the
- * removeMap method.
- *
- * Parameters:
- * evt - {Object}
- */
- handleChangeLayer: function(evt) {
- var layer = evt.layer;
- if(evt.property == "order" &&
- OpenLayers.Util.indexOf(this.layers, layer) != -1) {
- this.resetRoots();
- this.collectRoots();
- }
- },
+OpenLayers.Format.OSM.genericParser = function(relation, parser, nodes, ways, relations) {
+ var geometries = OpenLayers.Format.OSM.getLineStrings(relation, parser, nodes, ways);
+ for (var j = 0; j < relation.nodes.length; j++) {
+ var node = relation.nodes[j]
+ geometries.push(new OpenLayers.Geometry.Node(node));
+ }
+ var geometry = new OpenLayers.Geometry.Collection(geometries);
+ var feat = new OpenLayers.Feature.Vector(geometry, relation.tags);
+ feat.osm_id = parseInt(relation.id);
+ feat.type = "relation";
+ feat.fid = "relation." + feat.osm_id;
+ return [feat];
+}
- CLASS_NAME: "OpenLayers.Layer.Vector.RootContainer"
-});
-/* ======================================================================
- OpenLayers/Control/SelectFeature.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/Control.js
- * @requires OpenLayers/Feature/Vector.js
- * @requires OpenLayers/Handler/Feature.js
- * @requires OpenLayers/Layer/Vector/RootContainer.js
- */
-
-/**
- * Class: OpenLayers.Control.SelectFeature
- * The SelectFeature control selects vector features from a given layer on
- * click or hover.
+ * Function that parse a route. All linear ways with the same role
+ * will be converted into one LineString.
*
- * Inherits from:
- * - <OpenLayers.Control>
+ * Parameters:
+ * relation - {DOMElement} the relation to parse
+ * parser - <OpenLayers.parser.OSM> the parser
+ * nodes - {Array({DOMElement})} all the available nodes
+ * ways - {Array({DOMElement})} all the available ways
+ * relations - {Array({DOMElement})} all the available relations
+ *
+ * Returns:
+ * {Array(<OpenLayers.Feature.Vector>)} a list of linear LineString.
*/
-OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
+OpenLayers.Format.OSM.routeParserWithRoles = function(relation, parser, nodes, ways, relations) {
+ var geometries = [];
+ var lastRole = '';
+ var lastPointList = [];
+ var features = [];
- /**
- * APIProperty: events
- * {<OpenLayers.Events>} Events instance for listeners and triggering
- * control specific events.
- *
- * Register a listener for a particular event with the following syntax:
- * (code)
- * control.events.register(type, obj, listener);
- * (end)
- *
- * Supported event types (in addition to those from <OpenLayers.Control.events>):
- * beforefeaturehighlighted - Triggered before a feature is highlighted
- * featurehighlighted - Triggered when a feature is highlighted
- * featureunhighlighted - Triggered when a feature is unhighlighted
- * boxselectionstart - Triggered before box selection starts
- * boxselectionend - Triggered after box selection ends
- */
-
- /**
- * Property: multipleKey
- * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
- * the <multiple> property to true. Default is null.
- */
- multipleKey: null,
-
- /**
- * Property: toggleKey
- * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
- * the <toggle> property to true. Default is null.
- */
- toggleKey: null,
-
- /**
- * APIProperty: multiple
- * {Boolean} Allow selection of multiple geometries. Default is false.
- */
- multiple: false,
+ for (var j = 0; j < relation.ways.length; j++) {
+ var way = relation.ways[j]
+ var ref = way.getAttribute("ref");
+ var role = way.getAttribute("role");
- /**
- * APIProperty: clickout
- * {Boolean} Unselect features when clicking outside any feature.
- * Default is true.
- */
- clickout: true,
-
- /**
- * APIProperty: toggle
- * {Boolean} Unselect a selected feature on click. Default is false. Only
- * has meaning if hover is false.
- */
- toggle: false,
-
- /**
- * APIProperty: hover
- * {Boolean} Select on mouse over and deselect on mouse out. If true, this
- * ignores clicks and only listens to mouse moves.
- */
- hover: false,
-
- /**
- * APIProperty: highlightOnly
- * {Boolean} If true do not actually select features (that is place them in
- * the layer's selected features array), just highlight them. This property
- * has no effect if hover is false. Defaults to false.
- */
- highlightOnly: false,
-
- /**
- * APIProperty: box
- * {Boolean} Allow feature selection by drawing a box.
- */
- box: false,
-
- /**
- * Property: onBeforeSelect
- * {Function} Optional function to be called before a feature is selected.
- * The function should expect to be called with a feature.
- */
- onBeforeSelect: function() {},
-
- /**
- * APIProperty: onSelect
- * {Function} Optional function to be called when a feature is selected.
- * The function should expect to be called with a feature.
- */
- onSelect: function() {},
-
- /**
- * APIProperty: onUnselect
- * {Function} Optional function to be called when a feature is unselected.
- * The function should expect to be called with a feature.
- */
- onUnselect: function() {},
-
- /**
- * Property: scope
- * {Object} The scope to use with the onBeforeSelect, onSelect, onUnselect
- * callbacks. If null the scope will be this control.
- */
- scope: null,
-
- /**
- * APIProperty: geometryTypes
- * {Array(String)} To restrict selecting to a limited set of geometry types,
- * send a list of strings corresponding to the geometry class names.
- */
- geometryTypes: null,
-
- /**
- * Property: layer
- * {<OpenLayers.Layer.Vector>} The vector layer with a common renderer
- * root for all layers this control is configured with (if an array of
- * layers was passed to the constructor), or the vector layer the control
- * was configured with (if a single layer was passed to the constructor).
- */
- layer: null,
-
- /**
- * Property: layers
- * {Array(<OpenLayers.Layer.Vector>)} The layers this control will work on,
- * or null if the control was configured with a single layer
- */
- layers: null,
-
- /**
- * APIProperty: callbacks
- * {Object} The functions that are sent to the handlers.feature for callback
- */
- callbacks: null,
-
- /**
- * APIProperty: selectStyle
- * {Object} Hash of styles
- */
- selectStyle: null,
-
- /**
- * Property: renderIntent
- * {String} key used to retrieve the select style from the layer's
- * style map.
- */
- renderIntent: "select",
-
- /**
- * Property: handlers
- * {Object} Object with references to multiple <OpenLayers.Handler>
- * instances.
- */
- handlers: null,
-
- /**
- * Constructor: OpenLayers.Control.SelectFeature
- * Create a new control for selecting features.
- *
- * Parameters:
- * layers - {<OpenLayers.Layer.Vector>}, or an array of vector layers. The
- * layer(s) this control will select features from.
- * options - {Object}
- */
- initialize: function(layers, options) {
- OpenLayers.Control.prototype.initialize.apply(this, [options]);
-
- if(this.scope === null) {
- this.scope = this;
+ var pointList = parser.getPointList(ways[ref], nodes);
+ if (pointList.length == 0) {
+ continue;
}
- this.initLayer(layers);
- var callbacks = {
- click: this.clickFeature,
- clickout: this.clickoutFeature
- };
- if (this.hover) {
- callbacks.over = this.overFeature;
- callbacks.out = this.outFeature;
+ var newPath = true;
+ if (lastRole == '') {
+ lastRole = role;
}
-
- this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks);
- this.handlers = {
- feature: new OpenLayers.Handler.Feature(
- this, this.layer, this.callbacks,
- {geometryTypes: this.geometryTypes}
- )
- };
-
- if (this.box) {
- this.handlers.box = new OpenLayers.Handler.Box(
- this, {done: this.selectBox},
- {boxDivClassName: "olHandlerBoxSelectFeature"}
- );
- }
- },
-
- /**
- * Method: initLayer
- * Assign the layer property. If layers is an array, we need to use
- * a RootContainer.
- *
- * Parameters:
- * layers - {<OpenLayers.Layer.Vector>}, or an array of vector layers.
- */
- initLayer: function(layers) {
- if(OpenLayers.Util.isArray(layers)) {
- this.layers = layers;
- this.layer = new OpenLayers.Layer.Vector.RootContainer(
- this.id + "_container", {
- layers: layers
- }
- );
- } else {
- this.layer = layers;
- }
- },
-
- /**
- * Method: destroy
- */
- destroy: function() {
- if(this.active && this.layers) {
- this.map.removeLayer(this.layer);
- }
- OpenLayers.Control.prototype.destroy.apply(this, arguments);
- if(this.layers) {
- this.layer.destroy();
- }
- },
-
- /**
- * Method: activate
- * Activates the control.
- *
- * Returns:
- * {Boolean} The control was effectively activated.
- */
- activate: function () {
- if (!this.active) {
- if(this.layers) {
- this.map.addLayer(this.layer);
+ if (lastRole == role) {
+ var result = parser.concatPathsIfLinear(lastPointList, pointList);
+ if (result.succed) {
+ newPath = false;
+ lastPointList = result.lastPointList;
}
- this.handlers.feature.activate();
- if(this.box && this.handlers.box) {
- this.handlers.box.activate();
- }
}
- return OpenLayers.Control.prototype.activate.apply(
- this, arguments
- );
- },
-
- /**
- * Method: deactivate
- * Deactivates the control.
- *
- * Returns:
- * {Boolean} The control was effectively deactivated.
- */
- deactivate: function () {
- if (this.active) {
- this.handlers.feature.deactivate();
- if(this.handlers.box) {
- this.handlers.box.deactivate();
+ if (newPath) {
+ var geometry = new OpenLayers.Geometry.LineString(lastPointList)
+ var feat = new OpenLayers.Feature.Vector(geometry, relation.tags);
+ if (role) {
+ feat.attributes.role = role;
}
- if(this.layers) {
- this.map.removeLayer(this.layer);
- }
+ feat.osm_id = parseInt(relation.id);
+ feat.type = "relation";
+ feat.fid = "relation." + feat.osm_id + "." + j;
+ features.push(feat);
+ lastPointList = pointList;
+ lastRole = role;
}
- return OpenLayers.Control.prototype.deactivate.apply(
- this, arguments
- );
- },
-
- /**
- * Method: unselectAll
- * Unselect all selected features. To unselect all except for a single
- * feature, set the options.except property to the feature.
- *
- * Parameters:
- * options - {Object} Optional configuration object.
- */
- unselectAll: function(options) {
- // we'll want an option to supress notification here
- var layers = this.layers || [this.layer],
- layer, feature, l, numExcept;
- for(l=0; l<layers.length; ++l) {
- layer = layers[l];
- numExcept = 0;
- //layer.selectedFeatures is null when layer is destroyed and
- //one of it's preremovelayer listener calls setLayer
- //with another layer on this control
- if(layer.selectedFeatures != null) {
- while(layer.selectedFeatures.length > numExcept) {
- feature = layer.selectedFeatures[numExcept];
- if(!options || options.except != feature) {
- this.unselect(feature);
- } else {
- ++numExcept;
- }
- }
- }
- }
- },
-
- /**
- * Method: clickFeature
- * Called on click in a feature
- * Only responds if this.hover is false.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- clickFeature: function(feature) {
- if(!this.hover) {
- var selected = (OpenLayers.Util.indexOf(
- feature.layer.selectedFeatures, feature) > -1);
- if(selected) {
- if(this.toggleSelect()) {
- this.unselect(feature);
- } else if(!this.multipleSelect()) {
- this.unselectAll({except: feature});
- }
- } else {
- if(!this.multipleSelect()) {
- this.unselectAll({except: feature});
- }
- this.select(feature);
- }
- }
- },
-
- /**
- * Method: multipleSelect
- * Allow for multiple selected features based on <multiple> property and
- * <multipleKey> event modifier.
- *
- * Returns:
- * {Boolean} Allow for multiple selected features.
- */
- multipleSelect: function() {
- return this.multiple || (this.handlers.feature.evt &&
- this.handlers.feature.evt[this.multipleKey]);
- },
-
- /**
- * Method: toggleSelect
- * Event should toggle the selected state of a feature based on <toggle>
- * property and <toggleKey> event modifier.
- *
- * Returns:
- * {Boolean} Toggle the selected state of a feature.
- */
- toggleSelect: function() {
- return this.toggle || (this.handlers.feature.evt &&
- this.handlers.feature.evt[this.toggleKey]);
- },
-
- /**
- * Method: clickoutFeature
- * Called on click outside a previously clicked (selected) feature.
- * Only responds if this.hover is false.
- *
- * Parameters:
- * feature - {<OpenLayers.Vector.Feature>}
- */
- clickoutFeature: function(feature) {
- if(!this.hover && this.clickout) {
- this.unselectAll();
- }
- },
-
- /**
- * Method: overFeature
- * Called on over a feature.
- * Only responds if this.hover is true.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- overFeature: function(feature) {
- var layer = feature.layer;
- if(this.hover) {
- if(this.highlightOnly) {
- this.highlight(feature);
- } else if(OpenLayers.Util.indexOf(
- layer.selectedFeatures, feature) == -1) {
- this.select(feature);
- }
- }
- },
-
- /**
- * Method: outFeature
- * Called on out of a selected feature.
- * Only responds if this.hover is true.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- outFeature: function(feature) {
- if(this.hover) {
- if(this.highlightOnly) {
- // we do nothing if we're not the last highlighter of the
- // feature
- if(feature._lastHighlighter == this.id) {
- // if another select control had highlighted the feature before
- // we did it ourself then we use that control to highlight the
- // feature as it was before we highlighted it, else we just
- // unhighlight it
- if(feature._prevHighlighter &&
- feature._prevHighlighter != this.id) {
- delete feature._lastHighlighter;
- var control = this.map.getControl(
- feature._prevHighlighter);
- if(control) {
- control.highlight(feature);
- }
- } else {
- this.unhighlight(feature);
- }
- }
- } else {
- this.unselect(feature);
- }
- }
- },
-
- /**
- * Method: highlight
- * Redraw feature with the select style.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- highlight: function(feature) {
- var layer = feature.layer;
- var cont = this.events.triggerEvent("beforefeaturehighlighted", {
- feature : feature
- });
- if(cont !== false) {
- feature._prevHighlighter = feature._lastHighlighter;
- feature._lastHighlighter = this.id;
- var style = this.selectStyle || this.renderIntent;
- layer.drawFeature(feature, style);
- this.events.triggerEvent("featurehighlighted", {feature : feature});
- }
- },
-
- /**
- * Method: unhighlight
- * Redraw feature with the "default" style
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- unhighlight: function(feature) {
- var layer = feature.layer;
- // three cases:
- // 1. there's no other highlighter, in that case _prev is undefined,
- // and we just need to undef _last
- // 2. another control highlighted the feature after we did it, in
- // that case _last references this other control, and we just
- // need to undef _prev
- // 3. another control highlighted the feature before we did it, in
- // that case _prev references this other control, and we need to
- // set _last to _prev and undef _prev
- if(feature._prevHighlighter == undefined) {
- delete feature._lastHighlighter;
- } else if(feature._prevHighlighter == this.id) {
- delete feature._prevHighlighter;
- } else {
- feature._lastHighlighter = feature._prevHighlighter;
- delete feature._prevHighlighter;
- }
- layer.drawFeature(feature, feature.style || feature.layer.style ||
- "default");
- this.events.triggerEvent("featureunhighlighted", {feature : feature});
- },
-
- /**
- * Method: select
- * Add feature to the layer's selectedFeature array, render the feature as
- * selected, and call the onSelect function.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- select: function(feature) {
- var cont = this.onBeforeSelect.call(this.scope, feature);
- var layer = feature.layer;
- if(cont !== false) {
- cont = layer.events.triggerEvent("beforefeatureselected", {
- feature: feature
- });
- if(cont !== false) {
- layer.selectedFeatures.push(feature);
- this.highlight(feature);
- // if the feature handler isn't involved in the feature
- // selection (because the box handler is used or the
- // feature is selected programatically) we fake the
- // feature handler to allow unselecting on click
- if(!this.handlers.feature.lastFeature) {
- this.handlers.feature.lastFeature = layer.selectedFeatures[0];
- }
- layer.events.triggerEvent("featureselected", {feature: feature});
- this.onSelect.call(this.scope, feature);
- }
- }
- },
-
- /**
- * Method: unselect
- * Remove feature from the layer's selectedFeature array, render the feature as
- * normal, and call the onUnselect function.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- */
- unselect: function(feature) {
- var layer = feature.layer;
- // Store feature style for restoration later
- this.unhighlight(feature);
- OpenLayers.Util.removeItem(layer.selectedFeatures, feature);
- layer.events.triggerEvent("featureunselected", {feature: feature});
- this.onUnselect.call(this.scope, feature);
- },
-
- /**
- * Method: selectBox
- * Callback from the handlers.box set up when <box> selection is true
- * on.
- *
- * Parameters:
- * position - {<OpenLayers.Bounds> || <OpenLayers.Pixel> }
- */
- selectBox: function(position) {
- if (position instanceof OpenLayers.Bounds) {
- var minXY = this.map.getLonLatFromPixel({
- x: position.left,
- y: position.bottom
- });
- var maxXY = this.map.getLonLatFromPixel({
- x: position.right,
- y: position.top
- });
- var bounds = new OpenLayers.Bounds(
- minXY.lon, minXY.lat, maxXY.lon, maxXY.lat
- );
-
- // if multiple is false, first deselect currently selected features
- if (!this.multipleSelect()) {
- this.unselectAll();
- }
-
- // because we're using a box, we consider we want multiple selection
- var prevMultiple = this.multiple;
- this.multiple = true;
- var layers = this.layers || [this.layer];
- this.events.triggerEvent("boxselectionstart", {layers: layers});
- var layer;
- for(var l=0; l<layers.length; ++l) {
- layer = layers[l];
- for(var i=0, len = layer.features.length; i<len; ++i) {
- var feature = layer.features[i];
- // check if the feature is displayed
- if (!feature.getVisibility()) {
- continue;
- }
-
- if (this.geometryTypes == null || OpenLayers.Util.indexOf(
- this.geometryTypes, feature.geometry.CLASS_NAME) > -1) {
- if (bounds.toGeometry().intersects(feature.geometry)) {
- if (OpenLayers.Util.indexOf(layer.selectedFeatures, feature) == -1) {
- this.select(feature);
- }
- }
- }
- }
- }
- this.multiple = prevMultiple;
- this.events.triggerEvent("boxselectionend", {layers: layers});
- }
- },
-
- /**
- * Method: setMap
- * Set the map property for the control.
- *
- * Parameters:
- * map - {<OpenLayers.Map>}
- */
- setMap: function(map) {
- this.handlers.feature.setMap(map);
- if (this.box) {
- this.handlers.box.setMap(map);
- }
- OpenLayers.Control.prototype.setMap.apply(this, arguments);
- },
-
- /**
- * APIMethod: setLayer
- * Attach a new layer to the control, overriding any existing layers.
- *
- * Parameters:
- * layers - Array of {<OpenLayers.Layer.Vector>} or a single
- * {<OpenLayers.Layer.Vector>}
- */
- setLayer: function(layers) {
- var isActive = this.active;
- this.unselectAll();
- this.deactivate();
- if(this.layers) {
- this.layer.destroy();
- this.layers = null;
- }
- this.initLayer(layers);
- this.handlers.feature.layer = this.layer;
- if (isActive) {
- this.activate();
- }
- },
-
- CLASS_NAME: "OpenLayers.Control.SelectFeature"
-});
+ }
+ var geometry = new OpenLayers.Geometry.LineString(lastPointList)
+ var feat = new OpenLayers.Feature.Vector(geometry, relation.tags);
+ if (role) {
+ feat.attributes.role = role;
+ }
+ feat.osm_id = parseInt(relation.id);
+ feat.type = "relation";
+ feat.fid = "relation." + feat.osm_id;
+ features.push(feat);
+ return features;
+}
/* ======================================================================
OpenLayers/Handler/Keyboard.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -43485,18 +42256,18 @@
});
/* ======================================================================
OpenLayers/Control/ModifyFeature.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Control/DragFeature.js
- * @requires OpenLayers/Control/SelectFeature.js
+ * @requires OpenLayers/Control.js
+ * @requires OpenLayers/Handler/Drag.js
* @requires OpenLayers/Handler/Keyboard.js
*/
/**
* Class: OpenLayers.Control.ModifyFeature
@@ -43510,10 +42281,20 @@
* - <OpenLayers.Control>
*/
OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, {
/**
+ * APIProperty: bySegment
+ * {Boolean} If set to true, one segment at a time will be editable (the
+ * one under the mouse cursor on hover). This supports editing much
+ * larger geometries. This requires the rbush library
+ * (https://github.com/mourner/rbush) for spatial indexing. Default is
+ * false.
+ */
+ bySegment: false,
+
+ /**
* APIProperty: documentDrag
* {Boolean} If set to true, dragging vertices will continue even if the
* mouse cursor leaves the map viewport. Default is false.
*/
documentDrag: false,
@@ -43537,11 +42318,11 @@
* APIProperty: toggle
* {Boolean} Unselect a selected feature on click.
* Default is true.
*/
toggle: true,
-
+
/**
* APIProperty: standalone
* {Boolean} Set to true to create a control without SelectFeature
* capabilities. Default is false. If standalone is true, to modify
* a feature, call the <selectFeature> method with the target feature.
@@ -43554,49 +42335,43 @@
/**
* Property: layer
* {<OpenLayers.Layer.Vector>}
*/
layer: null,
-
+
/**
* Property: feature
* {<OpenLayers.Feature.Vector>} Feature currently available for modification.
*/
feature: null,
-
+
/**
+ * Property: vertex
+ * {<OpenLayers.Feature.Vector>} Vertex currently being modified.
+ */
+ vertex: null,
+
+ /**
* Property: vertices
* {Array(<OpenLayers.Feature.Vector>)} Verticies currently available
* for dragging.
*/
vertices: null,
-
+
/**
* Property: virtualVertices
* {Array(<OpenLayers.Feature.Vector>)} Virtual vertices in the middle
* of each edge.
*/
virtualVertices: null,
/**
- * Property: selectControl
- * {<OpenLayers.Control.SelectFeature>}
- */
- selectControl: null,
-
- /**
- * Property: dragControl
- * {<OpenLayers.Control.DragFeature>}
- */
- dragControl: null,
-
- /**
* Property: handlers
* {Object}
*/
handlers: null,
-
+
/**
* APIProperty: deleteCodes
* {Array(Integer)} Keycodes for deleting verticies. Set to null to disable
* vertex deltion by keypress. If non-null, keypresses with codes
* in this array will delete vertices under the mouse. Default
@@ -43607,11 +42382,11 @@
/**
* APIProperty: virtualStyle
* {Object} A symbolizer to be used for virtual vertices.
*/
virtualStyle: null,
-
+
/**
* APIProperty: vertexRenderIntent
* {String} The renderIntent to use for vertices. If no <virtualStyle> is
* provided, this renderIntent will also be used for virtual vertices, with
* a fillOpacity and strokeOpacity of 0.3. Default is null, which means
@@ -43719,79 +42494,111 @@
this.mode = OpenLayers.Control.ModifyFeature.RESHAPE;
OpenLayers.Control.prototype.initialize.apply(this, [options]);
if(!(OpenLayers.Util.isArray(this.deleteCodes))) {
this.deleteCodes = [this.deleteCodes];
}
- var control = this;
-
- // configure the select control
- var selectOptions = {
- geometryTypes: this.geometryTypes,
- clickout: this.clickout,
- toggle: this.toggle,
- onBeforeSelect: this.beforeSelectFeature,
- onSelect: this.selectFeature,
- onUnselect: this.unselectFeature,
- scope: this
- };
- if(this.standalone === false) {
- this.selectControl = new OpenLayers.Control.SelectFeature(
- layer, selectOptions
- );
- }
-
- // configure the drag control
- var dragOptions = {
- documentDrag: this.documentDrag,
- geometryTypes: ["OpenLayers.Geometry.Point"],
- onStart: function(feature, pixel) {
- control.dragStart.apply(control, [feature, pixel]);
+
+ // configure the drag handler
+ var dragCallbacks = {
+ down: function(pixel) {
+ this.vertex = null;
+ var feature = this.layer.getFeatureFromEvent(
+ this.handlers.drag.evt);
+ if (feature) {
+ this.dragStart(feature);
+ } else if (this.clickout) {
+ this._unselect = this.feature;
+ }
},
- onDrag: function(feature, pixel) {
- control.dragVertex.apply(control, [feature, pixel]);
+ move: function(pixel) {
+ delete this._unselect;
+ if (this.vertex) {
+ this.dragVertex(this.vertex, pixel);
+ }
},
- onComplete: function(feature) {
- control.dragComplete.apply(control, [feature]);
+ up: function() {
+ this.handlers.drag.stopDown = false;
+ if (this._unselect) {
+ this.unselectFeature(this._unselect);
+ delete this._unselect;
+ }
},
- featureCallbacks: {
- over: function(feature) {
- /**
- * In normal mode, the feature handler is set up to allow
- * dragging of all points. In standalone mode, we only
- * want to allow dragging of sketch vertices and virtual
- * vertices - or, in the case of a modifiable point, the
- * point itself.
- */
- if(control.standalone !== true || feature._sketch ||
- control.feature === feature) {
- control.dragControl.overFeature.apply(
- control.dragControl, [feature]);
- }
+ done: function(pixel) {
+ if (this.vertex) {
+ this.dragComplete(this.vertex);
}
}
};
- this.dragControl = new OpenLayers.Control.DragFeature(
- layer, dragOptions
- );
+ var _self = this;
+ var dragOptions = {
+ documentDrag: this.documentDrag,
+ setEvent: function(evt) {
+ var feature = _self.feature;
+ _self._lastVertex = feature ?
+ feature.layer.getFeatureFromEvent(evt) : null;
+ OpenLayers.Handler.Drag.prototype.setEvent.apply(
+ this, arguments);
+ },
+ stopDown: false
+ };
// configure the keyboard handler
var keyboardOptions = {
keydown: this.handleKeypress
};
this.handlers = {
- keyboard: new OpenLayers.Handler.Keyboard(this, keyboardOptions)
+ keyboard: new OpenLayers.Handler.Keyboard(this, keyboardOptions),
+ drag: new OpenLayers.Handler.Drag(this, dragCallbacks, dragOptions)
};
+
+ if (this.bySegment) {
+ if (!window.rbush) {
+ throw new Error("The rbush library is required");
+ }
+ if (!OpenLayers.Control.ModifyFeature.BySegment) {
+ throw new Error("OpenLayers.Control.ModifyFeature.BySegment is missing from the build");
+ } else {
+ OpenLayers.Util.extend(this, OpenLayers.Control.ModifyFeature.BySegment);
+ }
+ }
},
/**
+ * Method: createVirtualVertex
+ * Create a virtual vertex in the middle of the segment.
+ *
+ * Parameters:
+ * point1 - {<OpenLayers.Geometry.Point>} First point of the segment.
+ * point2 - {<OpenLayers.Geometry.Point>} Second point of the segment.
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>} The virtual vertex created.
+ */
+ createVirtualVertex: function(point1, point2) {
+ var x = (point1.x + point2.x) / 2;
+ var y = (point1.y + point2.y) / 2;
+ var point = new OpenLayers.Feature.Vector(
+ new OpenLayers.Geometry.Point(x, y),
+ null, this.virtualStyle
+ );
+ point._sketch = true;
+ return point;
+ },
+
+ /**
* APIMethod: destroy
* Take care of things that are not handled in superclass.
*/
destroy: function() {
+ if (this.map) {
+ this.map.events.un({
+ "removelayer": this.handleMapEvents,
+ "changelayer": this.handleMapEvents,
+ scope: this
+ });
+ }
this.layer = null;
- this.standalone || this.selectControl.destroy();
- this.dragControl.destroy();
OpenLayers.Control.prototype.destroy.apply(this, []);
},
/**
* APIMethod: activate
@@ -43799,13 +42606,22 @@
*
* Returns:
* {Boolean} Successfully activated the control.
*/
activate: function() {
- return ((this.standalone || this.selectControl.activate()) &&
- this.handlers.keyboard.activate() &&
- OpenLayers.Control.prototype.activate.apply(this, arguments));
+ if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
+ this.moveLayerToTop();
+ this.map.events.on({
+ "removelayer": this.handleMapEvents,
+ "changelayer": this.handleMapEvents,
+ scope: this
+ });
+ this._lastVertex = null;
+ return this.handlers.keyboard.activate() &&
+ this.handlers.drag.activate();
+ }
+ return false;
},
/**
* APIMethod: deactivate
* Deactivate the control.
@@ -43815,33 +42631,30 @@
*/
deactivate: function() {
var deactivated = false;
// the return from the controls is unimportant in this case
if(OpenLayers.Control.prototype.deactivate.apply(this, arguments)) {
+ this.moveLayerBack();
+ this.map.events.un({
+ "removelayer": this.handleMapEvents,
+ "changelayer": this.handleMapEvents,
+ scope: this
+ });
this.layer.removeFeatures(this.vertices, {silent: true});
this.layer.removeFeatures(this.virtualVertices, {silent: true});
this.vertices = [];
- this.dragControl.deactivate();
+ this.handlers.drag.deactivate();
+ this.handlers.keyboard.deactivate();
var feature = this.feature;
- var valid = feature && feature.geometry && feature.layer;
- if(this.standalone === false) {
- if(valid) {
- this.selectControl.unselect.apply(this.selectControl,
- [feature]);
- }
- this.selectControl.deactivate();
- } else {
- if(valid) {
- this.unselectFeature(feature);
- }
+ if (feature && feature.geometry && feature.layer) {
+ this.unselectFeature(feature);
}
- this.handlers.keyboard.deactivate();
deactivated = true;
}
return deactivated;
},
-
+
/**
* Method: beforeSelectFeature
* Called before a feature is selected.
*
* Parameters:
@@ -43854,23 +42667,32 @@
},
/**
* APIMethod: selectFeature
* Select a feature for modification in standalone mode. In non-standalone
- * mode, this method is called when the select feature control selects a
- * feature. Register a listener to the beforefeaturemodified event and
- * return false to prevent feature modification.
+ * mode, this method is called when a feature is selected by clicking.
+ * Register a listener to the beforefeaturemodified event and return false
+ * to prevent feature modification.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>} the selected feature.
*/
selectFeature: function(feature) {
- if (!this.standalone || this.beforeSelectFeature(feature) !== false) {
+ if (this.feature === feature ||
+ (this.geometryTypes && OpenLayers.Util.indexOf(this.geometryTypes,
+ feature.geometry.CLASS_NAME) == -1)) {
+ return;
+ }
+ if (this.beforeSelectFeature(feature) !== false) {
+ if (this.feature) {
+ this.unselectFeature(this.feature);
+ }
this.feature = feature;
+ this.layer.selectedFeatures.push(feature);
+ this.layer.drawFeature(feature, 'select');
this.modified = false;
this.resetVertices();
- this.dragControl.activate();
this.onModificationStart(this.feature);
}
// keep track of geometry modifications
var modified = feature.modified;
if (feature.geometry && !(modified && modified.geometry)) {
@@ -43896,77 +42718,63 @@
}
if(this.radiusHandle) {
this.layer.destroyFeatures([this.radiusHandle], {silent: true});
delete this.radiusHandle;
}
+ this.layer.drawFeature(this.feature, 'default');
this.feature = null;
- this.dragControl.deactivate();
+ OpenLayers.Util.removeItem(this.layer.selectedFeatures, feature);
this.onModificationEnd(feature);
this.layer.events.triggerEvent("afterfeaturemodified", {
feature: feature,
modified: this.modified
});
this.modified = false;
},
-
+
+
/**
* Method: dragStart
- * Called by the drag feature control with before a feature is dragged.
- * This method is used to differentiate between points and vertices
- * of higher order geometries. This respects the <geometryTypes>
- * property and forces a select of points when the drag control is
- * already active (and stops events from propagating to the select
- * control).
+ * Called by the drag handler before a feature is dragged. This method is
+ * used to differentiate between points and vertices
+ * of higher order geometries.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>} The point or vertex about to be
* dragged.
- * pixel - {<OpenLayers.Pixel>} Pixel location of the mouse event.
*/
- dragStart: function(feature, pixel) {
- // only change behavior if the feature is not in the vertices array
- if(feature != this.feature && !feature.geometry.parent &&
- feature != this.dragHandle && feature != this.radiusHandle) {
- if(this.standalone === false && this.feature) {
- // unselect the currently selected feature
- this.selectControl.clickFeature.apply(this.selectControl,
- [this.feature]);
+ dragStart: function(feature) {
+ var isPoint = feature.geometry.CLASS_NAME ==
+ 'OpenLayers.Geometry.Point';
+ if (!this.standalone &&
+ ((!feature._sketch && isPoint) || !feature._sketch)) {
+ if (this.toggle && this.feature === feature) {
+ // mark feature for unselection
+ this._unselect = feature;
}
- // check any constraints on the geometry type
- if(this.geometryTypes == null ||
- OpenLayers.Util.indexOf(this.geometryTypes,
- feature.geometry.CLASS_NAME) != -1) {
- // select the point
- this.standalone || this.selectControl.clickFeature.apply(
- this.selectControl, [feature]);
- /**
- * TBD: These lines improve workflow by letting the user
- * immediately start dragging after the mouse down.
- * However, it is very ugly to be messing with controls
- * and their handlers in this way. I'd like a better
- * solution if the workflow change is necessary.
- */
- // prepare the point for dragging
- this.dragControl.overFeature.apply(this.dragControl,
- [feature]);
- this.dragControl.lastPixel = pixel;
- this.dragControl.handlers.drag.started = true;
- this.dragControl.handlers.drag.start = pixel;
- this.dragControl.handlers.drag.last = pixel;
- }
+ this.selectFeature(feature);
}
+ if (this.feature &&
+ (feature._sketch || isPoint && feature === this.feature)) {
+ // feature is a drag or virtual handle or point
+ this.vertex = feature;
+ this.handlers.drag.stopDown = true;
+ }
},
-
+
/**
* Method: dragVertex
- * Called by the drag feature control with each drag move of a vertex.
+ * Called by the drag handler with each drag move of a vertex.
*
* Parameters:
* vertex - {<OpenLayers.Feature.Vector>} The vertex being dragged.
* pixel - {<OpenLayers.Pixel>} Pixel location of the mouse event.
*/
dragVertex: function(vertex, pixel) {
+ var pos = this.map.getLonLatFromViewPortPx(pixel);
+ var geom = vertex.geometry;
+ geom.move(pos.lon - geom.x, pos.lat - geom.y);
this.modified = true;
/**
* Five cases:
* 1) dragging a simple point
* 2) dragging a virtual vertex
@@ -43974,20 +42782,20 @@
* 4) dragging a real vertex
* 5) dragging a radius handle
*/
if(this.feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
// dragging a simple point
- if(this.feature != vertex) {
- this.feature = vertex;
- }
this.layer.events.triggerEvent("vertexmodified", {
vertex: vertex.geometry,
feature: this.feature,
pixel: pixel
});
} else {
if(vertex._index) {
+ if (vertex._index == -1) {
+ vertex._index = OpenLayers.Util.indexOf(vertex.geometry.parent.components, vertex._next);
+ }
// dragging a virtual vertex
vertex.geometry.parent.addComponent(vertex.geometry,
vertex._index);
// move from virtual to real vertex
delete vertex._index;
@@ -44013,21 +42821,21 @@
if(this.virtualVertices.length > 0) {
this.layer.destroyFeatures(this.virtualVertices, {silent: true});
this.virtualVertices = [];
}
this.layer.drawFeature(this.feature, this.standalone ? undefined :
- this.selectControl.renderIntent);
+ 'select');
}
// keep the vertex on top so it gets the mouseout after dragging
// this should be removed in favor of an option to draw under or
// maintain node z-index
this.layer.drawFeature(vertex);
},
-
+
/**
* Method: dragComplete
- * Called by the drag feature control when the feature dragging is complete.
+ * Called by the drag handler when the feature dragging is complete.
*
* Parameters:
* vertex - {<OpenLayers.Feature.Vector>} The vertex being dragged.
*/
dragComplete: function(vertex) {
@@ -44059,20 +42867,10 @@
/**
* Method: resetVertices
*/
resetVertices: function() {
- // if coming from a drag complete we're about to destroy the vertex
- // that was just dragged. For that reason, the drag feature control
- // will never detect a mouse-out on that vertex, meaning that the drag
- // handler won't be deactivated. This can cause errors because the drag
- // feature control still has a feature to drag but that feature is
- // destroyed. To prevent this, we call outFeature on the drag feature
- // control if the control actually has a feature to drag.
- if(this.dragControl.feature) {
- this.dragControl.outFeature(this.dragControl.feature);
- }
if(this.vertices.length > 0) {
this.layer.removeFeatures(this.vertices, {silent: true});
this.vertices = [];
}
if(this.virtualVertices.length > 0) {
@@ -44119,25 +42917,23 @@
var code = evt.keyCode;
// check for delete key
if(this.feature &&
OpenLayers.Util.indexOf(this.deleteCodes, code) != -1) {
- var vertex = this.dragControl.feature;
- if(vertex &&
- OpenLayers.Util.indexOf(this.vertices, vertex) != -1 &&
- !this.dragControl.handlers.drag.dragging &&
- vertex.geometry.parent) {
+ var vertex = this._lastVertex;
+ if (vertex &&
+ OpenLayers.Util.indexOf(this.vertices, vertex) != -1 &&
+ !this.handlers.drag.dragging && vertex.geometry.parent) {
// remove the vertex
vertex.geometry.parent.removeComponent(vertex.geometry);
this.layer.events.triggerEvent("vertexremoved", {
vertex: vertex.geometry,
feature: this.feature,
pixel: evt.xy
});
this.layer.drawFeature(this.feature, this.standalone ?
- undefined :
- this.selectControl.renderIntent);
+ undefined : 'select');
this.modified = true;
this.resetVertices();
this.setFeatureState();
this.onModification(this.feature);
this.layer.events.triggerEvent("featuremodified",
@@ -44184,20 +42980,14 @@
for(i=0, len=geometry.components.length; i<len-1; ++i) {
var prevVertex = geometry.components[i];
var nextVertex = geometry.components[i + 1];
if(prevVertex.CLASS_NAME == "OpenLayers.Geometry.Point" &&
nextVertex.CLASS_NAME == "OpenLayers.Geometry.Point") {
- var x = (prevVertex.x + nextVertex.x) / 2;
- var y = (prevVertex.y + nextVertex.y) / 2;
- var point = new OpenLayers.Feature.Vector(
- new OpenLayers.Geometry.Point(x, y),
- null, control.virtualStyle
- );
+ var point = control.createVirtualVertex.call(control, prevVertex, nextVertex);
// set the virtual parent and intended index
point.geometry.parent = geometry;
point._index = i + 1;
- point._sketch = true;
control.virtualVertices.push(point);
}
}
}
}
@@ -44287,15 +43077,53 @@
*
* Parameters:
* map - {<OpenLayers.Map>} The control's map.
*/
setMap: function(map) {
- this.standalone || this.selectControl.setMap(map);
- this.dragControl.setMap(map);
+ this.handlers.drag.setMap(map);
OpenLayers.Control.prototype.setMap.apply(this, arguments);
},
+ /**
+ * Method: handleMapEvents
+ *
+ * Parameters:
+ * evt - {Object}
+ */
+ handleMapEvents: function(evt) {
+ if (evt.type == "removelayer" || evt.property == "order") {
+ this.moveLayerToTop();
+ }
+ },
+
+ /**
+ * Method: moveLayerToTop
+ * Moves the layer for this handler to the top, so mouse events can reach
+ * it.
+ */
+ moveLayerToTop: function() {
+ var index = Math.max(this.map.Z_INDEX_BASE['Feature'] - 1,
+ this.layer.getZIndex()) + 1;
+ this.layer.setZIndex(index);
+
+ },
+
+ /**
+ * Method: moveLayerBack
+ * Moves the layer back to the position determined by the map's layers
+ * array.
+ */
+ moveLayerBack: function() {
+ var index = this.layer.getZIndex() - 1;
+ if (index >= this.map.Z_INDEX_BASE['Feature']) {
+ this.layer.setZIndex(index);
+ } else {
+ this.map.setLayerZIndex(this.layer,
+ this.map.getLayerIndex(this.layer));
+ }
+ },
+
CLASS_NAME: "OpenLayers.Control.ModifyFeature"
});
/**
* Constant: RESHAPE
@@ -44319,11 +43147,11 @@
OpenLayers.Control.ModifyFeature.DRAG = 8;
/* ======================================================================
OpenLayers/Layer/XYZ.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -44460,13 +43288,13 @@
* Returns:
* {Object} - an object with x, y and z properties.
*/
getXYZ: function(bounds) {
var res = this.getServerResolution();
- var x = Math.round((bounds.left - this.maxExtent.left) /
+ var x = Math.round((bounds.left - this.tileOrigin.lon) /
(res * this.tileSize.w));
- var y = Math.round((this.maxExtent.top - bounds.top) /
+ var y = Math.round((this.tileOrigin.lat - bounds.top) /
(res * this.tileSize.h));
var z = this.getServerZoom();
if (this.wrapDateLine) {
var limit = Math.pow(2, z);
@@ -44485,21 +43313,21 @@
*/
setMap: function(map) {
OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
if (!this.tileOrigin) {
this.tileOrigin = new OpenLayers.LonLat(this.maxExtent.left,
- this.maxExtent.bottom);
+ this.maxExtent.top);
}
},
CLASS_NAME: "OpenLayers.Layer.XYZ"
});
/* ======================================================================
OpenLayers/Layer/Bing.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -44745,11 +43573,11 @@
var res = metadata.resourceSets[0].resources[0];
var extent = this.map.getExtent().transform(
this.map.getProjectionObject(),
new OpenLayers.Projection("EPSG:4326")
);
- var providers = res.imageryProviders,
+ var providers = res.imageryProviders || [],
zoom = OpenLayers.Util.indexOf(this.serverResolutions,
this.getServerResolution()),
copyrights = "", provider, i, ii, j, jj, bbox, coverage;
for (i=0,ii=providers.length; i<ii; ++i) {
provider = providers[i];
@@ -44832,11 +43660,11 @@
};
/* ======================================================================
OpenLayers/Format/SOSGetFeatureOfInterest.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -45026,11 +43854,11 @@
});
/* ======================================================================
OpenLayers/Format/SOSGetObservation.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -45332,11 +44160,11 @@
});
/* ======================================================================
OpenLayers/Handler/MouseWheel.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -45366,10 +44194,18 @@
* Defaults to 0, meaning no interval.
*/
interval: 0,
/**
+ * Property: maxDelta
+ * {Integer} Maximum delta to collect before breaking from the current
+ * interval. In cumulative mode, this also limits the maximum delta
+ * returned from the handler. Default is Number.POSITIVE_INFINITY.
+ */
+ maxDelta: Number.POSITIVE_INFINITY,
+
+ /**
* Property: delta
* {Integer} When interval is set, delta collects the mousewheel z-deltas
* of the events that occur within the interval.
* See also the cumulative option
*/
@@ -45510,14 +44346,14 @@
} else if (e.detail) {
// detail in Firefox on OS X is 1/3 of Windows
// so force delta 1 / -1
delta = - (e.detail / Math.abs(e.detail));
}
- this.delta = this.delta + delta;
+ this.delta += delta;
- if(this.interval) {
- window.clearTimeout(this._timeoutId);
+ window.clearTimeout(this._timeoutId);
+ if(this.interval && Math.abs(this.delta) < this.maxDelta) {
// store e because window.event might change during delay
var evt = OpenLayers.Util.extend({}, e);
this._timeoutId = window.setTimeout(
OpenLayers.Function.bind(function(){
this.wheelZoom(evt);
@@ -45545,13 +44381,15 @@
this.delta = 0;
if (delta) {
e.xy = this.map.events.getMousePosition(e);
if (delta < 0) {
- this.callback("down", [e, this.cumulative ? delta : -1]);
+ this.callback("down",
+ [e, this.cumulative ? Math.max(-this.maxDelta, delta) : -1]);
} else {
- this.callback("up", [e, this.cumulative ? delta : 1]);
+ this.callback("up",
+ [e, this.cumulative ? Math.min(this.maxDelta, delta) : 1]);
}
}
},
/**
@@ -45590,11 +44428,11 @@
});
/* ======================================================================
OpenLayers/Format/WFST/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -45768,11 +44606,11 @@
});
/* ======================================================================
OpenLayers/Renderer/Elements.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -45980,20 +44818,17 @@
* Returns:
* {DOMElement} the node following the index passed in, or
* null.
*/
getNextElement: function(index) {
- var nextIndex = index + 1;
- if (nextIndex < this.order.length) {
- var nextElement = OpenLayers.Util.getElement(this.order[nextIndex]);
- if (nextElement == undefined) {
- nextElement = this.getNextElement(nextIndex);
- }
- return nextElement;
- } else {
- return null;
- }
+ for (var nextIndex = index + 1, nextElement = undefined;
+ (nextIndex < this.order.length) && (nextElement == undefined);
+ nextIndex++) {
+ nextElement = OpenLayers.Util.getElement(this.order[nextIndex]);
+ }
+
+ return nextElement || null;
},
CLASS_NAME: "OpenLayers.ElementsIndexer"
});
@@ -46825,11 +45660,11 @@
/* ======================================================================
OpenLayers/Control/ArgParser.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -47011,11 +45846,11 @@
});
/* ======================================================================
OpenLayers/Control/Permalink.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -47272,11 +46107,11 @@
});
/* ======================================================================
OpenLayers/Layer/TMS.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -47475,298 +46310,14 @@
},
CLASS_NAME: "OpenLayers.Layer.TMS"
});
/* ======================================================================
- OpenLayers/Format/WCSCapabilities.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/Format/XML/VersionedOGC.js
- */
-
-/**
- * Class: OpenLayers.Format.WCSCapabilities
- * Read WCS Capabilities.
- *
- * Inherits from:
- * - <OpenLayers.Format.XML.VersionedOGC>
- */
-OpenLayers.Format.WCSCapabilities = OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC, {
-
- /**
- * APIProperty: defaultVersion
- * {String} Version number to assume if none found. Default is "1.1.0".
- */
- defaultVersion: "1.1.0",
-
- /**
- * Constructor: OpenLayers.Format.WCSCapabilities
- * Create a new parser for WCS capabilities.
- *
- * Parameters:
- * options - {Object} An optional object whose properties will be set on
- * this instance.
- */
-
- /**
- * APIMethod: read
- * Read capabilities data from a string, and return a list of coverages.
- *
- * Parameters:
- * data - {String} or {DOMElement} data to read/parse.
- *
- * Returns:
- * {Array} List of named coverages.
- */
-
- CLASS_NAME: "OpenLayers.Format.WCSCapabilities"
-
-});
-/* ======================================================================
- OpenLayers/Format/WCSCapabilities/v1.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/Format/WCSCapabilities.js
- */
-
-/**
- * Class: OpenLayers.Format.WCSCapabilities.v1
- * Abstract class not to be instantiated directly.
- *
- * Inherits from:
- * - <OpenLayers.Format.XML>
- */
-OpenLayers.Format.WCSCapabilities.v1 = OpenLayers.Class(
- OpenLayers.Format.XML, {
-
- regExes: {
- trimSpace: (/^\s*|\s*$/g),
- splitSpace: (/\s+/)
- },
-
- /**
- * Property: defaultPrefix
- */
- defaultPrefix: "wcs",
-
- /**
- * APIMethod: read
- * Read capabilities data from a string, and return a list of coverages.
- *
- * Parameters:
- * data - {String} or {DOMElement} data to read/parse.
- *
- * Returns:
- * {Array} List of named coverages.
- */
- read: function(data) {
- if(typeof data == "string") {
- data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
- }
- var raw = data;
- if(data && data.nodeType == 9) {
- data = data.documentElement;
- }
- var capabilities = {};
- this.readNode(data, capabilities);
- return capabilities;
- },
-
- CLASS_NAME: "OpenLayers.Format.WCSCapabilities.v1"
-
-});
-/* ======================================================================
- OpenLayers/Format/WCSCapabilities/v1_0_0.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/Format/WCSCapabilities/v1.js
- * @requires OpenLayers/Format/GML/v3.js
- */
-
-/**
- * Class: OpenLayers.Format.WCSCapabilities/v1_0_0
- * Read WCS Capabilities version 1.0.0.
- *
- * Inherits from:
- * - <OpenLayers.Format.WCSCapabilities.v1>
- */
-OpenLayers.Format.WCSCapabilities.v1_0_0 = OpenLayers.Class(
- OpenLayers.Format.WCSCapabilities.v1, {
-
- /**
- * Constructor: OpenLayers.Format.WCSCapabilities.v1_0_0
- * Create a new parser for WCS capabilities version 1.0.0.
- *
- * Parameters:
- * options - {Object} An optional object whose properties will be set on
- * this instance.
- */
-
- /**
- * Property: namespaces
- * {Object} Mapping of namespace aliases to namespace URIs.
- */
- namespaces: {
- wcs: "http://www.opengis.net/wcs",
- xlink: "http://www.w3.org/1999/xlink",
- xsi: "http://www.w3.org/2001/XMLSchema-instance",
- ows: "http://www.opengis.net/ows"
- },
-
- /**
- * Property: errorProperty
- * {String} Which property of the returned object to check for in order to
- * determine whether or not parsing has failed. In the case that the
- * errorProperty is undefined on the returned object, the document will be
- * run through an OGCExceptionReport parser.
- */
- errorProperty: "service",
-
- /**
- * Property: readers
- * Contains public functions, grouped by namespace prefix, that will
- * be applied when a namespaced node is found matching the function
- * name. The function will be applied in the scope of this parser
- * with two arguments: the node being read and a context object passed
- * from the parent.
- */
- readers: {
- "wcs": {
- "WCS_Capabilities": function(node, obj) {
- this.readChildNodes(node, obj);
- },
- "Service": function(node, obj) {
- obj.service = {};
- this.readChildNodes(node, obj.service);
- },
- "name": function(node, service) {
- service.name = this.getChildValue(node);
- },
- "label": function(node, service) {
- service.label = this.getChildValue(node);
- },
- "keywords": function(node, service) {
- service.keywords = [];
- this.readChildNodes(node, service.keywords);
- },
- "keyword": function(node, keywords) {
- // Append the keyword to the keywords list
- keywords.push(this.getChildValue(node));
- },
- "responsibleParty": function(node, service) {
- service.responsibleParty = {};
- this.readChildNodes(node, service.responsibleParty);
- },
- "individualName": function(node, responsibleParty) {
- responsibleParty.individualName = this.getChildValue(node);
- },
- "organisationName": function(node, responsibleParty) {
- responsibleParty.organisationName = this.getChildValue(node);
- },
- "positionName": function(node, responsibleParty) {
- responsibleParty.positionName = this.getChildValue(node);
- },
- "contactInfo": function(node, responsibleParty) {
- responsibleParty.contactInfo = {};
- this.readChildNodes(node, responsibleParty.contactInfo);
- },
- "phone": function(node, contactInfo) {
- contactInfo.phone = {};
- this.readChildNodes(node, contactInfo.phone);
- },
- "voice": function(node, phone) {
- phone.voice = this.getChildValue(node);
- },
- "facsimile": function(node, phone) {
- phone.facsimile = this.getChildValue(node);
- },
- "address": function(node, contactInfo) {
- contactInfo.address = {};
- this.readChildNodes(node, contactInfo.address);
- },
- "deliveryPoint": function(node, address) {
- address.deliveryPoint = this.getChildValue(node);
- },
- "city": function(node, address) {
- address.city = this.getChildValue(node);
- },
- "postalCode": function(node, address) {
- address.postalCode = this.getChildValue(node);
- },
- "country": function(node, address) {
- address.country = this.getChildValue(node);
- },
- "electronicMailAddress": function(node, address) {
- address.electronicMailAddress = this.getChildValue(node);
- },
- "fees": function(node, service) {
- service.fees = this.getChildValue(node);
- },
- "accessConstraints": function(node, service) {
- service.accessConstraints = this.getChildValue(node);
- },
- "ContentMetadata": function(node, obj) {
- obj.contentMetadata = [];
- this.readChildNodes(node, obj.contentMetadata);
- },
- "CoverageOfferingBrief": function(node, contentMetadata) {
- var coverageOfferingBrief = {};
- this.readChildNodes(node, coverageOfferingBrief);
- contentMetadata.push(coverageOfferingBrief);
- },
- "name": function(node, coverageOfferingBrief) {
- coverageOfferingBrief.name = this.getChildValue(node);
- },
- "label": function(node, coverageOfferingBrief) {
- coverageOfferingBrief.label = this.getChildValue(node);
- },
- "lonLatEnvelope": function(node, coverageOfferingBrief) {
- var nodeList = this.getElementsByTagNameNS(node, "http://www.opengis.net/gml", "pos");
-
- // We expect two nodes here, to create the corners of a bounding box
- if(nodeList.length == 2) {
- var min = {};
- var max = {};
-
- OpenLayers.Format.GML.v3.prototype.readers["gml"].pos.apply(this, [nodeList[0], min]);
- OpenLayers.Format.GML.v3.prototype.readers["gml"].pos.apply(this, [nodeList[1], max]);
-
- coverageOfferingBrief.lonLatEnvelope = {};
- coverageOfferingBrief.lonLatEnvelope.srsName = node.getAttribute("srsName");
- coverageOfferingBrief.lonLatEnvelope.min = min.points[0];
- coverageOfferingBrief.lonLatEnvelope.max = max.points[0];
- }
- }
- }
- },
-
- CLASS_NAME: "OpenLayers.Format.WCSCapabilities.v1_0_0"
-
-});
-/* ======================================================================
OpenLayers/Strategy/Fixed.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -47806,11 +46357,12 @@
* Returns:
* {Boolean} True if the strategy was successfully activated or false if
* the strategy was already active.
*/
activate: function() {
- if(OpenLayers.Strategy.prototype.activate.apply(this, arguments)) {
+ var activated = OpenLayers.Strategy.prototype.activate.apply(this, arguments);
+ if(activated) {
this.layer.events.on({
"refresh": this.load,
scope: this
});
if(this.layer.visibility == true || this.preload) {
@@ -47819,13 +46371,12 @@
this.layer.events.on({
"visibilitychanged": this.load,
scope: this
});
}
- return true;
}
- return false;
+ return activated;
},
/**
* Method: deactivate
* Deactivate the strategy. Undo what is done in <activate>.
@@ -47854,40 +46405,43 @@
*/
load: function(options) {
var layer = this.layer;
layer.events.triggerEvent("loadstart", {filter: layer.filter});
layer.protocol.read(OpenLayers.Util.applyDefaults({
- callback: OpenLayers.Function.bind(this.merge, this,
- layer.map.getProjectionObject()),
- filter: layer.filter
+ callback: this.merge,
+ filter: layer.filter,
+ scope: this
}, options));
layer.events.un({
"visibilitychanged": this.load,
scope: this
});
},
/**
* Method: merge
* Add all features to the layer.
+ * If the layer projection differs from the map projection, features
+ * will be transformed from the layer projection to the map projection.
*
* Parameters:
- * mapProjection - {<OpenLayers.Projection>} the map projection
* resp - {<OpenLayers.Protocol.Response>} The response object passed
* by the protocol.
*/
- merge: function(mapProjection, resp) {
+ merge: function(resp) {
var layer = this.layer;
layer.destroyFeatures();
var features = resp.features;
if (features && features.length > 0) {
- if(!mapProjection.equals(layer.projection)) {
+ var remote = layer.projection;
+ var local = layer.map.getProjectionObject();
+ if(!local.equals(remote)) {
var geom;
for(var i=0, len=features.length; i<len; ++i) {
geom = features[i].geometry;
if(geom) {
- geom.transform(layer.projection, mapProjection);
+ geom.transform(remote, local);
}
}
}
layer.addFeatures(features);
}
@@ -47898,11 +46452,11 @@
});
/* ======================================================================
OpenLayers/Control/Zoom.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -48037,14 +46591,1190 @@
},
CLASS_NAME: "OpenLayers.Control.Zoom"
});
/* ======================================================================
+ 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 {<OpenLayers.Style>}, 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 - {<OpenLayers.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/Layer/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. */
+
+/**
+ * @requires OpenLayers/Layer.js
+ * @requires OpenLayers/Renderer.js
+ * @requires OpenLayers/StyleMap.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/Lang.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Vector
+ * Instances of OpenLayers.Layer.Vector are used to render vector data from
+ * a variety of sources. Create a new vector layer with the
+ * <OpenLayers.Layer.Vector> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Layer>
+ */
+OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
+
+ /**
+ * APIProperty: events
+ * {<OpenLayers.Events>}
+ *
+ * Register a listener for a particular event with the following syntax:
+ * (code)
+ * layer.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 layer.events.object.
+ * element - {DOMElement} A reference to layer.events.element.
+ *
+ * Supported map event types (in addition to those from <OpenLayers.Layer.events>):
+ * beforefeatureadded - Triggered before a feature is added. Listeners
+ * will receive an object with a *feature* property referencing the
+ * feature to be added. To stop the feature from being added, a
+ * listener should return false.
+ * beforefeaturesadded - Triggered before an array of features is added.
+ * Listeners will receive an object with a *features* property
+ * referencing the feature to be added. To stop the features from
+ * being added, a listener should return false.
+ * featureadded - Triggered after a feature is added. The event
+ * object passed to listeners will have a *feature* property with a
+ * reference to the added feature.
+ * featuresadded - Triggered after features are added. The event
+ * object passed to listeners will have a *features* property with a
+ * reference to an array of added features.
+ * beforefeatureremoved - Triggered before a feature is removed. Listeners
+ * will receive an object with a *feature* property referencing the
+ * feature to be removed.
+ * beforefeaturesremoved - Triggered before multiple features are removed.
+ * Listeners will receive an object with a *features* property
+ * referencing the features to be removed.
+ * featureremoved - Triggerd after a feature is removed. The event
+ * object passed to listeners will have a *feature* property with a
+ * reference to the removed feature.
+ * featuresremoved - Triggered after features are removed. The event
+ * object passed to listeners will have a *features* property with a
+ * reference to an array of removed features.
+ * beforefeatureselected - Triggered before a feature is selected. Listeners
+ * will receive an object with a *feature* property referencing the
+ * feature to be selected. To stop the feature from being selectd, a
+ * listener should return false.
+ * featureselected - Triggered after a feature is selected. Listeners
+ * will receive an object with a *feature* property referencing the
+ * selected feature.
+ * featureunselected - Triggered after a feature is unselected.
+ * Listeners will receive an object with a *feature* property
+ * referencing the unselected feature.
+ * beforefeaturemodified - Triggered when a feature is selected to
+ * be modified. Listeners will receive an object with a *feature*
+ * property referencing the selected feature.
+ * featuremodified - Triggered when a feature has been modified.
+ * Listeners will receive an object with a *feature* property referencing
+ * the modified feature.
+ * afterfeaturemodified - Triggered when a feature is finished being modified.
+ * Listeners will receive an object with a *feature* property referencing
+ * the modified feature.
+ * vertexmodified - Triggered when a vertex within any feature geometry
+ * has been modified. Listeners will receive an object with a
+ * *feature* property referencing the modified feature, a *vertex*
+ * property referencing the vertex modified (always a point geometry),
+ * and a *pixel* property referencing the pixel location of the
+ * modification.
+ * vertexremoved - Triggered when a vertex within any feature geometry
+ * has been deleted. Listeners will receive an object with a
+ * *feature* property referencing the modified feature, a *vertex*
+ * property referencing the vertex modified (always a point geometry),
+ * and a *pixel* property referencing the pixel location of the
+ * removal.
+ * sketchstarted - Triggered when a feature sketch bound for this layer
+ * is started. Listeners will receive an object with a *feature*
+ * property referencing the new sketch feature and a *vertex* property
+ * referencing the creation point.
+ * sketchmodified - Triggered when a feature sketch bound for this layer
+ * is modified. Listeners will receive an object with a *vertex*
+ * property referencing the modified vertex and a *feature* property
+ * referencing the sketch feature.
+ * sketchcomplete - Triggered when a feature sketch bound for this layer
+ * is complete. Listeners will receive an object with a *feature*
+ * property referencing the sketch feature. By returning false, a
+ * listener can stop the sketch feature from being added to the layer.
+ * refresh - Triggered when something wants a strategy to ask the protocol
+ * for a new set of features.
+ */
+
+ /**
+ * APIProperty: isBaseLayer
+ * {Boolean} The layer is a base layer. Default is false. Set this property
+ * in the layer options.
+ */
+ isBaseLayer: false,
+
+ /**
+ * APIProperty: isFixed
+ * {Boolean} Whether the layer remains in one place while dragging the
+ * map. Note that setting this to true will move the layer to the bottom
+ * of the layer stack.
+ */
+ isFixed: false,
+
+ /**
+ * APIProperty: features
+ * {Array(<OpenLayers.Feature.Vector>)}
+ */
+ features: null,
+
+ /**
+ * Property: filter
+ * {<OpenLayers.Filter>} The filter set in this layer,
+ * a strategy launching read requests can combined
+ * this filter with its own filter.
+ */
+ filter: null,
+
+ /**
+ * Property: selectedFeatures
+ * {Array(<OpenLayers.Feature.Vector>)}
+ */
+ selectedFeatures: null,
+
+ /**
+ * Property: unrenderedFeatures
+ * {Object} hash of features, keyed by feature.id, that the renderer
+ * failed to draw
+ */
+ unrenderedFeatures: null,
+
+ /**
+ * APIProperty: reportError
+ * {Boolean} report friendly error message when loading of renderer
+ * fails.
+ */
+ reportError: true,
+
+ /**
+ * APIProperty: style
+ * {Object} Default style for the layer
+ */
+ style: null,
+
+ /**
+ * Property: styleMap
+ * {<OpenLayers.StyleMap>}
+ */
+ styleMap: null,
+
+ /**
+ * Property: strategies
+ * {Array(<OpenLayers.Strategy>})} Optional list of strategies for the layer.
+ */
+ strategies: null,
+
+ /**
+ * Property: protocol
+ * {<OpenLayers.Protocol>} Optional protocol for the layer.
+ */
+ protocol: null,
+
+ /**
+ * Property: renderers
+ * {Array(String)} List of supported Renderer classes. Add to this list to
+ * add support for additional renderers. This list is ordered:
+ * the first renderer which returns true for the 'supported()'
+ * method will be used, if not defined in the 'renderer' option.
+ */
+ renderers: ['SVG', 'VML', 'Canvas'],
+
+ /**
+ * Property: renderer
+ * {<OpenLayers.Renderer>}
+ */
+ renderer: null,
+
+ /**
+ * APIProperty: rendererOptions
+ * {Object} Options for the renderer. See {<OpenLayers.Renderer>} for
+ * supported options.
+ */
+ rendererOptions: null,
+
+ /**
+ * APIProperty: geometryType
+ * {String} geometryType allows you to limit the types of geometries this
+ * layer supports. This should be set to something like
+ * "OpenLayers.Geometry.Point" to limit types.
+ */
+ geometryType: null,
+
+ /**
+ * Property: drawn
+ * {Boolean} Whether the Vector Layer features have been drawn yet.
+ */
+ drawn: false,
+
+ /**
+ * APIProperty: ratio
+ * {Float} This specifies the ratio of the size of the visiblity of the Vector Layer features to the size of the map.
+ */
+ ratio: 1,
+
+ /**
+ * Constructor: OpenLayers.Layer.Vector
+ * Create a new vector layer
+ *
+ * Parameters:
+ * name - {String} A name for the layer
+ * options - {Object} Optional object with non-default properties to set on
+ * the layer.
+ *
+ * Returns:
+ * {<OpenLayers.Layer.Vector>} A new vector layer
+ */
+ initialize: function(name, options) {
+ OpenLayers.Layer.prototype.initialize.apply(this, arguments);
+
+ // allow user-set renderer, otherwise assign one
+ if (!this.renderer || !this.renderer.supported()) {
+ this.assignRenderer();
+ }
+
+ // if no valid renderer found, display error
+ if (!this.renderer || !this.renderer.supported()) {
+ this.renderer = null;
+ this.displayError();
+ }
+
+ if (!this.styleMap) {
+ this.styleMap = new OpenLayers.StyleMap();
+ }
+
+ this.features = [];
+ this.selectedFeatures = [];
+ this.unrenderedFeatures = {};
+
+ // Allow for custom layer behavior
+ if(this.strategies){
+ for(var i=0, len=this.strategies.length; i<len; i++) {
+ this.strategies[i].setLayer(this);
+ }
+ }
+
+ },
+
+ /**
+ * APIMethod: destroy
+ * Destroy this layer
+ */
+ destroy: function() {
+ if (this.strategies) {
+ var strategy, i, len;
+ for(i=0, len=this.strategies.length; i<len; i++) {
+ strategy = this.strategies[i];
+ if(strategy.autoDestroy) {
+ strategy.destroy();
+ }
+ }
+ this.strategies = null;
+ }
+ if (this.protocol) {
+ if(this.protocol.autoDestroy) {
+ this.protocol.destroy();
+ }
+ this.protocol = null;
+ }
+ this.destroyFeatures();
+ this.features = null;
+ this.selectedFeatures = null;
+ this.unrenderedFeatures = null;
+ if (this.renderer) {
+ this.renderer.destroy();
+ }
+ this.renderer = null;
+ this.geometryType = null;
+ this.drawn = null;
+ OpenLayers.Layer.prototype.destroy.apply(this, arguments);
+ },
+
+ /**
+ * Method: clone
+ * Create a clone of this layer.
+ *
+ * Note: Features of the layer are also cloned.
+ *
+ * Returns:
+ * {<OpenLayers.Layer.Vector>} An exact clone of this layer
+ */
+ clone: function (obj) {
+
+ if (obj == null) {
+ obj = new OpenLayers.Layer.Vector(this.name, this.getOptions());
+ }
+
+ //get all additions from superclasses
+ obj = OpenLayers.Layer.prototype.clone.apply(this, [obj]);
+
+ // copy/set any non-init, non-simple values here
+ var features = this.features;
+ var len = features.length;
+ var clonedFeatures = new Array(len);
+ for(var i=0; i<len; ++i) {
+ clonedFeatures[i] = features[i].clone();
+ }
+ obj.features = clonedFeatures;
+
+ return obj;
+ },
+
+ /**
+ * Method: refresh
+ * Ask the layer to request features again and redraw them. Triggers
+ * the refresh event if the layer is in range and visible.
+ *
+ * Parameters:
+ * obj - {Object} Optional object with properties for any listener of
+ * the refresh event.
+ */
+ refresh: function(obj) {
+ if(this.calculateInRange() && this.visibility) {
+ this.events.triggerEvent("refresh", obj);
+ }
+ },
+
+ /**
+ * Method: assignRenderer
+ * Iterates through the available renderer implementations and selects
+ * and assigns the first one whose "supported()" function returns true.
+ */
+ assignRenderer: function() {
+ for (var i=0, len=this.renderers.length; i<len; i++) {
+ var rendererClass = this.renderers[i];
+ var renderer = (typeof rendererClass == "function") ?
+ rendererClass :
+ OpenLayers.Renderer[rendererClass];
+ if (renderer && renderer.prototype.supported()) {
+ this.renderer = new renderer(this.div, this.rendererOptions);
+ break;
+ }
+ }
+ },
+
+ /**
+ * Method: displayError
+ * Let the user know their browser isn't supported.
+ */
+ displayError: function() {
+ if (this.reportError) {
+ OpenLayers.Console.userError(OpenLayers.i18n("browserNotSupported",
+ {renderers: this. renderers.join('\n')}));
+ }
+ },
+
+ /**
+ * Method: setMap
+ * The layer has been added to the map.
+ *
+ * If there is no renderer set, the layer can't be used. Remove it.
+ * Otherwise, give the renderer a reference to the map and set its size.
+ *
+ * Parameters:
+ * map - {<OpenLayers.Map>}
+ */
+ setMap: function(map) {
+ OpenLayers.Layer.prototype.setMap.apply(this, arguments);
+
+ if (!this.renderer) {
+ this.map.removeLayer(this);
+ } else {
+ this.renderer.map = this.map;
+
+ var newSize = this.map.getSize();
+ newSize.w = newSize.w * this.ratio;
+ newSize.h = newSize.h * this.ratio;
+ this.renderer.setSize(newSize);
+ }
+ },
+
+ /**
+ * Method: afterAdd
+ * Called at the end of the map.addLayer sequence. At this point, the map
+ * will have a base layer. Any autoActivate strategies will be
+ * activated here.
+ */
+ afterAdd: function() {
+ if(this.strategies) {
+ var strategy, i, len;
+ for(i=0, len=this.strategies.length; i<len; i++) {
+ strategy = this.strategies[i];
+ if(strategy.autoActivate) {
+ strategy.activate();
+ }
+ }
+ }
+ },
+
+ /**
+ * Method: removeMap
+ * The layer has been removed from the map.
+ *
+ * Parameters:
+ * map - {<OpenLayers.Map>}
+ */
+ removeMap: function(map) {
+ this.drawn = false;
+ if(this.strategies) {
+ var strategy, i, len;
+ for(i=0, len=this.strategies.length; i<len; i++) {
+ strategy = this.strategies[i];
+ if(strategy.autoActivate) {
+ strategy.deactivate();
+ }
+ }
+ }
+ },
+
+ /**
+ * Method: onMapResize
+ * Notify the renderer of the change in size.
+ *
+ */
+ onMapResize: function() {
+ OpenLayers.Layer.prototype.onMapResize.apply(this, arguments);
+
+ var newSize = this.map.getSize();
+ newSize.w = newSize.w * this.ratio;
+ newSize.h = newSize.h * this.ratio;
+ this.renderer.setSize(newSize);
+ },
+
+ /**
+ * Method: moveTo
+ * Reset the vector layer's div so that it once again is lined up with
+ * the map. Notify the renderer of the change of extent, and in the
+ * case of a change of zoom level (resolution), have the
+ * renderer redraw features.
+ *
+ * If the layer has not yet been drawn, cycle through the layer's
+ * features and draw each one.
+ *
+ * Parameters:
+ * bounds - {<OpenLayers.Bounds>}
+ * zoomChanged - {Boolean}
+ * dragging - {Boolean}
+ */
+ moveTo: function(bounds, zoomChanged, dragging) {
+ OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
+
+ var coordSysUnchanged = true;
+ if (!dragging) {
+ this.renderer.root.style.visibility = 'hidden';
+
+ var viewSize = this.map.getSize(),
+ viewWidth = viewSize.w,
+ viewHeight = viewSize.h,
+ offsetLeft = (viewWidth / 2 * this.ratio) - viewWidth / 2,
+ offsetTop = (viewHeight / 2 * this.ratio) - viewHeight / 2;
+ offsetLeft += this.map.layerContainerOriginPx.x;
+ offsetLeft = -Math.round(offsetLeft);
+ offsetTop += this.map.layerContainerOriginPx.y;
+ offsetTop = -Math.round(offsetTop);
+
+ this.div.style.left = offsetLeft + 'px';
+ this.div.style.top = offsetTop + 'px';
+
+ var extent = this.map.getExtent().scale(this.ratio);
+ coordSysUnchanged = this.renderer.setExtent(extent, zoomChanged);
+
+ this.renderer.root.style.visibility = 'visible';
+
+ // Force a reflow on gecko based browsers to prevent jump/flicker.
+ // This seems to happen on only certain configurations; it was originally
+ // noticed in FF 2.0 and Linux.
+ if (OpenLayers.IS_GECKO === true) {
+ this.div.scrollLeft = this.div.scrollLeft;
+ }
+
+ if (!zoomChanged && coordSysUnchanged) {
+ for (var i in this.unrenderedFeatures) {
+ var feature = this.unrenderedFeatures[i];
+ this.drawFeature(feature);
+ }
+ }
+ }
+ if (!this.drawn || zoomChanged || !coordSysUnchanged) {
+ this.drawn = true;
+ var feature;
+ for(var i=0, len=this.features.length; i<len; i++) {
+ this.renderer.locked = (i !== (len - 1));
+ feature = this.features[i];
+ this.drawFeature(feature);
+ }
+ }
+ },
+
+ /**
+ * APIMethod: display
+ * Hide or show the Layer
+ *
+ * Parameters:
+ * display - {Boolean}
+ */
+ display: function(display) {
+ OpenLayers.Layer.prototype.display.apply(this, arguments);
+ // we need to set the display style of the root in case it is attached
+ // to a foreign layer
+ var currentDisplay = this.div.style.display;
+ if(currentDisplay != this.renderer.root.style.display) {
+ this.renderer.root.style.display = currentDisplay;
+ }
+ },
+
+ /**
+ * APIMethod: addFeatures
+ * Add Features to the layer.
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)}
+ * options - {Object}
+ */
+ addFeatures: function(features, options) {
+ if (!(OpenLayers.Util.isArray(features))) {
+ features = [features];
+ }
+
+ var notify = !options || !options.silent;
+ if(notify) {
+ var event = {features: features};
+ var ret = this.events.triggerEvent("beforefeaturesadded", event);
+ if(ret === false) {
+ return;
+ }
+ features = event.features;
+ }
+
+ // Track successfully added features for featuresadded event, since
+ // beforefeatureadded can veto single features.
+ var featuresAdded = [];
+ for (var i=0, len=features.length; i<len; i++) {
+ if (i != (features.length - 1)) {
+ this.renderer.locked = true;
+ } else {
+ this.renderer.locked = false;
+ }
+ var feature = features[i];
+
+ if (this.geometryType &&
+ !(feature.geometry instanceof this.geometryType)) {
+ throw new TypeError('addFeatures: component should be an ' +
+ this.geometryType.prototype.CLASS_NAME);
+ }
+
+ //give feature reference to its layer
+ feature.layer = this;
+
+ if (!feature.style && this.style) {
+ feature.style = OpenLayers.Util.extend({}, this.style);
+ }
+
+ if (notify) {
+ if(this.events.triggerEvent("beforefeatureadded",
+ {feature: feature}) === false) {
+ continue;
+ }
+ this.preFeatureInsert(feature);
+ }
+
+ featuresAdded.push(feature);
+ this.features.push(feature);
+ this.drawFeature(feature);
+
+ if (notify) {
+ this.events.triggerEvent("featureadded", {
+ feature: feature
+ });
+ this.onFeatureInsert(feature);
+ }
+ }
+
+ if(notify) {
+ this.events.triggerEvent("featuresadded", {features: featuresAdded});
+ }
+ },
+
+
+ /**
+ * APIMethod: removeFeatures
+ * Remove features from the layer. This erases any drawn features and
+ * removes them from the layer's control. The beforefeatureremoved
+ * and featureremoved events will be triggered for each feature. The
+ * featuresremoved event will be triggered after all features have
+ * been removed. To supress event triggering, use the silent option.
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)} List of features to be
+ * removed.
+ * options - {Object} Optional properties for changing behavior of the
+ * removal.
+ *
+ * Valid options:
+ * silent - {Boolean} Supress event triggering. Default is false.
+ */
+ removeFeatures: function(features, options) {
+ if(!features || features.length === 0) {
+ return;
+ }
+ if (features === this.features) {
+ return this.removeAllFeatures(options);
+ }
+ if (!(OpenLayers.Util.isArray(features))) {
+ features = [features];
+ }
+ if (features === this.selectedFeatures) {
+ features = features.slice();
+ }
+
+ var notify = !options || !options.silent;
+
+ if (notify) {
+ this.events.triggerEvent(
+ "beforefeaturesremoved", {features: features}
+ );
+ }
+
+ for (var i = features.length - 1; i >= 0; i--) {
+ // We remain locked so long as we're not at 0
+ // and the 'next' feature has a geometry. We do the geometry check
+ // because if all the features after the current one are 'null', we
+ // won't call eraseGeometry, so we break the 'renderer functions
+ // will always be called with locked=false *last*' rule. The end result
+ // is a possible gratiutious unlocking to save a loop through the rest
+ // of the list checking the remaining features every time. So long as
+ // null geoms are rare, this is probably okay.
+ if (i != 0 && features[i-1].geometry) {
+ this.renderer.locked = true;
+ } else {
+ this.renderer.locked = false;
+ }
+
+ var feature = features[i];
+ delete this.unrenderedFeatures[feature.id];
+
+ if (notify) {
+ this.events.triggerEvent("beforefeatureremoved", {
+ feature: feature
+ });
+ }
+
+ this.features = OpenLayers.Util.removeItem(this.features, feature);
+ // feature has no layer at this point
+ feature.layer = null;
+
+ if (feature.geometry) {
+ this.renderer.eraseFeatures(feature);
+ }
+
+ //in the case that this feature is one of the selected features,
+ // remove it from that array as well.
+ if (OpenLayers.Util.indexOf(this.selectedFeatures, feature) != -1){
+ OpenLayers.Util.removeItem(this.selectedFeatures, feature);
+ }
+
+ if (notify) {
+ this.events.triggerEvent("featureremoved", {
+ feature: feature
+ });
+ }
+ }
+
+ if (notify) {
+ this.events.triggerEvent("featuresremoved", {features: features});
+ }
+ },
+
+ /**
+ * APIMethod: removeAllFeatures
+ * Remove all features from the layer.
+ *
+ * Parameters:
+ * options - {Object} Optional properties for changing behavior of the
+ * removal.
+ *
+ * Valid options:
+ * silent - {Boolean} Supress event triggering. Default is false.
+ */
+ removeAllFeatures: function(options) {
+ var notify = !options || !options.silent;
+ var features = this.features;
+ if (notify) {
+ this.events.triggerEvent(
+ "beforefeaturesremoved", {features: features}
+ );
+ }
+ var feature;
+ for (var i = features.length-1; i >= 0; i--) {
+ feature = features[i];
+ if (notify) {
+ this.events.triggerEvent("beforefeatureremoved", {
+ feature: feature
+ });
+ }
+ feature.layer = null;
+ if (notify) {
+ this.events.triggerEvent("featureremoved", {
+ feature: feature
+ });
+ }
+ }
+ this.renderer.clear();
+ this.features = [];
+ this.unrenderedFeatures = {};
+ this.selectedFeatures = [];
+ if (notify) {
+ this.events.triggerEvent("featuresremoved", {features: features});
+ }
+ },
+
+ /**
+ * APIMethod: destroyFeatures
+ * Erase and destroy features on the layer.
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)} An optional array of
+ * features to destroy. If not supplied, all features on the layer
+ * will be destroyed.
+ * options - {Object}
+ */
+ destroyFeatures: function(features, options) {
+ var all = (features == undefined); // evaluates to true if
+ // features is null
+ if(all) {
+ features = this.features;
+ }
+ if(features) {
+ this.removeFeatures(features, options);
+ for(var i=features.length-1; i>=0; i--) {
+ features[i].destroy();
+ }
+ }
+ },
+
+ /**
+ * APIMethod: drawFeature
+ * Draw (or redraw) a feature on the layer. If the optional style argument
+ * is included, this style will be used. If no style is included, the
+ * feature's style will be used. If the feature doesn't have a style,
+ * the layer's style will be used.
+ *
+ * This function is not designed to be used when adding features to
+ * the layer (use addFeatures instead). It is meant to be used when
+ * the style of a feature has changed, or in some other way needs to
+ * visually updated *after* it has already been added to a layer. You
+ * must add the feature to the layer for most layer-related events to
+ * happen.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ * style - {String | Object} Named render intent or full symbolizer object.
+ */
+ drawFeature: function(feature, style) {
+ // don't try to draw the feature with the renderer if the layer is not
+ // drawn itself
+ if (!this.drawn) {
+ return;
+ }
+ if (typeof style != "object") {
+ if(!style && feature.state === OpenLayers.State.DELETE) {
+ style = "delete";
+ }
+ var renderIntent = style || feature.renderIntent;
+ style = feature.style || this.style;
+ if (!style) {
+ style = this.styleMap.createSymbolizer(feature, renderIntent);
+ }
+ }
+
+ var drawn = this.renderer.drawFeature(feature, style);
+ //TODO remove the check for null when we get rid of Renderer.SVG
+ if (drawn === false || drawn === null) {
+ this.unrenderedFeatures[feature.id] = feature;
+ } else {
+ delete this.unrenderedFeatures[feature.id];
+ }
+ },
+
+ /**
+ * Method: eraseFeatures
+ * Erase features from the layer.
+ *
+ * Parameters:
+ * features - {Array(<OpenLayers.Feature.Vector>)}
+ */
+ eraseFeatures: function(features) {
+ this.renderer.eraseFeatures(features);
+ },
+
+ /**
+ * Method: getFeatureFromEvent
+ * Given an event, return a feature if the event occurred over one.
+ * Otherwise, return null.
+ *
+ * Parameters:
+ * evt - {Event}
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>} A feature if one was under the event.
+ */
+ getFeatureFromEvent: function(evt) {
+ if (!this.renderer) {
+ throw new Error('getFeatureFromEvent called on layer with no ' +
+ 'renderer. This usually means you destroyed a ' +
+ 'layer, but not some handler which is associated ' +
+ 'with it.');
+ }
+ var feature = null;
+ var featureId = this.renderer.getFeatureIdFromEvent(evt);
+ if (featureId) {
+ if (typeof featureId === "string") {
+ feature = this.getFeatureById(featureId);
+ } else {
+ feature = featureId;
+ }
+ }
+ return feature;
+ },
+
+ /**
+ * APIMethod: getFeatureBy
+ * Given a property value, return the feature if it exists in the features array
+ *
+ * Parameters:
+ * property - {String}
+ * value - {String}
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
+ * property value or null if there is no such feature.
+ */
+ getFeatureBy: function(property, value) {
+ //TBD - would it be more efficient to use a hash for this.features?
+ var feature = null;
+ for(var i=0, len=this.features.length; i<len; ++i) {
+ if(this.features[i][property] == value) {
+ feature = this.features[i];
+ break;
+ }
+ }
+ return feature;
+ },
+
+ /**
+ * APIMethod: getFeatureById
+ * Given a feature id, return the feature if it exists in the features array
+ *
+ * Parameters:
+ * featureId - {String}
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
+ * featureId or null if there is no such feature.
+ */
+ getFeatureById: function(featureId) {
+ return this.getFeatureBy('id', featureId);
+ },
+
+ /**
+ * APIMethod: getFeatureByFid
+ * Given a feature fid, return the feature if it exists in the features array
+ *
+ * Parameters:
+ * featureFid - {String}
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>} A feature corresponding to the given
+ * featureFid or null if there is no such feature.
+ */
+ getFeatureByFid: function(featureFid) {
+ return this.getFeatureBy('fid', featureFid);
+ },
+
+ /**
+ * APIMethod: getFeaturesByAttribute
+ * Returns an array of features that have the given attribute key set to the
+ * given value. Comparison of attribute values takes care of datatypes, e.g.
+ * the string '1234' is not equal to the number 1234.
+ *
+ * Parameters:
+ * attrName - {String}
+ * attrValue - {Mixed}
+ *
+ * Returns:
+ * Array({<OpenLayers.Feature.Vector>}) An array of features that have the
+ * passed named attribute set to the given value.
+ */
+ getFeaturesByAttribute: function(attrName, attrValue) {
+ var i,
+ feature,
+ len = this.features.length,
+ foundFeatures = [];
+ for(i = 0; i < len; i++) {
+ feature = this.features[i];
+ if(feature && feature.attributes) {
+ if (feature.attributes[attrName] === attrValue) {
+ foundFeatures.push(feature);
+ }
+ }
+ }
+ return foundFeatures;
+ },
+
+ /**
+ * Unselect the selected features
+ * i.e. clears the featureSelection array
+ * change the style back
+ clearSelection: function() {
+
+ var vectorLayer = this.map.vectorLayer;
+ for (var i = 0; i < this.map.featureSelection.length; i++) {
+ var featureSelection = this.map.featureSelection[i];
+ vectorLayer.drawFeature(featureSelection, vectorLayer.style);
+ }
+ this.map.featureSelection = [];
+ },
+ */
+
+
+ /**
+ * APIMethod: onFeatureInsert
+ * method called after a feature is inserted.
+ * Does nothing by default. Override this if you
+ * need to do something on feature updates.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ onFeatureInsert: function(feature) {
+ },
+
+ /**
+ * APIMethod: preFeatureInsert
+ * method called before a feature is inserted.
+ * Does nothing by default. Override this if you
+ * need to do something when features are first added to the
+ * layer, but before they are drawn, such as adjust the style.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ preFeatureInsert: function(feature) {
+ },
+
+ /**
+ * APIMethod: getDataExtent
+ * Calculates the max extent which includes all of the features.
+ *
+ * Returns:
+ * {<OpenLayers.Bounds>} or null if the layer has no features with
+ * geometries.
+ */
+ getDataExtent: function () {
+ var maxExtent = null;
+ var features = this.features;
+ if(features && (features.length > 0)) {
+ var geometry = null;
+ for(var i=0, len=features.length; i<len; i++) {
+ geometry = features[i].geometry;
+ if (geometry) {
+ if (maxExtent === null) {
+ maxExtent = new OpenLayers.Bounds();
+ }
+ maxExtent.extend(geometry.getBounds());
+ }
+ }
+ }
+ return maxExtent;
+ },
+
+ CLASS_NAME: "OpenLayers.Layer.Vector"
+});
+/* ======================================================================
OpenLayers/Layer/PointTrack.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -48169,11 +47899,11 @@
OpenLayers.Layer.PointTrack.dataFrom = {'SOURCE_NODE': -1, 'TARGET_NODE': 0};
/* ======================================================================
OpenLayers/Protocol.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -48464,11 +48194,11 @@
OpenLayers.Protocol.Response.FAILURE = 0;
/* ======================================================================
OpenLayers/Protocol/WFS.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -48554,11 +48284,11 @@
};
/* ======================================================================
OpenLayers/Layer/Markers.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -48745,11 +48475,11 @@
});
/* ======================================================================
OpenLayers/Control/Pan.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -48844,11 +48574,11 @@
OpenLayers.Control.Pan.WEST = "West";
/* ======================================================================
OpenLayers/Format/CSWGetDomain.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -48882,11 +48612,11 @@
};
/* ======================================================================
OpenLayers/Format/CSWGetDomain/v2_0_2.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -49126,11 +48856,11 @@
});
/* ======================================================================
OpenLayers/Format/ArcXML/Features.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -49176,11 +48906,11 @@
});
/* ======================================================================
OpenLayers/Control/Snapping.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -49740,11 +49470,11 @@
});
/* ======================================================================
OpenLayers/Format/OWSCommon/v1_1_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -49860,11 +49590,11 @@
});
/* ======================================================================
OpenLayers/Format/WCSGetCoverage.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -50060,14 +49790,524 @@
CLASS_NAME: "OpenLayers.Format.WCSGetCoverage"
});
/* ======================================================================
+ OpenLayers/Format/Filter/v2.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/Format/Filter.js
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Filter/Function.js
+ * @requires OpenLayers/BaseTypes/Date.js
+ */
+
+/**
+ * Class: OpenLayers.Format.Filter.v2
+ * Superclass for Filter version 2 parsers.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.Filter.v2 = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ fes: "http://www.opengis.net/fes/2.0",
+ gml: "http://www.opengis.net/gml/3.2",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "fes",
+
+ /**
+ * Property: schemaLocation
+ * {String} Schema location for a particular minor version.
+ */
+ schemaLocation: null,
+
+ /**
+ * Constructor: OpenLayers.Format.Filter.v1
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.Filter> constructor instead.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * Method: read
+ *
+ * Parameters:
+ * data - {DOMElement} A Filter document element.
+ *
+ * Returns:
+ * {<OpenLayers.Filter>} A filter object.
+ */
+ read: function(data) {
+ var obj = {};
+ this.readers.fes["Filter"].apply(this, [data, obj]);
+ return obj.filter;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "fes": {
+ "_expression": function(node) {
+ // only the simplest of fes:expression handled
+ // "some text and an <ValueReference>attribute</ValueReference>"}
+ var obj, value = "";
+ for(var child=node.firstChild; child; child=child.nextSibling) {
+ switch(child.nodeType) {
+ case 1:
+ obj = this.readNode(child);
+ if (obj.property) {
+ value += "${" + obj.property + "}";
+ } else if (obj.value !== undefined) {
+ value += obj.value;
+ }
+ break;
+ case 3: // text node
+ case 4: // cdata section
+ value += child.nodeValue;
+ }
+ }
+ return value;
+ },
+ "Filter": function(node, parent) {
+ // Filters correspond to subclasses of OpenLayers.Filter.
+ // Since they contain information we don't persist, we
+ // create a temporary object and then pass on the filter
+ // (fes:Filter) to the parent obj.
+ var obj = {
+ fids: [],
+ filters: []
+ };
+ this.readChildNodes(node, obj);
+ if(obj.fids.length > 0) {
+ parent.filter = new OpenLayers.Filter.FeatureId({
+ fids: obj.fids
+ });
+ } else if(obj.filters.length > 0) {
+ parent.filter = obj.filters[0];
+ }
+ },
+ "ResourceId": function(node, obj) {
+ var fid = node.getAttribute("rid");
+ if(fid) {
+ obj.fids.push(fid);
+ }
+ },
+
+ "And": function(node, obj) {
+ var filter = new OpenLayers.Filter.Logical({
+ type: OpenLayers.Filter.Logical.AND
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "Or": function(node, obj) {
+ var filter = new OpenLayers.Filter.Logical({
+ type: OpenLayers.Filter.Logical.OR
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "Not": function(node, obj) {
+ var filter = new OpenLayers.Filter.Logical({
+ type: OpenLayers.Filter.Logical.NOT
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsLessThan": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.LESS_THAN
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsGreaterThan": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.GREATER_THAN
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsLessThanOrEqualTo": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsGreaterThanOrEqualTo": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "PropertyIsBetween": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.BETWEEN
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ },
+ "Literal": function(node, obj) {
+ obj.value = OpenLayers.String.numericIf(
+ this.getChildValue(node), true);
+ },
+ "ValueReference": function(node, filter) {
+ filter.property = this.getChildValue(node);
+ },
+ "LowerBoundary": function(node, filter) {
+ filter.lowerBoundary = OpenLayers.String.numericIf(
+ this.readers.fes._expression.call(this, node), true);
+ },
+ "UpperBoundary": function(node, filter) {
+ filter.upperBoundary = OpenLayers.String.numericIf(
+ this.readers.fes._expression.call(this, node), true);
+ },
+ "Intersects": function(node, obj) {
+ this.readSpatial(node, obj, OpenLayers.Filter.Spatial.INTERSECTS);
+ },
+ "Within": function(node, obj) {
+ this.readSpatial(node, obj, OpenLayers.Filter.Spatial.WITHIN);
+ },
+ "Contains": function(node, obj) {
+ this.readSpatial(node, obj, OpenLayers.Filter.Spatial.CONTAINS);
+ },
+ "DWithin": function(node, obj) {
+ this.readSpatial(node, obj, OpenLayers.Filter.Spatial.DWITHIN);
+ },
+ "Distance": function(node, obj) {
+ obj.distance = parseInt(this.getChildValue(node));
+ obj.distanceUnits = node.getAttribute("units");
+ },
+ "Function": function(node, obj) {
+ //TODO write decoder for it
+ return;
+ },
+ "PropertyIsNull": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.IS_NULL
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
+ }
+ }
+ },
+
+ /**
+ * Method: readSpatial
+ *
+ * Read a {<OpenLayers.Filter.Spatial>} filter.
+ *
+ * Parameters:
+ * node - {DOMElement} A DOM element that contains an fes:expression.
+ * obj - {Object} The target object.
+ * type - {String} One of the OpenLayers.Filter.Spatial.* constants.
+ *
+ * Returns:
+ * {<OpenLayers.Filter.Spatial>} The created filter.
+ */
+ readSpatial: function(node, obj, type) {
+ var filter = new OpenLayers.Filter.Spatial({
+ type: type
+ });
+ this.readChildNodes(node, filter);
+ filter.value = filter.components[0];
+ delete filter.components;
+ obj.filters.push(filter);
+ },
+
+ /**
+ * APIMethod: encodeLiteral
+ * Generates the string representation of a value for use in <Literal>
+ * elements. The default encoder writes Date values as ISO 8601
+ * strings.
+ *
+ * Parameters:
+ * value - {Object} Literal value to encode
+ *
+ * Returns:
+ * {String} String representation of the provided value.
+ */
+ encodeLiteral: function(value) {
+ if (value instanceof Date) {
+ value = OpenLayers.Date.toISOString(value);
+ }
+ return value;
+ },
+
+ /**
+ * Method: writeOgcExpression
+ * Limited support for writing OGC expressions. Currently it supports
+ * (<OpenLayers.Filter.Function> || String || Number)
+ *
+ * Parameters:
+ * value - (<OpenLayers.Filter.Function> || String || Number)
+ * node - {DOMElement} A parent DOM element
+ *
+ * Returns:
+ * {DOMElement} Updated node element.
+ */
+ writeOgcExpression: function(value, node) {
+ if (value instanceof OpenLayers.Filter.Function){
+ this.writeNode("Function", value, node);
+ } else {
+ this.writeNode("Literal", value, node);
+ }
+ return node;
+ },
+
+ /**
+ * Method: write
+ *
+ * Parameters:
+ * filter - {<OpenLayers.Filter>} A filter object.
+ *
+ * Returns:
+ * {DOMElement} An fes:Filter element.
+ */
+ write: function(filter) {
+ return this.writers.fes["Filter"].apply(this, [filter]);
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "fes": {
+ "Filter": function(filter) {
+ var node = this.createElementNSPlus("fes:Filter");
+ this.writeNode(this.getFilterType(filter), filter, node);
+ return node;
+ },
+ "_featureIds": function(filter) {
+ var node = this.createDocumentFragment();
+ for (var i=0, ii=filter.fids.length; i<ii; ++i) {
+ this.writeNode("fes:ResourceId", filter.fids[i], node);
+ }
+ return node;
+ },
+ "ResourceId": function(fid) {
+ return this.createElementNSPlus("fes:ResourceId", {
+ attributes: {rid: fid}
+ });
+ },
+
+ "And": function(filter) {
+ var node = this.createElementNSPlus("fes:And");
+ var childFilter;
+ for (var i=0, ii=filter.filters.length; i<ii; ++i) {
+ childFilter = filter.filters[i];
+ this.writeNode(
+ this.getFilterType(childFilter), childFilter, node
+ );
+ }
+ return node;
+ },
+ "Or": function(filter) {
+ var node = this.createElementNSPlus("fes:Or");
+ var childFilter;
+ for (var i=0, ii=filter.filters.length; i<ii; ++i) {
+ childFilter = filter.filters[i];
+ this.writeNode(
+ this.getFilterType(childFilter), childFilter, node
+ );
+ }
+ return node;
+ },
+ "Not": function(filter) {
+ var node = this.createElementNSPlus("fes:Not");
+ var childFilter = filter.filters[0];
+ this.writeNode(
+ this.getFilterType(childFilter), childFilter, node
+ );
+ return node;
+ },
+ "PropertyIsLessThan": function(filter) {
+ var node = this.createElementNSPlus("fes:PropertyIsLessThan");
+ // no fes:expression handling for ValueReference for now
+ this.writeNode("ValueReference", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsGreaterThan": function(filter) {
+ var node = this.createElementNSPlus("fes:PropertyIsGreaterThan");
+ // no fes:expression handling for ValueReference for now
+ this.writeNode("ValueReference", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsLessThanOrEqualTo": function(filter) {
+ var node = this.createElementNSPlus("fes:PropertyIsLessThanOrEqualTo");
+ // no fes:expression handling for ValueReference for now
+ this.writeNode("ValueReference", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsGreaterThanOrEqualTo": function(filter) {
+ var node = this.createElementNSPlus("fes:PropertyIsGreaterThanOrEqualTo");
+ // no fes:expression handling for ValueReference for now
+ this.writeNode("ValueReference", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
+ return node;
+ },
+ "PropertyIsBetween": function(filter) {
+ var node = this.createElementNSPlus("fes:PropertyIsBetween");
+ // no fes:expression handling for ValueReference for now
+ this.writeNode("ValueReference", filter, node);
+ this.writeNode("LowerBoundary", filter, node);
+ this.writeNode("UpperBoundary", filter, node);
+ return node;
+ },
+ "ValueReference": function(filter) {
+ // no fes:expression handling for now
+ return this.createElementNSPlus("fes:ValueReference", {
+ value: filter.property
+ });
+ },
+ "Literal": function(value) {
+ var encode = this.encodeLiteral ||
+ OpenLayers.Format.Filter.v1.prototype.encodeLiteral;
+ return this.createElementNSPlus("fes:Literal", {
+ value: encode(value)
+ });
+ },
+ "LowerBoundary": function(filter) {
+ // handle Literals or Functions for now
+ var node = this.createElementNSPlus("fes:LowerBoundary");
+ this.writeOgcExpression(filter.lowerBoundary, node);
+ return node;
+ },
+ "UpperBoundary": function(filter) {
+ // handle Literals or Functions for now
+ var node = this.createElementNSPlus("fes:UpperBoundary");
+ this.writeNode("Literal", filter.upperBoundary, node);
+ return node;
+ },
+ "INTERSECTS": function(filter) {
+ return this.writeSpatial(filter, "Intersects");
+ },
+ "WITHIN": function(filter) {
+ return this.writeSpatial(filter, "Within");
+ },
+ "CONTAINS": function(filter) {
+ return this.writeSpatial(filter, "Contains");
+ },
+ "DWITHIN": function(filter) {
+ var node = this.writeSpatial(filter, "DWithin");
+ this.writeNode("Distance", filter, node);
+ return node;
+ },
+ "Distance": function(filter) {
+ return this.createElementNSPlus("fes:Distance", {
+ attributes: {
+ units: filter.distanceUnits
+ },
+ value: filter.distance
+ });
+ },
+ "Function": function(filter) {
+ var node = this.createElementNSPlus("fes:Function", {
+ attributes: {
+ name: filter.name
+ }
+ });
+ var params = filter.params;
+ for(var i=0, len=params.length; i<len; i++){
+ this.writeOgcExpression(params[i], node);
+ }
+ return node;
+ },
+ "PropertyIsNull": function(filter) {
+ var node = this.createElementNSPlus("fes:PropertyIsNull");
+ this.writeNode("ValueReference", filter, node);
+ return node;
+ }
+ }
+ },
+
+ /**
+ * Method: getFilterType
+ */
+ getFilterType: function(filter) {
+ var filterType = this.filterMap[filter.type];
+ if(!filterType) {
+ throw "Filter writing not supported for rule type: " + filter.type;
+ }
+ return filterType;
+ },
+
+ /**
+ * Property: filterMap
+ * {Object} Contains a member for each filter type. Values are node names
+ * for corresponding OGC Filter child elements.
+ */
+ filterMap: {
+ "&&": "And",
+ "||": "Or",
+ "!": "Not",
+ "==": "PropertyIsEqualTo",
+ "!=": "PropertyIsNotEqualTo",
+ "<": "PropertyIsLessThan",
+ ">": "PropertyIsGreaterThan",
+ "<=": "PropertyIsLessThanOrEqualTo",
+ ">=": "PropertyIsGreaterThanOrEqualTo",
+ "..": "PropertyIsBetween",
+ "~": "PropertyIsLike",
+ "NULL": "PropertyIsNull",
+ "BBOX": "BBOX",
+ "DWITHIN": "DWITHIN",
+ "WITHIN": "WITHIN",
+ "CONTAINS": "CONTAINS",
+ "INTERSECTS": "INTERSECTS",
+ "FID": "_featureIds"
+ },
+
+ CLASS_NAME: "OpenLayers.Format.Filter.v2"
+
+});
+/* ======================================================================
OpenLayers/Format/WMSCapabilities.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -50123,11 +50363,11 @@
});
/* ======================================================================
OpenLayers/Format/WMSCapabilities/v1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -50495,11 +50735,11 @@
});
/* ======================================================================
OpenLayers/Format/WMSCapabilities/v1_1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -50621,11 +50861,11 @@
});
/* ======================================================================
OpenLayers/Format/WMSCapabilities/v1_1_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -50679,471 +50919,1551 @@
CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_0"
});
/* ======================================================================
- OpenLayers/Protocol/WFS/v1.js
+ OpenLayers/Strategy/BBOX.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Protocol/WFS.js
+ * @requires OpenLayers/Strategy.js
+ * @requires OpenLayers/Filter/Spatial.js
*/
/**
- * Class: OpenLayers.Protocol.WFS.v1
- * Abstract class for for v1.0.0 and v1.1.0 protocol.
+ * Class: OpenLayers.Strategy.BBOX
+ * A simple strategy that reads new features when the viewport invalidates
+ * some bounds.
*
* Inherits from:
- * - <OpenLayers.Protocol>
+ * - <OpenLayers.Strategy>
*/
-OpenLayers.Protocol.WFS.v1 = OpenLayers.Class(OpenLayers.Protocol, {
+OpenLayers.Strategy.BBOX = OpenLayers.Class(OpenLayers.Strategy, {
/**
- * Property: version
- * {String} WFS version number.
+ * Property: bounds
+ * {<OpenLayers.Bounds>} The current data bounds (in the same projection
+ * as the layer - not always the same projection as the map).
*/
- version: null,
+ bounds: null,
+ /**
+ * Property: resolution
+ * {Float} The current data resolution.
+ */
+ resolution: null,
+
/**
- * Property: srsName
- * {String} Name of spatial reference system. Default is "EPSG:4326".
+ * APIProperty: ratio
+ * {Float} The ratio of the data bounds to the viewport bounds (in each
+ * dimension). Default is 2.
*/
- srsName: "EPSG:4326",
+ ratio: 2,
+
+ /**
+ * Property: resFactor
+ * {Float} Optional factor used to determine when previously requested
+ * features are invalid. If set, the resFactor will be compared to the
+ * resolution of the previous request to the current map resolution.
+ * If resFactor > (old / new) and 1/resFactor < (old / new). If you
+ * set a resFactor of 1, data will be requested every time the
+ * resolution changes. If you set a resFactor of 3, data will be
+ * requested if the old resolution is 3 times the new, or if the new is
+ * 3 times the old. If the old bounds do not contain the new bounds
+ * new data will always be requested (with or without considering
+ * resFactor).
+ */
+ resFactor: null,
/**
- * Property: featureType
- * {String} Local feature typeName.
+ * Property: response
+ * {<OpenLayers.Protocol.Response>} The protocol response object returned
+ * by the layer protocol.
*/
- featureType: null,
+ response: null,
+
+ /**
+ * Constructor: OpenLayers.Strategy.BBOX
+ * Create a new BBOX strategy.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will be set on the
+ * instance.
+ */
/**
- * Property: featureNS
- * {String} Feature namespace.
+ * Method: activate
+ * Set up strategy with regard to reading new batches of remote data.
+ *
+ * Returns:
+ * {Boolean} The strategy was successfully activated.
*/
- featureNS: null,
+ activate: function() {
+ var activated = OpenLayers.Strategy.prototype.activate.call(this);
+ if(activated) {
+ this.layer.events.on({
+ "moveend": this.update,
+ "refresh": this.update,
+ "visibilitychanged": this.update,
+ scope: this
+ });
+ this.update();
+ }
+ return activated;
+ },
/**
- * Property: geometryName
- * {String} Name of the geometry attribute for features. Default is
- * "the_geom" for WFS <version> 1.0, and null for higher versions.
+ * Method: deactivate
+ * Tear down strategy with regard to reading new batches of remote data.
+ *
+ * Returns:
+ * {Boolean} The strategy was successfully deactivated.
*/
- geometryName: "the_geom",
+ deactivate: function() {
+ var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
+ if(deactivated) {
+ this.layer.events.un({
+ "moveend": this.update,
+ "refresh": this.update,
+ "visibilitychanged": this.update,
+ scope: this
+ });
+ }
+ return deactivated;
+ },
/**
- * Property: maxFeatures
- * {Integer} Optional maximum number of features to retrieve.
+ * Method: update
+ * Callback function called on "moveend" or "refresh" layer events.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will determine
+ * the behaviour of this Strategy
+ *
+ * Valid options include:
+ * force - {Boolean} if true, new data must be unconditionally read.
+ * noAbort - {Boolean} if true, do not abort previous requests.
*/
+ update: function(options) {
+ var mapBounds = this.getMapBounds();
+ if (mapBounds !== null && ((options && options.force) ||
+ (this.layer.visibility && this.layer.calculateInRange() && this.invalidBounds(mapBounds)))) {
+ this.calculateBounds(mapBounds);
+ this.resolution = this.layer.map.getResolution();
+ this.triggerRead(options);
+ }
+ },
/**
- * Property: schema
- * {String} Optional schema location that will be included in the
- * schemaLocation attribute value. Note that the feature type schema
- * is required for a strict XML validator (on transactions with an
- * insert for example), but is *not* required by the WFS specification
- * (since the server is supposed to know about feature type schemas).
+ * Method: getMapBounds
+ * Get the map bounds expressed in the same projection as this layer.
+ *
+ * Returns:
+ * {<OpenLayers.Bounds>} Map bounds in the projection of the layer.
*/
- schema: null,
+ getMapBounds: function() {
+ if (this.layer.map === null) {
+ return null;
+ }
+ var bounds = this.layer.map.getExtent();
+ if(bounds && !this.layer.projection.equals(
+ this.layer.map.getProjectionObject())) {
+ bounds = bounds.clone().transform(
+ this.layer.map.getProjectionObject(), this.layer.projection
+ );
+ }
+ return bounds;
+ },
/**
- * Property: featurePrefix
- * {String} Namespace alias for feature type. Default is "feature".
+ * Method: invalidBounds
+ * Determine whether the previously requested set of features is invalid.
+ * This occurs when the new map bounds do not contain the previously
+ * requested bounds. In addition, if <resFactor> is set, it will be
+ * considered.
+ *
+ * Parameters:
+ * mapBounds - {<OpenLayers.Bounds>} the current map extent, will be
+ * retrieved from the map object if not provided
+ *
+ * Returns:
+ * {Boolean}
*/
- featurePrefix: "feature",
+ invalidBounds: function(mapBounds) {
+ if(!mapBounds) {
+ mapBounds = this.getMapBounds();
+ }
+ var invalid = !this.bounds || !this.bounds.containsBounds(mapBounds);
+ if(!invalid && this.resFactor) {
+ var ratio = this.resolution / this.layer.map.getResolution();
+ invalid = (ratio >= this.resFactor || ratio <= (1 / this.resFactor));
+ }
+ return invalid;
+ },
+
+ /**
+ * Method: calculateBounds
+ *
+ * Parameters:
+ * mapBounds - {<OpenLayers.Bounds>} the current map extent, will be
+ * retrieved from the map object if not provided
+ */
+ calculateBounds: function(mapBounds) {
+ if(!mapBounds) {
+ mapBounds = this.getMapBounds();
+ }
+ var center = mapBounds.getCenterLonLat();
+ var dataWidth = mapBounds.getWidth() * this.ratio;
+ var dataHeight = mapBounds.getHeight() * this.ratio;
+ this.bounds = new OpenLayers.Bounds(
+ center.lon - (dataWidth / 2),
+ center.lat - (dataHeight / 2),
+ center.lon + (dataWidth / 2),
+ center.lat + (dataHeight / 2)
+ );
+ },
/**
- * Property: formatOptions
- * {Object} Optional options for the format. If a format is not provided,
- * this property can be used to extend the default format options.
+ * Method: triggerRead
+ *
+ * Parameters:
+ * options - {Object} Additional options for the protocol's read method
+ * (optional)
+ *
+ * Returns:
+ * {<OpenLayers.Protocol.Response>} The protocol response object
+ * returned by the layer protocol.
*/
- formatOptions: null,
+ triggerRead: function(options) {
+ if (this.response && !(options && options.noAbort === true)) {
+ this.layer.protocol.abort(this.response);
+ this.layer.events.triggerEvent("loadend");
+ }
+ var evt = {filter: this.createFilter()};
+ this.layer.events.triggerEvent("loadstart", evt);
+ this.response = this.layer.protocol.read(
+ OpenLayers.Util.applyDefaults({
+ filter: evt.filter,
+ callback: this.merge,
+ scope: this
+ }, options));
+ },
+
+ /**
+ * Method: createFilter
+ * Creates a spatial BBOX filter. If the layer that this strategy belongs
+ * to has a filter property, this filter will be combined with the BBOX
+ * filter.
+ *
+ * Returns
+ * {<OpenLayers.Filter>} The filter object.
+ */
+ createFilter: function() {
+ var filter = new OpenLayers.Filter.Spatial({
+ type: OpenLayers.Filter.Spatial.BBOX,
+ value: this.bounds,
+ projection: this.layer.projection
+ });
+ if (this.layer.filter) {
+ filter = new OpenLayers.Filter.Logical({
+ type: OpenLayers.Filter.Logical.AND,
+ filters: [this.layer.filter, filter]
+ });
+ }
+ return filter;
+ },
+
+ /**
+ * Method: merge
+ * Given a list of features, determine which ones to add to the layer.
+ * If the layer projection differs from the map projection, features
+ * will be transformed from the layer projection to the map projection.
+ *
+ * Parameters:
+ * resp - {<OpenLayers.Protocol.Response>} The response object passed
+ * by the protocol.
+ */
+ merge: function(resp) {
+ this.layer.destroyFeatures();
+ if (resp.success()) {
+ var features = resp.features;
+ if(features && features.length > 0) {
+ var remote = this.layer.projection;
+ var local = this.layer.map.getProjectionObject();
+ if(!local.equals(remote)) {
+ var geom;
+ for(var i=0, len=features.length; i<len; ++i) {
+ geom = features[i].geometry;
+ if(geom) {
+ geom.transform(remote, local);
+ }
+ }
+ }
+ this.layer.addFeatures(features);
+ }
+ } else {
+ this.bounds = null;
+ }
+ this.response = null;
+ this.layer.events.triggerEvent("loadend", {response: resp});
+ },
+
+ CLASS_NAME: "OpenLayers.Strategy.BBOX"
+});
+/* ======================================================================
+ OpenLayers/Handler/Feature.js
+ ====================================================================== */
- /**
- * Property: readFormat
- * {<OpenLayers.Format>} For WFS requests it is possible to get a
- * different output format than GML. In that case, we cannot parse
- * the response with the default format (WFST) and we need a different
- * format for reading.
- */
- readFormat: 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. */
+
+
+/**
+ * @requires OpenLayers/Handler.js
+ */
+
+/**
+ * Class: OpenLayers.Handler.Feature
+ * Handler to respond to mouse events related to a drawn feature. Callbacks
+ * with the following keys will be notified of the following events
+ * associated with features: click, clickout, over, out, and dblclick.
+ *
+ * This handler stops event propagation for mousedown and mouseup if those
+ * browser events target features that can be selected.
+ *
+ * Inherits from:
+ * - <OpenLayers.Handler>
+ */
+OpenLayers.Handler.Feature = OpenLayers.Class(OpenLayers.Handler, {
+
+ /**
+ * Property: EVENTMAP
+ * {Object} A object mapping the browser events to objects with callback
+ * keys for in and out.
+ */
+ EVENTMAP: {
+ 'click': {'in': 'click', 'out': 'clickout'},
+ 'mousemove': {'in': 'over', 'out': 'out'},
+ 'dblclick': {'in': 'dblclick', 'out': null},
+ 'mousedown': {'in': null, 'out': null},
+ 'mouseup': {'in': null, 'out': null},
+ 'touchstart': {'in': 'click', 'out': 'clickout'}
+ },
+
+ /**
+ * Property: feature
+ * {<OpenLayers.Feature.Vector>} The last feature that was hovered.
+ */
+ feature: null,
+
+ /**
+ * Property: lastFeature
+ * {<OpenLayers.Feature.Vector>} The last feature that was handled.
+ */
+ lastFeature: null,
+
+ /**
+ * Property: down
+ * {<OpenLayers.Pixel>} The location of the last mousedown.
+ */
+ down: null,
+
+ /**
+ * Property: up
+ * {<OpenLayers.Pixel>} The location of the last mouseup.
+ */
+ up: null,
/**
- * Property: readOptions
- * {Object} Optional object to pass to format's read.
+ * Property: clickTolerance
+ * {Number} The number of pixels the mouse can move between mousedown
+ * and mouseup for the event to still be considered a click.
+ * Dragging the map should not trigger the click and clickout callbacks
+ * unless the map is moved by less than this tolerance. Defaults to 4.
*/
- readOptions: null,
+ clickTolerance: 4,
+
+ /**
+ * Property: geometryTypes
+ * To restrict dragging to a limited set of geometry types, send a list
+ * of strings corresponding to the geometry class names.
+ *
+ * @type Array(String)
+ */
+ geometryTypes: null,
+
+ /**
+ * Property: stopClick
+ * {Boolean} If stopClick is set to true, handled clicks do not
+ * propagate to other click listeners. Otherwise, handled clicks
+ * do propagate. Unhandled clicks always propagate, whatever the
+ * value of stopClick. Defaults to true.
+ */
+ stopClick: true,
+
+ /**
+ * Property: stopDown
+ * {Boolean} If stopDown is set to true, handled mousedowns do not
+ * propagate to other mousedown listeners. Otherwise, handled
+ * mousedowns do propagate. Unhandled mousedowns always propagate,
+ * whatever the value of stopDown. Defaults to true.
+ */
+ stopDown: true,
+
+ /**
+ * Property: stopUp
+ * {Boolean} If stopUp is set to true, handled mouseups do not
+ * propagate to other mouseup listeners. Otherwise, handled mouseups
+ * do propagate. Unhandled mouseups always propagate, whatever the
+ * value of stopUp. Defaults to false.
+ */
+ stopUp: false,
/**
- * Constructor: OpenLayers.Protocol.WFS
- * A class for giving layers WFS protocol.
+ * Constructor: OpenLayers.Handler.Feature
*
* Parameters:
- * options - {Object} Optional object whose properties will be set on the
- * instance.
+ * control - {<OpenLayers.Control>}
+ * layer - {<OpenLayers.Layer.Vector>}
+ * callbacks - {Object} An object with a 'over' property whos value is
+ * a function to be called when the mouse is over a feature. The
+ * callback should expect to recieve a single argument, the feature.
+ * options - {Object}
+ */
+ initialize: function(control, layer, callbacks, options) {
+ OpenLayers.Handler.prototype.initialize.apply(this, [control, callbacks, options]);
+ this.layer = layer;
+ },
+
+ /**
+ * Method: touchstart
+ * Handle touchstart events
*
- * Valid options properties:
- * url - {String} URL to send requests to (required).
- * featureType - {String} Local (without prefix) feature typeName (required).
- * featureNS - {String} Feature namespace (required, but can be autodetected
- * during the first query if GML is used as readFormat and
- * featurePrefix is provided and matches the prefix used by the server
- * for this featureType).
- * featurePrefix - {String} Feature namespace alias (optional - only used
- * for writing if featureNS is provided). Default is 'feature'.
- * geometryName - {String} Name of geometry attribute. The default is
- * 'the_geom' for WFS <version> 1.0, and null for higher versions. If
- * null, it will be set to the name of the first geometry found in the
- * first read operation.
- * multi - {Boolean} If set to true, geometries will be casted to Multi
- * geometries before they are written in a transaction. No casting will
- * be done when reading features.
+ * Parameters:
+ * evt - {Event}
+ *
+ * Returns:
+ * {Boolean} Let the event propagate.
*/
- initialize: function(options) {
- OpenLayers.Protocol.prototype.initialize.apply(this, [options]);
- if(!options.format) {
- this.format = OpenLayers.Format.WFST(OpenLayers.Util.extend({
- version: this.version,
- featureType: this.featureType,
- featureNS: this.featureNS,
- featurePrefix: this.featurePrefix,
- geometryName: this.geometryName,
- srsName: this.srsName,
- schema: this.schema
- }, this.formatOptions));
+ touchstart: function(evt) {
+ this.startTouch();
+ return OpenLayers.Event.isMultiTouch(evt) ?
+ true : this.mousedown(evt);
+ },
+
+ /**
+ * Method: touchmove
+ * Handle touchmove events. We just prevent the browser default behavior,
+ * for Android Webkit not to select text when moving the finger after
+ * selecting a feature.
+ *
+ * Parameters:
+ * evt - {Event}
+ */
+ touchmove: function(evt) {
+ OpenLayers.Event.preventDefault(evt);
+ },
+
+ /**
+ * Method: mousedown
+ * Handle mouse down. Stop propagation if a feature is targeted by this
+ * event (stops map dragging during feature selection).
+ *
+ * Parameters:
+ * evt - {Event}
+ */
+ mousedown: function(evt) {
+ // Feature selection is only done with a left click. Other handlers may stop the
+ // propagation of left-click mousedown events but not right-click mousedown events.
+ // This mismatch causes problems when comparing the location of the down and up
+ // events in the click function so it is important ignore right-clicks.
+ if (OpenLayers.Event.isLeftClick(evt) || OpenLayers.Event.isSingleTouch(evt)) {
+ this.down = evt.xy;
}
- if (!options.geometryName && parseFloat(this.format.version) > 1.0) {
- this.setGeometryName(null);
- }
+ return this.handle(evt) ? !this.stopDown : true;
},
/**
- * APIMethod: destroy
- * Clean up the protocol.
+ * Method: mouseup
+ * Handle mouse up. Stop propagation if a feature is targeted by this
+ * event.
+ *
+ * Parameters:
+ * evt - {Event}
*/
- destroy: function() {
- if(this.options && !this.options.format) {
- this.format.destroy();
- }
- this.format = null;
- OpenLayers.Protocol.prototype.destroy.apply(this);
+ mouseup: function(evt) {
+ this.up = evt.xy;
+ return this.handle(evt) ? !this.stopUp : true;
},
/**
- * APIMethod: read
- * Construct a request for reading new features. Since WFS splits the
- * basic CRUD operations into GetFeature requests (for read) and
- * Transactions (for all others), this method does not make use of the
- * format's read method (that is only about reading transaction
- * responses).
+ * Method: click
+ * Handle click. Call the "click" callback if click on a feature,
+ * or the "clickout" callback if click outside any feature.
+ *
+ * Parameters:
+ * evt - {Event}
*
+ * Returns:
+ * {Boolean}
+ */
+ click: function(evt) {
+ return this.handle(evt) ? !this.stopClick : true;
+ },
+
+ /**
+ * Method: mousemove
+ * Handle mouse moves. Call the "over" callback if moving in to a feature,
+ * or the "out" callback if moving out of a feature.
+ *
* Parameters:
- * options - {Object} Options for the read operation, in addition to the
- * options set on the instance (options set here will take precedence).
+ * evt - {Event}
*
- * To use a configured protocol to get e.g. a WFS hit count, applications
- * could do the following:
+ * Returns:
+ * {Boolean}
+ */
+ mousemove: function(evt) {
+ if (!this.callbacks['over'] && !this.callbacks['out']) {
+ return true;
+ }
+ this.handle(evt);
+ return true;
+ },
+
+ /**
+ * Method: dblclick
+ * Handle dblclick. Call the "dblclick" callback if dblclick on a feature.
*
- * (code)
- * protocol.read({
- * readOptions: {output: "object"},
- * resultType: "hits",
- * maxFeatures: null,
- * callback: function(resp) {
- * // process resp.numberOfFeatures here
- * }
- * });
- * (end)
+ * Parameters:
+ * evt - {Event}
*
- * To use a configured protocol to use WFS paging (if supported by the
- * server), applications could do the following:
+ * Returns:
+ * {Boolean}
+ */
+ dblclick: function(evt) {
+ return !this.handle(evt);
+ },
+
+ /**
+ * Method: geometryTypeMatches
+ * Return true if the geometry type of the passed feature matches
+ * one of the geometry types in the geometryTypes array.
*
- * (code)
- * protocol.read({
- * startIndex: 0,
- * count: 50
- * });
- * (end)
+ * Parameters:
+ * feature - {<OpenLayers.Vector.Feature>}
*
- * To limit the attributes returned by the GetFeature request, applications
- * can use the propertyNames option to specify the properties to include in
- * the response:
+ * Returns:
+ * {Boolean}
+ */
+ geometryTypeMatches: function(feature) {
+ return this.geometryTypes == null ||
+ OpenLayers.Util.indexOf(this.geometryTypes,
+ feature.geometry.CLASS_NAME) > -1;
+ },
+
+ /**
+ * Method: handle
*
- * (code)
- * protocol.read({
- * propertyNames: ["DURATION", "INTENSITY"]
- * });
- * (end)
+ * Parameters:
+ * evt - {Event}
+ *
+ * Returns:
+ * {Boolean} The event occurred over a relevant feature.
*/
- read: function(options) {
- OpenLayers.Protocol.prototype.read.apply(this, arguments);
- options = OpenLayers.Util.extend({}, options);
- OpenLayers.Util.applyDefaults(options, this.options || {});
- var response = new OpenLayers.Protocol.Response({requestType: "read"});
+ handle: function(evt) {
+ if(this.feature && !this.feature.layer) {
+ // feature has been destroyed
+ this.feature = null;
+ }
+ var type = evt.type;
+ var handled = false;
+ var previouslyIn = !!(this.feature); // previously in a feature
+ var click = (type == "click" || type == "dblclick" || type == "touchstart");
+ this.feature = this.layer.getFeatureFromEvent(evt);
+ if(this.feature && !this.feature.layer) {
+ // feature has been destroyed
+ this.feature = null;
+ }
+ if(this.lastFeature && !this.lastFeature.layer) {
+ // last feature has been destroyed
+ this.lastFeature = null;
+ }
+ if(this.feature) {
+ if(type === "touchstart") {
+ // stop the event to prevent Android Webkit from
+ // "flashing" the map div
+ OpenLayers.Event.preventDefault(evt);
+ }
+ var inNew = (this.feature != this.lastFeature);
+ if(this.geometryTypeMatches(this.feature)) {
+ // in to a feature
+ if(previouslyIn && inNew) {
+ // out of last feature and in to another
+ if(this.lastFeature) {
+ this.triggerCallback(type, 'out', [this.lastFeature]);
+ }
+ this.triggerCallback(type, 'in', [this.feature]);
+ } else if(!previouslyIn || click) {
+ // in feature for the first time
+ this.triggerCallback(type, 'in', [this.feature]);
+ }
+ this.lastFeature = this.feature;
+ handled = true;
+ } else {
+ // not in to a feature
+ if(this.lastFeature && (previouslyIn && inNew || click)) {
+ // out of last feature for the first time
+ this.triggerCallback(type, 'out', [this.lastFeature]);
+ }
+ // next time the mouse goes in a feature whose geometry type
+ // doesn't match we don't want to call the 'out' callback
+ // again, so let's set this.feature to null so that
+ // previouslyIn will evaluate to false the next time
+ // we enter handle. Yes, a bit hackish...
+ this.feature = null;
+ }
+ } else if(this.lastFeature && (previouslyIn || click)) {
+ this.triggerCallback(type, 'out', [this.lastFeature]);
+ }
+ return handled;
+ },
+
+ /**
+ * Method: triggerCallback
+ * Call the callback keyed in the event map with the supplied arguments.
+ * For click and clickout, the <clickTolerance> is checked first.
+ *
+ * Parameters:
+ * type - {String}
+ */
+ triggerCallback: function(type, mode, args) {
+ var key = this.EVENTMAP[type][mode];
+ if(key) {
+ if(type == 'click' && this.up && this.down) {
+ // for click/clickout, only trigger callback if tolerance is met
+ var dpx = Math.sqrt(
+ Math.pow(this.up.x - this.down.x, 2) +
+ Math.pow(this.up.y - this.down.y, 2)
+ );
+ if(dpx <= this.clickTolerance) {
+ this.callback(key, args);
+ }
+ // we're done with this set of events now: clear the cached
+ // positions so we can't trip over them later (this can occur
+ // if one of the up/down events gets eaten before it gets to us
+ // but we still get the click)
+ this.up = this.down = null;
+ } else {
+ this.callback(key, args);
+ }
+ }
+ },
+
+ /**
+ * Method: activate
+ * Turn on the handler. Returns false if the handler was already active.
+ *
+ * Returns:
+ * {Boolean}
+ */
+ activate: function() {
+ var activated = false;
+ if(OpenLayers.Handler.prototype.activate.apply(this, arguments)) {
+ this.moveLayerToTop();
+ this.map.events.on({
+ "removelayer": this.handleMapEvents,
+ "changelayer": this.handleMapEvents,
+ scope: this
+ });
+ activated = true;
+ }
+ return activated;
+ },
+
+ /**
+ * Method: deactivate
+ * Turn off the handler. Returns false if the handler was already active.
+ *
+ * Returns:
+ * {Boolean}
+ */
+ deactivate: function() {
+ var deactivated = false;
+ if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+ this.moveLayerBack();
+ this.feature = null;
+ this.lastFeature = null;
+ this.down = null;
+ this.up = null;
+ this.map.events.un({
+ "removelayer": this.handleMapEvents,
+ "changelayer": this.handleMapEvents,
+ scope: this
+ });
+ deactivated = true;
+ }
+ return deactivated;
+ },
+
+ /**
+ * Method: handleMapEvents
+ *
+ * Parameters:
+ * evt - {Object}
+ */
+ handleMapEvents: function(evt) {
+ if (evt.type == "removelayer" || evt.property == "order") {
+ this.moveLayerToTop();
+ }
+ },
+
+ /**
+ * Method: moveLayerToTop
+ * Moves the layer for this handler to the top, so mouse events can reach
+ * it.
+ */
+ moveLayerToTop: function() {
+ var index = Math.max(this.map.Z_INDEX_BASE['Feature'] - 1,
+ this.layer.getZIndex()) + 1;
+ this.layer.setZIndex(index);
- var data = OpenLayers.Format.XML.prototype.write.apply(
- this.format, [this.format.writeNode("wfs:GetFeature", options)]
- );
+ },
+
+ /**
+ * Method: moveLayerBack
+ * Moves the layer back to the position determined by the map's layers
+ * array.
+ */
+ moveLayerBack: function() {
+ var index = this.layer.getZIndex() - 1;
+ if (index >= this.map.Z_INDEX_BASE['Feature']) {
+ this.layer.setZIndex(index);
+ } else {
+ this.map.setLayerZIndex(this.layer,
+ this.map.getLayerIndex(this.layer));
+ }
+ },
- response.priv = OpenLayers.Request.POST({
- url: options.url,
- callback: this.createCallback(this.handleRead, response, options),
- params: options.params,
- headers: options.headers,
- data: data
- });
+ CLASS_NAME: "OpenLayers.Handler.Feature"
+});
+/* ======================================================================
+ OpenLayers/Layer/Vector/RootContainer.js
+ ====================================================================== */
- return response;
+/* 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/Layer/Vector.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Vector.RootContainer
+ * A special layer type to combine multiple vector layers inside a single
+ * renderer root container. This class is not supposed to be instantiated
+ * from user space, it is a helper class for controls that require event
+ * processing for multiple vector layers.
+ *
+ * Inherits from:
+ * - <OpenLayers.Layer.Vector>
+ */
+OpenLayers.Layer.Vector.RootContainer = OpenLayers.Class(OpenLayers.Layer.Vector, {
+
+ /**
+ * Property: displayInLayerSwitcher
+ * Set to false for this layer type
+ */
+ displayInLayerSwitcher: false,
+
+ /**
+ * APIProperty: layers
+ * Layers that are attached to this container. Required config option.
+ */
+ layers: null,
+
+ /**
+ * Constructor: OpenLayers.Layer.Vector.RootContainer
+ * Create a new root container for multiple vector layer. This constructor
+ * is not supposed to be used from user space, it is only to be used by
+ * controls that need feature selection across multiple vector layers.
+ *
+ * Parameters:
+ * name - {String} A name for the layer
+ * options - {Object} Optional object with non-default properties to set on
+ * the layer.
+ *
+ * Required options properties:
+ * layers - {Array(<OpenLayers.Layer.Vector>)} The layers managed by this
+ * container
+ *
+ * Returns:
+ * {<OpenLayers.Layer.Vector.RootContainer>} A new vector layer root
+ * container
+ */
+
+ /**
+ * Method: display
+ */
+ display: function() {},
+
+ /**
+ * Method: getFeatureFromEvent
+ * walk through the layers to find the feature returned by the event
+ *
+ * Parameters:
+ * evt - {Object} event object with a feature property
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>}
+ */
+ getFeatureFromEvent: function(evt) {
+ var layers = this.layers;
+ var feature;
+ for(var i=0; i<layers.length; i++) {
+ feature = layers[i].getFeatureFromEvent(evt);
+ if(feature) {
+ return feature;
+ }
+ }
},
+
+ /**
+ * Method: setMap
+ *
+ * Parameters:
+ * map - {<OpenLayers.Map>}
+ */
+ setMap: function(map) {
+ OpenLayers.Layer.Vector.prototype.setMap.apply(this, arguments);
+ this.collectRoots();
+ map.events.register("changelayer", this, this.handleChangeLayer);
+ },
+
+ /**
+ * Method: removeMap
+ *
+ * Parameters:
+ * map - {<OpenLayers.Map>}
+ */
+ removeMap: function(map) {
+ map.events.unregister("changelayer", this, this.handleChangeLayer);
+ this.resetRoots();
+ OpenLayers.Layer.Vector.prototype.removeMap.apply(this, arguments);
+ },
+
+ /**
+ * Method: collectRoots
+ * Collects the root nodes of all layers this control is configured with
+ * and moveswien the nodes to this control's layer
+ */
+ collectRoots: function() {
+ var layer;
+ // walk through all map layers, because we want to keep the order
+ for(var i=0; i<this.map.layers.length; ++i) {
+ layer = this.map.layers[i];
+ if(OpenLayers.Util.indexOf(this.layers, layer) != -1) {
+ layer.renderer.moveRoot(this.renderer);
+ }
+ }
+ },
+
+ /**
+ * Method: resetRoots
+ * Resets the root nodes back into the layers they belong to.
+ */
+ resetRoots: function() {
+ var layer;
+ for(var i=0; i<this.layers.length; ++i) {
+ layer = this.layers[i];
+ if(this.renderer && layer.renderer.getRenderLayerId() == this.id) {
+ this.renderer.moveRoot(layer.renderer);
+ }
+ }
+ },
+
+ /**
+ * Method: handleChangeLayer
+ * Event handler for the map's changelayer event. We need to rebuild
+ * this container's layer dom if order of one of its layers changes.
+ * This handler is added with the setMap method, and removed with the
+ * removeMap method.
+ *
+ * Parameters:
+ * evt - {Object}
+ */
+ handleChangeLayer: function(evt) {
+ var layer = evt.layer;
+ if(evt.property == "order" &&
+ OpenLayers.Util.indexOf(this.layers, layer) != -1) {
+ this.resetRoots();
+ this.collectRoots();
+ }
+ },
+ CLASS_NAME: "OpenLayers.Layer.Vector.RootContainer"
+});
+/* ======================================================================
+ OpenLayers/Control/SelectFeature.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/Control.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Handler/Feature.js
+ * @requires OpenLayers/Layer/Vector/RootContainer.js
+ */
+
+/**
+ * Class: OpenLayers.Control.SelectFeature
+ * The SelectFeature control selects vector features from a given layer on
+ * click or hover.
+ *
+ * Inherits from:
+ * - <OpenLayers.Control>
+ */
+OpenLayers.Control.SelectFeature = OpenLayers.Class(OpenLayers.Control, {
+
+ /**
+ * APIProperty: events
+ * {<OpenLayers.Events>} Events instance for listeners and triggering
+ * control specific events.
+ *
+ * Register a listener for a particular event with the following syntax:
+ * (code)
+ * control.events.register(type, obj, listener);
+ * (end)
+ *
+ * Supported event types (in addition to those from <OpenLayers.Control.events>):
+ * beforefeaturehighlighted - Triggered before a feature is highlighted
+ * featurehighlighted - Triggered when a feature is highlighted
+ * featureunhighlighted - Triggered when a feature is unhighlighted
+ * boxselectionstart - Triggered before box selection starts
+ * boxselectionend - Triggered after box selection ends
+ */
+
/**
- * APIMethod: setFeatureType
- * Change the feature type on the fly.
+ * Property: multipleKey
+ * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
+ * the <multiple> property to true. Default is null.
+ */
+ multipleKey: null,
+
+ /**
+ * Property: toggleKey
+ * {String} An event modifier ('altKey' or 'shiftKey') that temporarily sets
+ * the <toggle> property to true. Default is null.
+ */
+ toggleKey: null,
+
+ /**
+ * APIProperty: multiple
+ * {Boolean} Allow selection of multiple geometries. Default is false.
+ */
+ multiple: false,
+
+ /**
+ * APIProperty: clickout
+ * {Boolean} Unselect features when clicking outside any feature.
+ * Default is true.
+ */
+ clickout: true,
+
+ /**
+ * APIProperty: toggle
+ * {Boolean} Unselect a selected feature on click. Default is false. Only
+ * has meaning if hover is false.
+ */
+ toggle: false,
+
+ /**
+ * APIProperty: hover
+ * {Boolean} Select on mouse over and deselect on mouse out. If true, this
+ * ignores clicks and only listens to mouse moves.
+ */
+ hover: false,
+
+ /**
+ * APIProperty: highlightOnly
+ * {Boolean} If true do not actually select features (that is place them in
+ * the layer's selected features array), just highlight them. This property
+ * has no effect if hover is false. Defaults to false.
+ */
+ highlightOnly: false,
+
+ /**
+ * APIProperty: box
+ * {Boolean} Allow feature selection by drawing a box.
+ */
+ box: false,
+
+ /**
+ * Property: onBeforeSelect
+ * {Function} Optional function to be called before a feature is selected.
+ * The function should expect to be called with a feature.
+ */
+ onBeforeSelect: function() {},
+
+ /**
+ * APIProperty: onSelect
+ * {Function} Optional function to be called when a feature is selected.
+ * The function should expect to be called with a feature.
+ */
+ onSelect: function() {},
+
+ /**
+ * APIProperty: onUnselect
+ * {Function} Optional function to be called when a feature is unselected.
+ * The function should expect to be called with a feature.
+ */
+ onUnselect: function() {},
+
+ /**
+ * Property: scope
+ * {Object} The scope to use with the onBeforeSelect, onSelect, onUnselect
+ * callbacks. If null the scope will be this control.
+ */
+ scope: null,
+
+ /**
+ * APIProperty: geometryTypes
+ * {Array(String)} To restrict selecting to a limited set of geometry types,
+ * send a list of strings corresponding to the geometry class names.
+ */
+ geometryTypes: null,
+
+ /**
+ * Property: layer
+ * {<OpenLayers.Layer.Vector>} The vector layer with a common renderer
+ * root for all layers this control is configured with (if an array of
+ * layers was passed to the constructor), or the vector layer the control
+ * was configured with (if a single layer was passed to the constructor).
+ */
+ layer: null,
+
+ /**
+ * Property: layers
+ * {Array(<OpenLayers.Layer.Vector>)} The layers this control will work on,
+ * or null if the control was configured with a single layer
+ */
+ layers: null,
+
+ /**
+ * APIProperty: callbacks
+ * {Object} The functions that are sent to the handlers.feature for callback
+ */
+ callbacks: null,
+
+ /**
+ * APIProperty: selectStyle
+ * {Object} Hash of styles
+ */
+ selectStyle: null,
+
+ /**
+ * Property: renderIntent
+ * {String} key used to retrieve the select style from the layer's
+ * style map.
+ */
+ renderIntent: "select",
+
+ /**
+ * Property: handlers
+ * {Object} Object with references to multiple <OpenLayers.Handler>
+ * instances.
+ */
+ handlers: null,
+
+ /**
+ * Constructor: OpenLayers.Control.SelectFeature
+ * Create a new control for selecting features.
*
* Parameters:
- * featureType - {String} Local (without prefix) feature typeName.
+ * layers - {<OpenLayers.Layer.Vector>}, or an array of vector layers. The
+ * layer(s) this control will select features from.
+ * options - {Object}
*/
- setFeatureType: function(featureType) {
- this.featureType = featureType;
- this.format.featureType = featureType;
+ initialize: function(layers, options) {
+ OpenLayers.Control.prototype.initialize.apply(this, [options]);
+
+ if(this.scope === null) {
+ this.scope = this;
+ }
+ this.initLayer(layers);
+ var callbacks = {
+ click: this.clickFeature,
+ clickout: this.clickoutFeature
+ };
+ if (this.hover) {
+ callbacks.over = this.overFeature;
+ callbacks.out = this.outFeature;
+ }
+
+ this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks);
+ this.handlers = {
+ feature: new OpenLayers.Handler.Feature(
+ this, this.layer, this.callbacks,
+ {geometryTypes: this.geometryTypes}
+ )
+ };
+
+ if (this.box) {
+ this.handlers.box = new OpenLayers.Handler.Box(
+ this, {done: this.selectBox},
+ {boxDivClassName: "olHandlerBoxSelectFeature"}
+ );
+ }
},
-
+
/**
- * APIMethod: setGeometryName
- * Sets the geometryName option after instantiation.
+ * Method: initLayer
+ * Assign the layer property. If layers is an array, we need to use
+ * a RootContainer.
*
* Parameters:
- * geometryName - {String} Name of geometry attribute.
+ * layers - {<OpenLayers.Layer.Vector>}, or an array of vector layers.
*/
- setGeometryName: function(geometryName) {
- this.geometryName = geometryName;
- this.format.geometryName = geometryName;
+ initLayer: function(layers) {
+ if(OpenLayers.Util.isArray(layers)) {
+ this.layers = layers;
+ this.layer = new OpenLayers.Layer.Vector.RootContainer(
+ this.id + "_container", {
+ layers: layers
+ }
+ );
+ } else {
+ this.layer = layers;
+ }
},
/**
- * Method: handleRead
- * Deal with response from the read request.
+ * Method: destroy
+ */
+ destroy: function() {
+ if(this.active && this.layers) {
+ this.map.removeLayer(this.layer);
+ }
+ OpenLayers.Control.prototype.destroy.apply(this, arguments);
+ if(this.layers) {
+ this.layer.destroy();
+ }
+ },
+
+ /**
+ * Method: activate
+ * Activates the control.
+ *
+ * Returns:
+ * {Boolean} The control was effectively activated.
+ */
+ activate: function () {
+ if (!this.active) {
+ if(this.layers) {
+ this.map.addLayer(this.layer);
+ }
+ this.handlers.feature.activate();
+ if(this.box && this.handlers.box) {
+ this.handlers.box.activate();
+ }
+ }
+ return OpenLayers.Control.prototype.activate.apply(
+ this, arguments
+ );
+ },
+
+ /**
+ * Method: deactivate
+ * Deactivates the control.
+ *
+ * Returns:
+ * {Boolean} The control was effectively deactivated.
+ */
+ deactivate: function () {
+ if (this.active) {
+ this.handlers.feature.deactivate();
+ if(this.handlers.box) {
+ this.handlers.box.deactivate();
+ }
+ if(this.layers) {
+ this.map.removeLayer(this.layer);
+ }
+ }
+ return OpenLayers.Control.prototype.deactivate.apply(
+ this, arguments
+ );
+ },
+
+ /**
+ * Method: unselectAll
+ * Unselect all selected features. To unselect all except for a single
+ * feature, set the options.except property to the feature.
*
* Parameters:
- * response - {<OpenLayers.Protocol.Response>} The response object to pass
- * to the user callback.
- * options - {Object} The user options passed to the read call.
+ * options - {Object} Optional configuration object.
*/
- handleRead: function(response, options) {
- options = OpenLayers.Util.extend({}, options);
- OpenLayers.Util.applyDefaults(options, this.options);
-
- if(options.callback) {
- var request = response.priv;
- if(request.status >= 200 && request.status < 300) {
- // success
- var result = this.parseResponse(request, options.readOptions);
- if (result && result.success !== false) {
- if (options.readOptions && options.readOptions.output == "object") {
- OpenLayers.Util.extend(response, result);
+ unselectAll: function(options) {
+ // we'll want an option to supress notification here
+ var layers = this.layers || [this.layer],
+ layer, feature, l, numExcept;
+ for(l=0; l<layers.length; ++l) {
+ layer = layers[l];
+ numExcept = 0;
+ //layer.selectedFeatures is null when layer is destroyed and
+ //one of it's preremovelayer listener calls setLayer
+ //with another layer on this control
+ if(layer.selectedFeatures != null) {
+ while(layer.selectedFeatures.length > numExcept) {
+ feature = layer.selectedFeatures[numExcept];
+ if(!options || options.except != feature) {
+ this.unselect(feature);
} else {
- response.features = result;
+ ++numExcept;
}
- response.code = OpenLayers.Protocol.Response.SUCCESS;
- } else {
- // failure (service exception)
- response.code = OpenLayers.Protocol.Response.FAILURE;
- response.error = result;
}
- } else {
- // failure
- response.code = OpenLayers.Protocol.Response.FAILURE;
}
- options.callback.call(options.scope, response);
}
},
/**
- * Method: parseResponse
- * Read HTTP response body and return features
+ * Method: clickFeature
+ * Called on click in a feature
+ * Only responds if this.hover is false.
*
* Parameters:
- * request - {XMLHttpRequest} The request object
- * options - {Object} Optional object to pass to format's read
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ clickFeature: function(feature) {
+ if(!this.hover) {
+ var selected = (OpenLayers.Util.indexOf(
+ feature.layer.selectedFeatures, feature) > -1);
+ if(selected) {
+ if(this.toggleSelect()) {
+ this.unselect(feature);
+ } else if(!this.multipleSelect()) {
+ this.unselectAll({except: feature});
+ }
+ } else {
+ if(!this.multipleSelect()) {
+ this.unselectAll({except: feature});
+ }
+ this.select(feature);
+ }
+ }
+ },
+
+ /**
+ * Method: multipleSelect
+ * Allow for multiple selected features based on <multiple> property and
+ * <multipleKey> event modifier.
*
* Returns:
- * {Object} or {Array({<OpenLayers.Feature.Vector>})} or
- * {<OpenLayers.Feature.Vector>}
- * An object with a features property, an array of features or a single
- * feature.
+ * {Boolean} Allow for multiple selected features.
*/
- parseResponse: function(request, options) {
- var doc = request.responseXML;
- if(!doc || !doc.documentElement) {
- doc = request.responseText;
+ multipleSelect: function() {
+ return this.multiple || (this.handlers.feature.evt &&
+ this.handlers.feature.evt[this.multipleKey]);
+ },
+
+ /**
+ * Method: toggleSelect
+ * Event should toggle the selected state of a feature based on <toggle>
+ * property and <toggleKey> event modifier.
+ *
+ * Returns:
+ * {Boolean} Toggle the selected state of a feature.
+ */
+ toggleSelect: function() {
+ return this.toggle || (this.handlers.feature.evt &&
+ this.handlers.feature.evt[this.toggleKey]);
+ },
+
+ /**
+ * Method: clickoutFeature
+ * Called on click outside a previously clicked (selected) feature.
+ * Only responds if this.hover is false.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Vector.Feature>}
+ */
+ clickoutFeature: function(feature) {
+ if(!this.hover && this.clickout) {
+ this.unselectAll();
}
- if(!doc || doc.length <= 0) {
- return null;
- }
- var result = (this.readFormat !== null) ? this.readFormat.read(doc) :
- this.format.read(doc, options);
- if (!this.featureNS) {
- var format = this.readFormat || this.format;
- this.featureNS = format.featureNS;
- // no need to auto-configure again on subsequent reads
- format.autoConfig = false;
- if (!this.geometryName) {
- this.setGeometryName(format.geometryName);
+ },
+
+ /**
+ * Method: overFeature
+ * Called on over a feature.
+ * Only responds if this.hover is true.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ overFeature: function(feature) {
+ var layer = feature.layer;
+ if(this.hover) {
+ if(this.highlightOnly) {
+ this.highlight(feature);
+ } else if(OpenLayers.Util.indexOf(
+ layer.selectedFeatures, feature) == -1) {
+ this.select(feature);
}
}
- return result;
},
/**
- * Method: commit
- * Given a list of feature, assemble a batch request for update, create,
- * and delete transactions. A commit call on the prototype amounts
- * to writing a WFS transaction - so the write method on the format
- * is used.
+ * Method: outFeature
+ * Called on out of a selected feature.
+ * Only responds if this.hover is true.
*
* Parameters:
- * features - {Array(<OpenLayers.Feature.Vector>)}
- * options - {Object}
- *
- * Valid options properties:
- * nativeElements - {Array({Object})} Array of objects with information for writing
- * out <Native> elements, these objects have vendorId, safeToIgnore and
- * value properties. The <Native> element is intended to allow access to
- * vendor specific capabilities of any particular web feature server or
- * datastore.
- *
- * Returns:
- * {<OpenLayers.Protocol.Response>} A response object with a features
- * property containing any insertIds and a priv property referencing
- * the XMLHttpRequest object.
+ * feature - {<OpenLayers.Feature.Vector>}
*/
- commit: function(features, options) {
+ outFeature: function(feature) {
+ if(this.hover) {
+ if(this.highlightOnly) {
+ // we do nothing if we're not the last highlighter of the
+ // feature
+ if(feature._lastHighlighter == this.id) {
+ // if another select control had highlighted the feature before
+ // we did it ourself then we use that control to highlight the
+ // feature as it was before we highlighted it, else we just
+ // unhighlight it
+ if(feature._prevHighlighter &&
+ feature._prevHighlighter != this.id) {
+ delete feature._lastHighlighter;
+ var control = this.map.getControl(
+ feature._prevHighlighter);
+ if(control) {
+ control.highlight(feature);
+ }
+ } else {
+ this.unhighlight(feature);
+ }
+ }
+ } else {
+ this.unselect(feature);
+ }
+ }
+ },
- options = OpenLayers.Util.extend({}, options);
- OpenLayers.Util.applyDefaults(options, this.options);
-
- var response = new OpenLayers.Protocol.Response({
- requestType: "commit",
- reqFeatures: features
+ /**
+ * Method: highlight
+ * Redraw feature with the select style.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ highlight: function(feature) {
+ var layer = feature.layer;
+ var cont = this.events.triggerEvent("beforefeaturehighlighted", {
+ feature : feature
});
- response.priv = OpenLayers.Request.POST({
- url: options.url,
- headers: options.headers,
- data: this.format.write(features, options),
- callback: this.createCallback(this.handleCommit, response, options)
- });
-
- return response;
+ if(cont !== false) {
+ feature._prevHighlighter = feature._lastHighlighter;
+ feature._lastHighlighter = this.id;
+ var style = this.selectStyle || this.renderIntent;
+ layer.drawFeature(feature, style);
+ this.events.triggerEvent("featurehighlighted", {feature : feature});
+ }
},
+
+ /**
+ * Method: unhighlight
+ * Redraw feature with the "default" style
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ unhighlight: function(feature) {
+ var layer = feature.layer;
+ // three cases:
+ // 1. there's no other highlighter, in that case _prev is undefined,
+ // and we just need to undef _last
+ // 2. another control highlighted the feature after we did it, in
+ // that case _last references this other control, and we just
+ // need to undef _prev
+ // 3. another control highlighted the feature before we did it, in
+ // that case _prev references this other control, and we need to
+ // set _last to _prev and undef _prev
+ if(feature._prevHighlighter == undefined) {
+ delete feature._lastHighlighter;
+ } else if(feature._prevHighlighter == this.id) {
+ delete feature._prevHighlighter;
+ } else {
+ feature._lastHighlighter = feature._prevHighlighter;
+ delete feature._prevHighlighter;
+ }
+ layer.drawFeature(feature, feature.style || feature.layer.style ||
+ "default");
+ this.events.triggerEvent("featureunhighlighted", {feature : feature});
+ },
/**
- * Method: handleCommit
- * Called when the commit request returns.
+ * Method: select
+ * Add feature to the layer's selectedFeature array, render the feature as
+ * selected, and call the onSelect function.
*
* Parameters:
- * response - {<OpenLayers.Protocol.Response>} The response object to pass
- * to the user callback.
- * options - {Object} The user options passed to the commit call.
+ * feature - {<OpenLayers.Feature.Vector>}
*/
- handleCommit: function(response, options) {
- if(options.callback) {
- var request = response.priv;
-
- // ensure that we have an xml doc
- var data = request.responseXML;
- if(!data || !data.documentElement) {
- data = request.responseText;
+ select: function(feature) {
+ var cont = this.onBeforeSelect.call(this.scope, feature);
+ var layer = feature.layer;
+ if(cont !== false) {
+ cont = layer.events.triggerEvent("beforefeatureselected", {
+ feature: feature
+ });
+ if(cont !== false) {
+ layer.selectedFeatures.push(feature);
+ this.highlight(feature);
+ // if the feature handler isn't involved in the feature
+ // selection (because the box handler is used or the
+ // feature is selected programatically) we fake the
+ // feature handler to allow unselecting on click
+ if(!this.handlers.feature.lastFeature) {
+ this.handlers.feature.lastFeature = layer.selectedFeatures[0];
+ }
+ layer.events.triggerEvent("featureselected", {feature: feature});
+ this.onSelect.call(this.scope, feature);
}
-
- var obj = this.format.read(data) || {};
-
- response.insertIds = obj.insertIds || [];
- if (obj.success) {
- response.code = OpenLayers.Protocol.Response.SUCCESS;
- } else {
- response.code = OpenLayers.Protocol.Response.FAILURE;
- response.error = obj;
- }
- options.callback.call(options.scope, response);
}
},
+
+ /**
+ * Method: unselect
+ * Remove feature from the layer's selectedFeature array, render the feature as
+ * normal, and call the onUnselect function.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ unselect: function(feature) {
+ var layer = feature.layer;
+ // Store feature style for restoration later
+ this.unhighlight(feature);
+ OpenLayers.Util.removeItem(layer.selectedFeatures, feature);
+ layer.events.triggerEvent("featureunselected", {feature: feature});
+ this.onUnselect.call(this.scope, feature);
+ },
/**
- * Method: filterDelete
- * Send a request that deletes all features by their filter.
- *
+ * Method: selectBox
+ * Callback from the handlers.box set up when <box> selection is true
+ * on.
+ *
* Parameters:
- * filter - {<OpenLayers.Filter>} filter
+ * position - {<OpenLayers.Bounds> || <OpenLayers.Pixel> }
*/
- filterDelete: function(filter, options) {
- options = OpenLayers.Util.extend({}, options);
- OpenLayers.Util.applyDefaults(options, this.options);
-
- var response = new OpenLayers.Protocol.Response({
- requestType: "commit"
- });
-
- var root = this.format.createElementNSPlus("wfs:Transaction", {
- attributes: {
- service: "WFS",
- version: this.version
+ selectBox: function(position) {
+ if (position instanceof OpenLayers.Bounds) {
+ var minXY = this.map.getLonLatFromPixel({
+ x: position.left,
+ y: position.bottom
+ });
+ var maxXY = this.map.getLonLatFromPixel({
+ x: position.right,
+ y: position.top
+ });
+ var bounds = new OpenLayers.Bounds(
+ minXY.lon, minXY.lat, maxXY.lon, maxXY.lat
+ );
+
+ // if multiple is false, first deselect currently selected features
+ if (!this.multipleSelect()) {
+ this.unselectAll();
}
- });
-
- var deleteNode = this.format.createElementNSPlus("wfs:Delete", {
- attributes: {
- typeName: (options.featureNS ? this.featurePrefix + ":" : "") +
- options.featureType
+
+ // because we're using a box, we consider we want multiple selection
+ var prevMultiple = this.multiple;
+ this.multiple = true;
+ var layers = this.layers || [this.layer];
+ this.events.triggerEvent("boxselectionstart", {layers: layers});
+ var layer;
+ for(var l=0; l<layers.length; ++l) {
+ layer = layers[l];
+ for(var i=0, len = layer.features.length; i<len; ++i) {
+ var feature = layer.features[i];
+ // check if the feature is displayed
+ if (!feature.getVisibility()) {
+ continue;
+ }
+
+ if (this.geometryTypes == null || OpenLayers.Util.indexOf(
+ this.geometryTypes, feature.geometry.CLASS_NAME) > -1) {
+ if (bounds.toGeometry().intersects(feature.geometry)) {
+ if (OpenLayers.Util.indexOf(layer.selectedFeatures, feature) == -1) {
+ this.select(feature);
+ }
+ }
+ }
+ }
}
- });
-
- if(options.featureNS) {
- deleteNode.setAttribute("xmlns:" + this.featurePrefix, options.featureNS);
+ this.multiple = prevMultiple;
+ this.events.triggerEvent("boxselectionend", {layers: layers});
}
- var filterNode = this.format.writeNode("ogc:Filter", filter);
-
- deleteNode.appendChild(filterNode);
-
- root.appendChild(deleteNode);
-
- var data = OpenLayers.Format.XML.prototype.write.apply(
- this.format, [root]
- );
-
- return OpenLayers.Request.POST({
- url: this.url,
- callback : options.callback || function(){},
- data: data
- });
-
},
+ /**
+ * Method: setMap
+ * Set the map property for the control.
+ *
+ * Parameters:
+ * map - {<OpenLayers.Map>}
+ */
+ setMap: function(map) {
+ this.handlers.feature.setMap(map);
+ if (this.box) {
+ this.handlers.box.setMap(map);
+ }
+ OpenLayers.Control.prototype.setMap.apply(this, arguments);
+ },
+
/**
- * Method: abort
- * Abort an ongoing request, the response object passed to
- * this method must come from this protocol (as a result
- * of a read, or commit operation).
+ * APIMethod: setLayer
+ * Attach a new layer to the control, overriding any existing layers.
*
* Parameters:
- * response - {<OpenLayers.Protocol.Response>}
+ * layers - Array of {<OpenLayers.Layer.Vector>} or a single
+ * {<OpenLayers.Layer.Vector>}
*/
- abort: function(response) {
- if (response) {
- response.priv.abort();
+ setLayer: function(layers) {
+ var isActive = this.active;
+ this.unselectAll();
+ this.deactivate();
+ if(this.layers) {
+ this.layer.destroy();
+ this.layers = null;
}
+ this.initLayer(layers);
+ this.handlers.feature.layer = this.layer;
+ if (isActive) {
+ this.activate();
+ }
},
-
- CLASS_NAME: "OpenLayers.Protocol.WFS.v1"
+
+ CLASS_NAME: "OpenLayers.Control.SelectFeature"
});
/* ======================================================================
OpenLayers/Handler/Point.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -51255,16 +52575,10 @@
* no point will be added. Default value is 5.
*/
pixelTolerance: 5,
/**
- * Property: touch
- * {Boolean} Indcates the support of touch events.
- */
- touch: false,
-
- /**
* Property: lastTouchPx
* {<OpenLayers.Pixel>} The last pixel used to know the distance between
* two touches (for double touch).
*/
lastTouchPx: null,
@@ -51357,11 +52671,10 @@
if (this.layer.map != null) {
this.destroyFeature(true);
this.layer.destroy(false);
}
this.layer = null;
- this.touch = false;
return true;
},
/**
* Method: destroyFeature
@@ -51524,22 +52837,11 @@
*
* Returns:
* {Boolean} Allow event propagation
*/
touchstart: function(evt) {
- if (!this.touch) {
- this.touch = true;
- // unregister mouse listeners
- this.map.events.un({
- mousedown: this.mousedown,
- mouseup: this.mouseup,
- mousemove: this.mousemove,
- click: this.click,
- dblclick: this.dblclick,
- scope: this
- });
- }
+ this.startTouch();
this.lastTouchPx = evt.xy;
return this.down(evt);
},
/**
@@ -51717,11 +53019,11 @@
});
/* ======================================================================
OpenLayers/Handler/Path.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -51990,10 +53292,20 @@
var components = geometry.components;
var index = this.getCurrentPointIndex() - 1;
var target = components[index];
var undone = geometry.removeComponent(target);
if (undone) {
+ // On touch devices, set the current ("mouse location") point to
+ // match the last digitized point.
+ if (this.touch && index > 0) {
+ components = geometry.components; // safety
+ var lastpt = components[index - 1];
+ var curptidx = this.getCurrentPointIndex();
+ var curpt = components[curptidx];
+ curpt.x = lastpt.x;
+ curpt.y = lastpt.y;
+ }
if (!this.redoStack) {
this.redoStack = [];
}
this.redoStack.push(target);
this.drawFeature();
@@ -52325,11 +53637,11 @@
};
/* ======================================================================
OpenLayers/Control/CacheWrite.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -52586,11 +53898,11 @@
/* ======================================================================
OpenLayers/Control/PanPanel.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -52663,11 +53975,11 @@
});
/* ======================================================================
OpenLayers/Control/Attribution.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -52688,20 +54000,29 @@
/**
* APIProperty: separator
* {String} String used to separate layers.
*/
separator: ", ",
-
+
/**
* APIProperty: template
- * {String} Template for the attribution. This has to include the substring
- * "${layers}", which will be replaced by the layer specific
+ * {String} Template for the global attribution markup. This has to include the
+ * substring "${layers}", which will be replaced by the layer specific
* attributions, separated by <separator>. The default is "${layers}".
*/
template: "${layers}",
-
+
/**
+ * APIProperty: layerTemplate
+ * {String} Template for the layer specific attribution. This has to include
+ * the substrings "${href}" and "${title}", which will be replaced by
+ * the layer specific attribution object properties.
+ * The default is '<a href="${href}" target="_blank">${title}</a>'.
+ */
+ layerTemplate: '<a href="${href}" target="_blank">${title}</a>',
+
+ /**
* Constructor: OpenLayers.Control.Attribution
*
* Parameters:
* options - {Object} Options for control.
*/
@@ -52747,19 +54068,23 @@
/**
* Method: updateAttribution
* Update attribution string.
*/
updateAttribution: function() {
- var attributions = [];
+ var attributions = [], attribution;
if (this.map && this.map.layers) {
for(var i=0, len=this.map.layers.length; i<len; i++) {
var layer = this.map.layers[i];
if (layer.attribution && layer.getVisibility()) {
+ attribution = (typeof layer.attribution == "object") ?
+ OpenLayers.String.format(
+ this.layerTemplate, layer.attribution) :
+ layer.attribution;
// add attribution only if attribution text is unique
if (OpenLayers.Util.indexOf(
- attributions, layer.attribution) === -1) {
- attributions.push( layer.attribution );
+ attributions, attribution) === -1) {
+ attributions.push( attribution );
}
}
}
this.div.innerHTML = OpenLayers.String.format(this.template, {
layers: attributions.join(this.separator)
@@ -52771,11 +54096,11 @@
});
/* ======================================================================
OpenLayers/Kinetic.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -52950,14 +54275,165 @@
},
CLASS_NAME: "OpenLayers.Kinetic"
});
/* ======================================================================
+ OpenLayers/Format/WFSCapabilities/v2_0_0.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/Format/WFSCapabilities.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFSCapabilities.v2_0_0
+ * Abstract class not to be instantiated directly.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.XML>
+ */
+OpenLayers.Format.WFSCapabilities.v2_0_0 = OpenLayers.Class(
+ OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ wfs: "http://www.opengis.net/wfs/2.0",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ ows: "http://www.opengis.net/ows/1.1"
+ },
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
+ },
+
+ /**
+ * APIProperty: errorProperty
+ * {String} Which property of the returned object to check for in order to
+ * determine whether or not parsing has failed. In the case that the
+ * errorProperty is undefined on the returned object, the document will be
+ * run through an OGCExceptionReport parser.
+ */
+ errorProperty: "featureTypeList",
+
+ /**
+ * Property: defaultPrefix
+ */
+ defaultPrefix: "wfs",
+
+ /**
+ * Constructor: OpenLayers.Format.WFSCapabilities.v1_1
+ * Create an instance of one of the subclasses.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Read capabilities data from a string, and return a list of layers.
+ *
+ * Parameters:
+ * data - {String} or {DOMElement} data to read/parse.
+ *
+ * Returns:
+ * {Array} List of named layers.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ var raw = data;
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var capabilities = {};
+ this.readNode(data, capabilities);
+ return capabilities;
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wfs": {
+ "WFS_Capabilities": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "FeatureTypeList": function(node, request) {
+ request.featureTypeList = {
+ featureTypes: []
+ };
+ this.readChildNodes(node, request.featureTypeList);
+ },
+ "FeatureType": function(node, featureTypeList) {
+ var featureType = {};
+ this.readChildNodes(node, featureType);
+ featureTypeList.featureTypes.push(featureType);
+ },
+ "Name": function(node, obj) {
+ var name = this.getChildValue(node);
+ if(name) {
+ var parts = name.split(":");
+ obj.name = parts.pop();
+ if(parts.length > 0) {
+ obj.featureNS = this.lookupNamespaceURI(node, parts[0]);
+ }
+ }
+ },
+ "Title": function(node, obj) {
+ var title = this.getChildValue(node);
+ if(title) {
+ obj.title = title;
+ }
+ },
+ "Abstract": function(node, obj) {
+ var abst = this.getChildValue(node);
+ if(abst) {
+ obj["abstract"] = abst;
+ }
+ },
+ "DefaultCRS": function(node, obj) {
+ var defaultCRS = this.getChildValue(node);
+ if (defaultCRS) {
+ obj.srs = defaultCRS;
+ }
+ }
+ },
+ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers.ows
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v2_0_0"
+
+});
+/* ======================================================================
OpenLayers/Format/WPSExecute.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -53352,11 +54828,11 @@
});
/* ======================================================================
OpenLayers/Layer/GeoRSS.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -53621,11 +55097,11 @@
});
/* ======================================================================
OpenLayers/Format/WMSCapabilities/v1_3.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -53636,10 +55112,18 @@
* Class: OpenLayers.Format.WMSCapabilities/v1_3
* Abstract base class for WMS Capabilities version 1.3.X.
* SLD 1.1.0 adds in the extra operations DescribeLayer and GetLegendGraphic,
* see: http://schemas.opengis.net/sld/1.1.0/sld_capabilities.xsd
*
+ * Note on <MinScaleDenominator> and <MaxScaleDenominator> parsing: If
+ * the <MinScaleDenominator> value is set to "0", no maxScale will be
+ * set on the layer object. If the <MaxScaleDenominator> value is set to
+ * "Infinity", no minScale will be set. This makes it easy to create proper
+ * {<OpenLayers.Layer.WMS>} configurations directly from the layer object
+ * literals returned by this format, because no minScale/maxScale modifications
+ * need to be made.
+ *
* Inherits from:
* - <OpenLayers.Format.WMSCapabilities.v1>
*/
OpenLayers.Format.WMSCapabilities.v1_3 = OpenLayers.Class(
OpenLayers.Format.WMSCapabilities.v1, {
@@ -53692,14 +55176,20 @@
},
"northBoundLatitude": function(node, obj) {
obj[3] = this.getChildValue(node);
},
"MinScaleDenominator": function(node, obj) {
- obj.maxScale = parseFloat(this.getChildValue(node)).toPrecision(16);
+ var maxScale = parseFloat(this.getChildValue(node)).toPrecision(16);
+ if (maxScale != 0) {
+ obj.maxScale = maxScale;
+ }
},
"MaxScaleDenominator": function(node, obj) {
- obj.minScale = parseFloat(this.getChildValue(node)).toPrecision(16);
+ var minScale = parseFloat(this.getChildValue(node)).toPrecision(16);
+ if (minScale != Number.POSITIVE_INFINITY) {
+ obj.minScale = minScale;
+ }
},
"Dimension": function(node, obj) {
// dimension has extra attributes: default, multipleValues,
// nearestValue, current which used to be part of Extent. It now
// also contains the values.
@@ -53753,11 +55243,11 @@
});
/* ======================================================================
OpenLayers/Format/SOSCapabilities.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -53805,11 +55295,11 @@
});
/* ======================================================================
OpenLayers/Layer/WMS.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -54004,11 +55494,11 @@
* parameters.
*/
getURL: function (bounds) {
bounds = this.adjustBounds(bounds);
- var imageSize = this.getImageSize();
+ var imageSize = this.getImageSize(bounds);
var newParams = {};
// WMS 1.3 introduced axis order
var reverseAxisOrder = this.reverseAxisOrder();
newParams.BBOX = this.encodeBBOX ?
bounds.toBBOX(null, reverseAxisOrder) :
@@ -54076,11 +55566,11 @@
});
/* ======================================================================
OpenLayers/Layer/KaMap.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -54272,11 +55762,11 @@
});
/* ======================================================================
OpenLayers/Format/WMC.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -54326,20 +55816,22 @@
name: layer.params["LAYERS"],
title: layer.name,
"abstract": layer.metadata["abstract"],
dataURL: layer.metadata.dataURL,
metadataURL: layer.metadataURL,
+ attribution: layer.attribution,
server: {
- version: layer.params["VERSION"],
+ version: layer.params["VERSION"],
url: layer.url
},
maxExtent: layer.maxExtent,
transparent: layer.params["TRANSPARENT"],
numZoomLevels: layer.numZoomLevels,
units: layer.units,
isBaseLayer: layer.isBaseLayer,
opacity: layer.opacity == 1 ? undefined : layer.opacity,
+ gutter: layer.gutter == 0 ? undefined : layer.gutter,
displayInLayerSwitcher: layer.displayInLayerSwitcher,
singleTile: layer.singleTile,
tileSize: (layer.singleTile || !layer.tileSize) ?
undefined : {width: layer.tileSize.w, height: layer.tileSize.h},
minScale : (layer.options.resolutions ||
@@ -54458,11 +55950,11 @@
});
/* ======================================================================
OpenLayers/Format/WMC/v1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -54698,12 +56190,19 @@
*/
read_ol_tileSize: function(layerContext, node) {
var obj = {"width": node.getAttribute("width"), "height": node.getAttribute("height")};
layerContext.tileSize = obj;
},
-
+
/**
+ * Method: read_ol_gutter
+ */
+ read_ol_gutter: function(layerContext, node) {
+ layerContext.gutter = parseInt(this.getChildValue(node));
+ },
+
+ /**
* Method: read_ol_isBaseLayer
*/
read_ol_isBaseLayer: function(layerContext, node) {
layerContext.isBaseLayer = (this.getChildValue(node) == "true");
},
@@ -54714,10 +56213,18 @@
read_ol_displayInLayerSwitcher: function(layerContext, node) {
layerContext.displayInLayerSwitcher = (this.getChildValue(node) == "true");
},
/**
+ * Method: read_ol_attribution
+ */
+ read_ol_attribution: function(obj, node) {
+ obj.attribution = {};
+ this.runChildNodes(obj.attribution, node);
+ },
+
+ /**
* Method: read_wmc_Server
*/
read_wmc_Server: function(layerContext, node) {
layerContext.version = node.getAttribute("version");
layerContext.url = this.getOnlineResource_href(node);
@@ -55416,12 +56923,42 @@
node.appendChild(this.write_wmc_URLType("MetadataURL", context.metadataURL));
}
return node;
},
-
+
/**
+ * Method: write_ol_attribution
+ * Create an attribution node given a layer attribution object.
+ *
+ * Parameters:
+ * attribution - {<Object>} or {<String>} A layer attribution object or string
+ *
+ * Returns:
+ * {Element} A ol:attribution element node.
+ */
+ write_ol_attribution: function(attribution) {
+ if (typeof attribution == "string") {
+ attribution = {title: attribution};
+ }
+ var node = this.createElementNS(this.namespaces.ol, "ol:attribution");
+ node.appendChild(this.createElementDefaultNS(
+ "Title", attribution.title
+ ));
+ if (attribution.href) {
+ node.appendChild(this.write_wmc_OnlineResource(attribution.href));
+ }
+ if (attribution.logo) {
+ node.appendChild(
+ this.write_wmc_URLType("LogoURL",
+ attribution.logo.href, attribution.logo)
+ );
+ }
+ return node;
+ },
+
+ /**
* Method: write_wmc_LayerExtension
* Add OpenLayers specific layer parameters to an Extension element.
*
* Parameters:
* context - {Object} A layer context object.
@@ -55449,23 +56986,28 @@
this.namespaces.ol, "ol:tileSize"
);
this.setAttributes(size, context.tileSize);
node.appendChild(size);
}
-
+
var properties = [
"transparent", "numZoomLevels", "units", "isBaseLayer",
- "opacity", "displayInLayerSwitcher", "singleTile"
+ "opacity", "displayInLayerSwitcher", "singleTile", "gutter"
];
var child;
for(var i=0, len=properties.length; i<len; ++i) {
child = this.createOLPropertyNode(context, properties[i]);
if(child) {
node.appendChild(child);
}
}
+ if (context.attribution) {
+ var attribution = this.write_ol_attribution(context.attribution);
+ node.appendChild(attribution);
+ }
+
return node;
},
/**
* Method: createOLPropertyNode
@@ -55729,11 +57271,11 @@
});
/* ======================================================================
OpenLayers/Format/WMC/v1_1_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -55882,11 +57424,11 @@
});
/* ======================================================================
OpenLayers/Format/XLS.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -55954,11 +57496,11 @@
});
/* ======================================================================
OpenLayers/Format/XLS/v1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -56262,11 +57804,11 @@
});
/* ======================================================================
OpenLayers/Format/XLS/v1_1_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -56311,14 +57853,416 @@
});
// Support non standard implementation
OpenLayers.Format.XLS.v1_1 = OpenLayers.Format.XLS.v1_1_0;
/* ======================================================================
+ OpenLayers/Format/JSON.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. */
+
+/**
+ * Note:
+ * This work draws heavily from the public domain JSON serializer/deserializer
+ * at http://www.json.org/json.js. Rewritten so that it doesn't modify
+ * basic data prototypes.
+ */
+
+/**
+ * @requires OpenLayers/Format.js
+ */
+
+/**
+ * Class: OpenLayers.Format.JSON
+ * A parser to read/write JSON safely. Create a new instance with the
+ * <OpenLayers.Format.JSON> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format>
+ */
+OpenLayers.Format.JSON = OpenLayers.Class(OpenLayers.Format, {
+
+ /**
+ * APIProperty: indent
+ * {String} For "pretty" printing, the indent string will be used once for
+ * each indentation level.
+ */
+ indent: " ",
+
+ /**
+ * APIProperty: space
+ * {String} For "pretty" printing, the space string will be used after
+ * the ":" separating a name/value pair.
+ */
+ space: " ",
+
+ /**
+ * APIProperty: newline
+ * {String} For "pretty" printing, the newline string will be used at the
+ * end of each name/value pair or array item.
+ */
+ newline: "\n",
+
+ /**
+ * Property: level
+ * {Integer} For "pretty" printing, this is incremented/decremented during
+ * serialization.
+ */
+ level: 0,
+
+ /**
+ * Property: pretty
+ * {Boolean} Serialize with extra whitespace for structure. This is set
+ * by the <write> method.
+ */
+ pretty: false,
+
+ /**
+ * Property: nativeJSON
+ * {Boolean} Does the browser support native json?
+ */
+ nativeJSON: (function() {
+ return !!(window.JSON && typeof JSON.parse == "function" && typeof JSON.stringify == "function");
+ })(),
+
+ /**
+ * Constructor: OpenLayers.Format.JSON
+ * Create a new parser for JSON.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * APIMethod: read
+ * Deserialize a json string.
+ *
+ * Parameters:
+ * json - {String} A JSON string
+ * filter - {Function} A function which will be called for every key and
+ * value at every level of the final result. Each value will be
+ * replaced by the result of the filter function. This can be used to
+ * reform generic objects into instances of classes, or to transform
+ * date strings into Date objects.
+ *
+ * Returns:
+ * {Object} An object, array, string, or number .
+ */
+ read: function(json, filter) {
+ var object;
+ if (this.nativeJSON) {
+ object = JSON.parse(json, filter);
+ } else try {
+ /**
+ * Parsing happens in three stages. In the first stage, we run the
+ * text against a regular expression which looks for non-JSON
+ * characters. We are especially concerned with '()' and 'new'
+ * because they can cause invocation, and '=' because it can
+ * cause mutation. But just to be safe, we will reject all
+ * unexpected characters.
+ */
+ if (/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g, '@').
+ replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+ replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+ /**
+ * In the second stage we use the eval function to compile the
+ * text into a JavaScript structure. The '{' operator is
+ * subject to a syntactic ambiguity in JavaScript - it can
+ * begin a block or an object literal. We wrap the text in
+ * parens to eliminate the ambiguity.
+ */
+ object = eval('(' + json + ')');
+
+ /**
+ * In the optional third stage, we recursively walk the new
+ * structure, passing each name/value pair to a filter
+ * function for possible transformation.
+ */
+ if(typeof filter === 'function') {
+ function walk(k, v) {
+ if(v && typeof v === 'object') {
+ for(var i in v) {
+ if(v.hasOwnProperty(i)) {
+ v[i] = walk(i, v[i]);
+ }
+ }
+ }
+ return filter(k, v);
+ }
+ object = walk('', object);
+ }
+ }
+ } catch(e) {
+ // Fall through if the regexp test fails.
+ }
+
+ if(this.keepData) {
+ this.data = object;
+ }
+
+ return object;
+ },
+
+ /**
+ * APIMethod: write
+ * Serialize an object into a JSON string.
+ *
+ * Parameters:
+ * value - {String} The object, array, string, number, boolean or date
+ * to be serialized.
+ * pretty - {Boolean} Structure the output with newlines and indentation.
+ * Default is false.
+ *
+ * Returns:
+ * {String} The JSON string representation of the input value.
+ */
+ write: function(value, pretty) {
+ this.pretty = !!pretty;
+ var json = null;
+ var type = typeof value;
+ if(this.serialize[type]) {
+ try {
+ json = (!this.pretty && this.nativeJSON) ?
+ JSON.stringify(value) :
+ this.serialize[type].apply(this, [value]);
+ } catch(err) {
+ OpenLayers.Console.error("Trouble serializing: " + err);
+ }
+ }
+ return json;
+ },
+
+ /**
+ * Method: writeIndent
+ * Output an indentation string depending on the indentation level.
+ *
+ * Returns:
+ * {String} An appropriate indentation string.
+ */
+ writeIndent: function() {
+ var pieces = [];
+ if(this.pretty) {
+ for(var i=0; i<this.level; ++i) {
+ pieces.push(this.indent);
+ }
+ }
+ return pieces.join('');
+ },
+
+ /**
+ * Method: writeNewline
+ * Output a string representing a newline if in pretty printing mode.
+ *
+ * Returns:
+ * {String} A string representing a new line.
+ */
+ writeNewline: function() {
+ return (this.pretty) ? this.newline : '';
+ },
+
+ /**
+ * Method: writeSpace
+ * Output a string representing a space if in pretty printing mode.
+ *
+ * Returns:
+ * {String} A space.
+ */
+ writeSpace: function() {
+ return (this.pretty) ? this.space : '';
+ },
+
+ /**
+ * Property: serialize
+ * Object with properties corresponding to the serializable data types.
+ * Property values are functions that do the actual serializing.
+ */
+ serialize: {
+ /**
+ * Method: serialize.object
+ * Transform an object into a JSON string.
+ *
+ * Parameters:
+ * object - {Object} The object to be serialized.
+ *
+ * Returns:
+ * {String} A JSON string representing the object.
+ */
+ 'object': function(object) {
+ // three special objects that we want to treat differently
+ if(object == null) {
+ return "null";
+ }
+ if(object.constructor == Date) {
+ return this.serialize.date.apply(this, [object]);
+ }
+ if(object.constructor == Array) {
+ return this.serialize.array.apply(this, [object]);
+ }
+ var pieces = ['{'];
+ this.level += 1;
+ var key, keyJSON, valueJSON;
+
+ var addComma = false;
+ for(key in object) {
+ if(object.hasOwnProperty(key)) {
+ // recursive calls need to allow for sub-classing
+ keyJSON = OpenLayers.Format.JSON.prototype.write.apply(this,
+ [key, this.pretty]);
+ valueJSON = OpenLayers.Format.JSON.prototype.write.apply(this,
+ [object[key], this.pretty]);
+ if(keyJSON != null && valueJSON != null) {
+ if(addComma) {
+ pieces.push(',');
+ }
+ pieces.push(this.writeNewline(), this.writeIndent(),
+ keyJSON, ':', this.writeSpace(), valueJSON);
+ addComma = true;
+ }
+ }
+ }
+
+ this.level -= 1;
+ pieces.push(this.writeNewline(), this.writeIndent(), '}');
+ return pieces.join('');
+ },
+
+ /**
+ * Method: serialize.array
+ * Transform an array into a JSON string.
+ *
+ * Parameters:
+ * array - {Array} The array to be serialized
+ *
+ * Returns:
+ * {String} A JSON string representing the array.
+ */
+ 'array': function(array) {
+ var json;
+ var pieces = ['['];
+ this.level += 1;
+
+ for(var i=0, len=array.length; i<len; ++i) {
+ // recursive calls need to allow for sub-classing
+ json = OpenLayers.Format.JSON.prototype.write.apply(this,
+ [array[i], this.pretty]);
+ if(json != null) {
+ if(i > 0) {
+ pieces.push(',');
+ }
+ pieces.push(this.writeNewline(), this.writeIndent(), json);
+ }
+ }
+
+ this.level -= 1;
+ pieces.push(this.writeNewline(), this.writeIndent(), ']');
+ return pieces.join('');
+ },
+
+ /**
+ * Method: serialize.string
+ * Transform a string into a JSON string.
+ *
+ * Parameters:
+ * string - {String} The string to be serialized
+ *
+ * Returns:
+ * {String} A JSON string representing the string.
+ */
+ 'string': function(string) {
+ // If the string contains no control characters, no quote characters, and no
+ // backslash characters, then we can simply slap some quotes around it.
+ // Otherwise we must also replace the offending characters with safe
+ // sequences.
+ var m = {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ };
+ if(/["\\\x00-\x1f]/.test(string)) {
+ return '"' + string.replace(/([\x00-\x1f\\"])/g, function(a, b) {
+ var c = m[b];
+ if(c) {
+ return c;
+ }
+ c = b.charCodeAt();
+ return '\\u00' +
+ Math.floor(c / 16).toString(16) +
+ (c % 16).toString(16);
+ }) + '"';
+ }
+ return '"' + string + '"';
+ },
+
+ /**
+ * Method: serialize.number
+ * Transform a number into a JSON string.
+ *
+ * Parameters:
+ * number - {Number} The number to be serialized.
+ *
+ * Returns:
+ * {String} A JSON string representing the number.
+ */
+ 'number': function(number) {
+ return isFinite(number) ? String(number) : "null";
+ },
+
+ /**
+ * Method: serialize.boolean
+ * Transform a boolean into a JSON string.
+ *
+ * Parameters:
+ * bool - {Boolean} The boolean to be serialized.
+ *
+ * Returns:
+ * {String} A JSON string representing the boolean.
+ */
+ 'boolean': function(bool) {
+ return String(bool);
+ },
+
+ /**
+ * Method: serialize.object
+ * Transform a date into a JSON string.
+ *
+ * Parameters:
+ * date - {Date} The date to be serialized.
+ *
+ * Returns:
+ * {String} A JSON string representing the date.
+ */
+ 'date': function(date) {
+ function format(number) {
+ // Format integers to have at least two digits.
+ return (number < 10) ? '0' + number : number;
+ }
+ return '"' + date.getFullYear() + '-' +
+ format(date.getMonth() + 1) + '-' +
+ format(date.getDate()) + 'T' +
+ format(date.getHours()) + ':' +
+ format(date.getMinutes()) + ':' +
+ format(date.getSeconds()) + '"';
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Format.JSON"
+
+});
+/* ======================================================================
OpenLayers/Renderer/SVG.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -56971,10 +58915,13 @@
if (drawOutline) {
var outlineStyle = OpenLayers.Util.extend({}, style);
outlineStyle.fontColor = outlineStyle.labelOutlineColor;
outlineStyle.fontStrokeColor = outlineStyle.labelOutlineColor;
outlineStyle.fontStrokeWidth = style.labelOutlineWidth;
+ if (style.labelOutlineOpacity) {
+ outlineStyle.fontOpacity = style.labelOutlineOpacity;
+ }
delete outlineStyle.labelOutlineWidth;
this.drawText(featureId, outlineStyle, location);
}
var resolution = this.getResolution();
@@ -57327,11 +59274,11 @@
};
/* ======================================================================
OpenLayers/Format/WMSDescribeLayer.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -57384,11 +59331,11 @@
});
/* ======================================================================
OpenLayers/Format/WMSDescribeLayer/v1_1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -57507,14 +59454,829 @@
// Version alias - workaround for http://trac.osgeo.org/mapserver/ticket/2257
OpenLayers.Format.WMSDescribeLayer.v1_1_0 =
OpenLayers.Format.WMSDescribeLayer.v1_1_1;
/* ======================================================================
+ OpenLayers/Control/TextButtonPanel.js
+ ====================================================================== */
+
+/* Copyright (c) 2006-2012 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/Control/Panel.js
+ */
+
+/**
+ * Class: OpenLayers.Control.TextButtonPanel
+ * The TextButtonPanel is a panel designed primarily to hold TextButton
+ * controls. By default it has a displayClass of olControlTextButtonPanel,
+ * which hooks it to a set of text-appropriate styles in the default stylesheet.
+ *
+ * Inherits from:
+ * - <OpenLayers.Control.Panel>
+ */
+OpenLayers.Control.TextButtonPanel = OpenLayers.Class(
+ OpenLayers.Control.Panel, {
+
+ /**
+ * APIProperty: vertical
+ * {Boolean} Whether the button strip should appear vertically on the map.
+ */
+ vertical: false,
+
+ /**
+ * APIProperty: additionalClass
+ * {String} An additional class to be applied in addition to
+ * .olControlTextButtonPanel to allow for non-default positioning.
+ */
+ additionalClass: null,
+
+ /**
+ * Constructor: OpenLayers.Control.TextButtonPanel
+ * Create a panel for holding text-based button controls
+ *
+ * Parameters:
+ * options - {Object}
+ */
+
+ /**
+ * Method: draw
+ * Overrides the draw method in <OpenLayers.Control.Panel> by applying
+ * up to two additional CSS classes
+ * Returns:
+ * {DOMElement}
+ */
+ draw: function() {
+ OpenLayers.Control.Panel.prototype.draw.apply(this, arguments);
+ this.setOrientationClass();
+ this.setAdditionalClass();
+ return this.div;
+ },
+
+ /**
+ * Method: redraw
+ * Overrides the redraw method in <OpenLayers.Control.Panel> by setting
+ * the orientation class.
+ */
+ redraw: function() {
+ OpenLayers.Control.Panel.prototype.redraw.apply(this, arguments);
+ this.setOrientationClass();
+ },
+
+ /**
+ * Method: setOrientationClass
+ * Adds the "vertical" class if this TextButtonPanel should have a vertical,
+ * rather than horizontal, layout.
+ */
+ setOrientationClass: function() {
+ if (this.vertical) {
+ OpenLayers.Element.addClass(this.div, "vertical");
+ }
+ else {
+ OpenLayers.Element.removeClass(this.div, "vertical");
+ }
+ },
+
+ /**
+ * APIMethod: setAdditionalClass
+ * Sets an additional CSS class for this TextButtonPanel
+ * (for example, to override the default placement). This
+ * allows more than one TextButtonPanel to exist on the map
+ * at once.
+ */
+ setAdditionalClass: function() {
+ if (!!this.additionalClass) {
+ OpenLayers.Element.addClass(this.div, this.additionalClass);
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Control.TextButtonPanel"
+});
+/* ======================================================================
+ OpenLayers/Control/ScaleLine.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/Control.js
+ */
+
+/**
+ * Class: OpenLayers.Control.ScaleLine
+ * The ScaleLine displays a small line indicator representing the current
+ * map scale on the map. By default it is drawn in the lower left corner of
+ * the map.
+ *
+ * Inherits from:
+ * - <OpenLayers.Control>
+ *
+ * Is a very close copy of:
+ * - <OpenLayers.Control.Scale>
+ */
+OpenLayers.Control.ScaleLine = OpenLayers.Class(OpenLayers.Control, {
+
+ /**
+ * Property: maxWidth
+ * {Integer} Maximum width of the scale line in pixels. Default is 100.
+ */
+ maxWidth: 100,
+
+ /**
+ * Property: topOutUnits
+ * {String} Units for zoomed out on top bar. Default is km.
+ */
+ topOutUnits: "km",
+
+ /**
+ * Property: topInUnits
+ * {String} Units for zoomed in on top bar. Default is m.
+ */
+ topInUnits: "m",
+
+ /**
+ * Property: bottomOutUnits
+ * {String} Units for zoomed out on bottom bar. Default is mi.
+ */
+ bottomOutUnits: "mi",
+
+ /**
+ * Property: bottomInUnits
+ * {String} Units for zoomed in on bottom bar. Default is ft.
+ */
+ bottomInUnits: "ft",
+
+ /**
+ * Property: eTop
+ * {DOMElement}
+ */
+ eTop: null,
+
+ /**
+ * Property: eBottom
+ * {DOMElement}
+ */
+ eBottom:null,
+
+ /**
+ * APIProperty: geodesic
+ * {Boolean} Use geodesic measurement. Default is false. The recommended
+ * setting for maps in EPSG:4326 is false, and true EPSG:900913. If set to
+ * true, the scale will be calculated based on the horizontal size of the
+ * pixel in the center of the map viewport.
+ */
+ geodesic: false,
+
+ /**
+ * Constructor: OpenLayers.Control.ScaleLine
+ * Create a new scale line control.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be used
+ * to extend the control.
+ */
+
+ /**
+ * Method: draw
+ *
+ * Returns:
+ * {DOMElement}
+ */
+ draw: function() {
+ OpenLayers.Control.prototype.draw.apply(this, arguments);
+ if (!this.eTop) {
+ // stick in the top bar
+ this.eTop = document.createElement("div");
+ this.eTop.className = this.displayClass + "Top";
+ var theLen = this.topInUnits.length;
+ this.div.appendChild(this.eTop);
+ if((this.topOutUnits == "") || (this.topInUnits == "")) {
+ this.eTop.style.visibility = "hidden";
+ } else {
+ this.eTop.style.visibility = "visible";
+ }
+
+ // and the bottom bar
+ this.eBottom = document.createElement("div");
+ this.eBottom.className = this.displayClass + "Bottom";
+ this.div.appendChild(this.eBottom);
+ if((this.bottomOutUnits == "") || (this.bottomInUnits == "")) {
+ this.eBottom.style.visibility = "hidden";
+ } else {
+ this.eBottom.style.visibility = "visible";
+ }
+ }
+ this.map.events.register('moveend', this, this.update);
+ this.update();
+ return this.div;
+ },
+
+ /**
+ * Method: getBarLen
+ * Given a number, round it down to the nearest 1,2,5 times a power of 10.
+ * That seems a fairly useful set of number groups to use.
+ *
+ * Parameters:
+ * maxLen - {float} the number we're rounding down from
+ *
+ * Returns:
+ * {Float} the rounded number (less than or equal to maxLen)
+ */
+ getBarLen: function(maxLen) {
+ // nearest power of 10 lower than maxLen
+ var digits = parseInt(Math.log(maxLen) / Math.log(10));
+ var pow10 = Math.pow(10, digits);
+
+ // ok, find first character
+ var firstChar = parseInt(maxLen / pow10);
+
+ // right, put it into the correct bracket
+ var barLen;
+ if(firstChar > 5) {
+ barLen = 5;
+ } else if(firstChar > 2) {
+ barLen = 2;
+ } else {
+ barLen = 1;
+ }
+
+ // scale it up the correct power of 10
+ return barLen * pow10;
+ },
+
+ /**
+ * Method: update
+ * Update the size of the bars, and the labels they contain.
+ */
+ update: function() {
+ var res = this.map.getResolution();
+ if (!res) {
+ return;
+ }
+
+ var curMapUnits = this.map.getUnits();
+ var inches = OpenLayers.INCHES_PER_UNIT;
+
+ // convert maxWidth to map units
+ var maxSizeData = this.maxWidth * res * inches[curMapUnits];
+ var geodesicRatio = 1;
+ if(this.geodesic === true) {
+ var maxSizeGeodesic = (this.map.getGeodesicPixelSize().w ||
+ 0.000001) * this.maxWidth;
+ var maxSizeKilometers = maxSizeData / inches["km"];
+ geodesicRatio = maxSizeGeodesic / maxSizeKilometers;
+ maxSizeData *= geodesicRatio;
+ }
+
+ // decide whether to use large or small scale units
+ var topUnits;
+ var bottomUnits;
+ if(maxSizeData > 100000) {
+ topUnits = this.topOutUnits;
+ bottomUnits = this.bottomOutUnits;
+ } else {
+ topUnits = this.topInUnits;
+ bottomUnits = this.bottomInUnits;
+ }
+
+ // and to map units units
+ var topMax = maxSizeData / inches[topUnits];
+ var bottomMax = maxSizeData / inches[bottomUnits];
+
+ // now trim this down to useful block length
+ var topRounded = this.getBarLen(topMax);
+ var bottomRounded = this.getBarLen(bottomMax);
+
+ // and back to display units
+ topMax = topRounded / inches[curMapUnits] * inches[topUnits];
+ bottomMax = bottomRounded / inches[curMapUnits] * inches[bottomUnits];
+
+ // and to pixel units
+ var topPx = topMax / res / geodesicRatio;
+ var bottomPx = bottomMax / res / geodesicRatio;
+
+ // now set the pixel widths
+ // and the values inside them
+
+ if (this.eBottom.style.visibility == "visible"){
+ this.eBottom.style.width = Math.round(bottomPx) + "px";
+ this.eBottom.innerHTML = bottomRounded + " " + bottomUnits ;
+ }
+
+ if (this.eTop.style.visibility == "visible"){
+ this.eTop.style.width = Math.round(topPx) + "px";
+ this.eTop.innerHTML = topRounded + " " + topUnits;
+ }
+
+ },
+
+ CLASS_NAME: "OpenLayers.Control.ScaleLine"
+});
+
+/* ======================================================================
+ OpenLayers/Icon.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.Icon
+ *
+ * The icon represents a graphical icon on the screen. Typically used in
+ * conjunction with a <OpenLayers.Marker> to represent markers on a screen.
+ *
+ * An icon has a url, size and position. It also contains an offset which
+ * allows the center point to be represented correctly. This can be
+ * provided either as a fixed offset or a function provided to calculate
+ * the desired offset.
+ *
+ */
+OpenLayers.Icon = OpenLayers.Class({
+
+ /**
+ * Property: url
+ * {String} image url
+ */
+ url: null,
+
+ /**
+ * Property: size
+ * {<OpenLayers.Size>|Object} An OpenLayers.Size or
+ * an object with a 'w' and 'h' properties.
+ */
+ size: null,
+
+ /**
+ * Property: offset
+ * {<OpenLayers.Pixel>|Object} distance in pixels to offset the
+ * image when being rendered. An OpenLayers.Pixel or an object
+ * with a 'x' and 'y' properties.
+ */
+ offset: null,
+
+ /**
+ * Property: calculateOffset
+ * {Function} Function to calculate the offset (based on the size)
+ */
+ calculateOffset: null,
+
+ /**
+ * Property: imageDiv
+ * {DOMElement}
+ */
+ imageDiv: null,
+
+ /**
+ * Property: px
+ * {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an object
+ * with a 'x' and 'y' properties.
+ */
+ px: null,
+
+ /**
+ * Constructor: OpenLayers.Icon
+ * Creates an icon, which is an image tag in a div.
+ *
+ * url - {String}
+ * size - {<OpenLayers.Size>|Object} An OpenLayers.Size or an
+ * object with a 'w' and 'h'
+ * properties.
+ * offset - {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an
+ * object with a 'x' and 'y'
+ * properties.
+ * calculateOffset - {Function}
+ */
+ initialize: function(url, size, offset, calculateOffset) {
+ this.url = url;
+ this.size = size || {w: 20, h: 20};
+ this.offset = offset || {x: -(this.size.w/2), y: -(this.size.h/2)};
+ this.calculateOffset = calculateOffset;
+
+ var id = OpenLayers.Util.createUniqueID("OL_Icon_");
+ this.imageDiv = OpenLayers.Util.createAlphaImageDiv(id);
+ },
+
+ /**
+ * Method: destroy
+ * Nullify references and remove event listeners to prevent circular
+ * references and memory leaks
+ */
+ destroy: function() {
+ // erase any drawn elements
+ this.erase();
+
+ OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);
+ this.imageDiv.innerHTML = "";
+ this.imageDiv = null;
+ },
+
+ /**
+ * Method: clone
+ *
+ * Returns:
+ * {<OpenLayers.Icon>} A fresh copy of the icon.
+ */
+ clone: function() {
+ return new OpenLayers.Icon(this.url,
+ this.size,
+ this.offset,
+ this.calculateOffset);
+ },
+
+ /**
+ * Method: setSize
+ *
+ * Parameters:
+ * size - {<OpenLayers.Size>|Object} An OpenLayers.Size or
+ * an object with a 'w' and 'h' properties.
+ */
+ setSize: function(size) {
+ if (size != null) {
+ this.size = size;
+ }
+ this.draw();
+ },
+
+ /**
+ * Method: setUrl
+ *
+ * Parameters:
+ * url - {String}
+ */
+ setUrl: function(url) {
+ if (url != null) {
+ this.url = url;
+ }
+ this.draw();
+ },
+
+ /**
+ * Method: draw
+ * Move the div to the given pixel.
+ *
+ * Parameters:
+ * px - {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an
+ * object with a 'x' and 'y' properties.
+ *
+ * Returns:
+ * {DOMElement} A new DOM Image of this icon set at the location passed-in
+ */
+ draw: function(px) {
+ OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,
+ null,
+ null,
+ this.size,
+ this.url,
+ "absolute");
+ this.moveTo(px);
+ return this.imageDiv;
+ },
+
+ /**
+ * Method: erase
+ * Erase the underlying image element.
+ */
+ erase: function() {
+ if (this.imageDiv != null && this.imageDiv.parentNode != null) {
+ OpenLayers.Element.remove(this.imageDiv);
+ }
+ },
+
+ /**
+ * Method: setOpacity
+ * Change the icon's opacity
+ *
+ * Parameters:
+ * opacity - {float}
+ */
+ setOpacity: function(opacity) {
+ OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null,
+ null, null, null, null, opacity);
+
+ },
+
+ /**
+ * Method: moveTo
+ * move icon to passed in px.
+ *
+ * Parameters:
+ * px - {<OpenLayers.Pixel>|Object} the pixel position to move to.
+ * An OpenLayers.Pixel or an object with a 'x' and 'y' properties.
+ */
+ moveTo: function (px) {
+ //if no px passed in, use stored location
+ if (px != null) {
+ this.px = px;
+ }
+
+ if (this.imageDiv != null) {
+ if (this.px == null) {
+ this.display(false);
+ } else {
+ if (this.calculateOffset) {
+ this.offset = this.calculateOffset(this.size);
+ }
+ OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, {
+ x: this.px.x + this.offset.x,
+ y: this.px.y + this.offset.y
+ });
+ }
+ }
+ },
+
+ /**
+ * Method: display
+ * Hide or show the icon
+ *
+ * Parameters:
+ * display - {Boolean}
+ */
+ display: function(display) {
+ this.imageDiv.style.display = (display) ? "" : "none";
+ },
+
+
+ /**
+ * APIMethod: isDrawn
+ *
+ * Returns:
+ * {Boolean} Whether or not the icon is drawn.
+ */
+ isDrawn: function() {
+ // nodeType 11 for ie, whose nodes *always* have a parentNode
+ // (of type document fragment)
+ var isDrawn = (this.imageDiv && this.imageDiv.parentNode &&
+ (this.imageDiv.parentNode.nodeType != 11));
+
+ return isDrawn;
+ },
+
+ CLASS_NAME: "OpenLayers.Icon"
+});
+/* ======================================================================
+ OpenLayers/Marker.js
+ ====================================================================== */
+
+/* Copyright (c) 2006-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
+ * @requires OpenLayers/Icon.js
+ */
+
+/**
+ * Class: OpenLayers.Marker
+ * Instances of OpenLayers.Marker are a combination of a
+ * <OpenLayers.LonLat> and an <OpenLayers.Icon>.
+ *
+ * Markers are generally added to a special layer called
+ * <OpenLayers.Layer.Markers>.
+ *
+ * Example:
+ * (code)
+ * var markers = new OpenLayers.Layer.Markers( "Markers" );
+ * map.addLayer(markers);
+ *
+ * var size = new OpenLayers.Size(21,25);
+ * var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
+ * var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset);
+ * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon));
+ * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon.clone()));
+ *
+ * (end)
+ *
+ * Note that if you pass an icon into the Marker constructor, it will take
+ * that icon and use it. This means that you should not share icons between
+ * markers -- you use them once, but you should clone() for any additional
+ * markers using that same icon.
+ */
+OpenLayers.Marker = OpenLayers.Class({
+
+ /**
+ * Property: icon
+ * {<OpenLayers.Icon>} The icon used by this marker.
+ */
+ icon: null,
+
+ /**
+ * Property: lonlat
+ * {<OpenLayers.LonLat>} location of object
+ */
+ lonlat: null,
+
+ /**
+ * Property: events
+ * {<OpenLayers.Events>} the event handler.
+ */
+ events: null,
+
+ /**
+ * Property: map
+ * {<OpenLayers.Map>} the map this marker is attached to
+ */
+ map: null,
+
+ /**
+ * Constructor: OpenLayers.Marker
+ *
+ * Parameters:
+ * lonlat - {<OpenLayers.LonLat>} the position of this marker
+ * icon - {<OpenLayers.Icon>} the icon for this marker
+ */
+ initialize: function(lonlat, icon) {
+ this.lonlat = lonlat;
+
+ var newIcon = (icon) ? icon : OpenLayers.Marker.defaultIcon();
+ if (this.icon == null) {
+ this.icon = newIcon;
+ } else {
+ this.icon.url = newIcon.url;
+ this.icon.size = newIcon.size;
+ this.icon.offset = newIcon.offset;
+ this.icon.calculateOffset = newIcon.calculateOffset;
+ }
+ this.events = new OpenLayers.Events(this, this.icon.imageDiv);
+ },
+
+ /**
+ * APIMethod: destroy
+ * Destroy the marker. You must first remove the marker from any
+ * layer which it has been added to, or you will get buggy behavior.
+ * (This can not be done within the marker since the marker does not
+ * know which layer it is attached to.)
+ */
+ destroy: function() {
+ // erase any drawn features
+ this.erase();
+
+ this.map = null;
+
+ this.events.destroy();
+ this.events = null;
+
+ if (this.icon != null) {
+ this.icon.destroy();
+ this.icon = null;
+ }
+ },
+
+ /**
+ * Method: draw
+ * Calls draw on the icon, and returns that output.
+ *
+ * Parameters:
+ * px - {<OpenLayers.Pixel>}
+ *
+ * Returns:
+ * {DOMElement} A new DOM Image with this marker's icon set at the
+ * location passed-in
+ */
+ draw: function(px) {
+ return this.icon.draw(px);
+ },
+
+ /**
+ * Method: erase
+ * Erases any drawn elements for this marker.
+ */
+ erase: function() {
+ if (this.icon != null) {
+ this.icon.erase();
+ }
+ },
+
+ /**
+ * Method: moveTo
+ * Move the marker to the new location.
+ *
+ * Parameters:
+ * px - {<OpenLayers.Pixel>|Object} the pixel position to move to.
+ * An OpenLayers.Pixel or an object with a 'x' and 'y' properties.
+ */
+ moveTo: function (px) {
+ if ((px != null) && (this.icon != null)) {
+ this.icon.moveTo(px);
+ }
+ this.lonlat = this.map.getLonLatFromLayerPx(px);
+ },
+
+ /**
+ * APIMethod: isDrawn
+ *
+ * Returns:
+ * {Boolean} Whether or not the marker is drawn.
+ */
+ isDrawn: function() {
+ var isDrawn = (this.icon && this.icon.isDrawn());
+ return isDrawn;
+ },
+
+ /**
+ * Method: onScreen
+ *
+ * Returns:
+ * {Boolean} Whether or not the marker is currently visible on screen.
+ */
+ onScreen:function() {
+
+ var onScreen = false;
+ if (this.map) {
+ var screenBounds = this.map.getExtent();
+ onScreen = screenBounds.containsLonLat(this.lonlat);
+ }
+ return onScreen;
+ },
+
+ /**
+ * Method: inflate
+ * Englarges the markers icon by the specified ratio.
+ *
+ * Parameters:
+ * inflate - {float} the ratio to enlarge the marker by (passing 2
+ * will double the size).
+ */
+ inflate: function(inflate) {
+ if (this.icon) {
+ this.icon.setSize({
+ w: this.icon.size.w * inflate,
+ h: this.icon.size.h * inflate
+ });
+ }
+ },
+
+ /**
+ * Method: setOpacity
+ * Change the opacity of the marker by changin the opacity of
+ * its icon
+ *
+ * Parameters:
+ * opacity - {float} Specified as fraction (0.4, etc)
+ */
+ setOpacity: function(opacity) {
+ this.icon.setOpacity(opacity);
+ },
+
+ /**
+ * Method: setUrl
+ * Change URL of the Icon Image.
+ *
+ * url - {String}
+ */
+ setUrl: function(url) {
+ this.icon.setUrl(url);
+ },
+
+ /**
+ * Method: display
+ * Hide or show the icon
+ *
+ * display - {Boolean}
+ */
+ display: function(display) {
+ this.icon.display(display);
+ },
+
+ CLASS_NAME: "OpenLayers.Marker"
+});
+
+
+/**
+ * Function: defaultIcon
+ * Creates a default <OpenLayers.Icon>.
+ *
+ * Returns:
+ * {<OpenLayers.Icon>} A default OpenLayers.Icon to use for a marker
+ */
+OpenLayers.Marker.defaultIcon = function() {
+ return new OpenLayers.Icon(OpenLayers.Util.getImageLocation("marker.png"),
+ {w: 21, h: 25}, {x: -10.5, y: -25});
+};
+
+
+/* ======================================================================
OpenLayers/Popup.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -58576,1450 +61338,14 @@
OpenLayers.Popup.HEIGHT = 200;
OpenLayers.Popup.COLOR = "white";
OpenLayers.Popup.OPACITY = 1;
OpenLayers.Popup.BORDER = "0px";
/* ======================================================================
- OpenLayers/Control/ScaleLine.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/Control.js
- */
-
-/**
- * Class: OpenLayers.Control.ScaleLine
- * The ScaleLine displays a small line indicator representing the current
- * map scale on the map. By default it is drawn in the lower left corner of
- * the map.
- *
- * Inherits from:
- * - <OpenLayers.Control>
- *
- * Is a very close copy of:
- * - <OpenLayers.Control.Scale>
- */
-OpenLayers.Control.ScaleLine = OpenLayers.Class(OpenLayers.Control, {
-
- /**
- * Property: maxWidth
- * {Integer} Maximum width of the scale line in pixels. Default is 100.
- */
- maxWidth: 100,
-
- /**
- * Property: topOutUnits
- * {String} Units for zoomed out on top bar. Default is km.
- */
- topOutUnits: "km",
-
- /**
- * Property: topInUnits
- * {String} Units for zoomed in on top bar. Default is m.
- */
- topInUnits: "m",
-
- /**
- * Property: bottomOutUnits
- * {String} Units for zoomed out on bottom bar. Default is mi.
- */
- bottomOutUnits: "mi",
-
- /**
- * Property: bottomInUnits
- * {String} Units for zoomed in on bottom bar. Default is ft.
- */
- bottomInUnits: "ft",
-
- /**
- * Property: eTop
- * {DOMElement}
- */
- eTop: null,
-
- /**
- * Property: eBottom
- * {DOMElement}
- */
- eBottom:null,
-
- /**
- * APIProperty: geodesic
- * {Boolean} Use geodesic measurement. Default is false. The recommended
- * setting for maps in EPSG:4326 is false, and true EPSG:900913. If set to
- * true, the scale will be calculated based on the horizontal size of the
- * pixel in the center of the map viewport.
- */
- geodesic: false,
-
- /**
- * Constructor: OpenLayers.Control.ScaleLine
- * Create a new scale line control.
- *
- * Parameters:
- * options - {Object} An optional object whose properties will be used
- * to extend the control.
- */
-
- /**
- * Method: draw
- *
- * Returns:
- * {DOMElement}
- */
- draw: function() {
- OpenLayers.Control.prototype.draw.apply(this, arguments);
- if (!this.eTop) {
- // stick in the top bar
- this.eTop = document.createElement("div");
- this.eTop.className = this.displayClass + "Top";
- var theLen = this.topInUnits.length;
- this.div.appendChild(this.eTop);
- if((this.topOutUnits == "") || (this.topInUnits == "")) {
- this.eTop.style.visibility = "hidden";
- } else {
- this.eTop.style.visibility = "visible";
- }
-
- // and the bottom bar
- this.eBottom = document.createElement("div");
- this.eBottom.className = this.displayClass + "Bottom";
- this.div.appendChild(this.eBottom);
- if((this.bottomOutUnits == "") || (this.bottomInUnits == "")) {
- this.eBottom.style.visibility = "hidden";
- } else {
- this.eBottom.style.visibility = "visible";
- }
- }
- this.map.events.register('moveend', this, this.update);
- this.update();
- return this.div;
- },
-
- /**
- * Method: getBarLen
- * Given a number, round it down to the nearest 1,2,5 times a power of 10.
- * That seems a fairly useful set of number groups to use.
- *
- * Parameters:
- * maxLen - {float} the number we're rounding down from
- *
- * Returns:
- * {Float} the rounded number (less than or equal to maxLen)
- */
- getBarLen: function(maxLen) {
- // nearest power of 10 lower than maxLen
- var digits = parseInt(Math.log(maxLen) / Math.log(10));
- var pow10 = Math.pow(10, digits);
-
- // ok, find first character
- var firstChar = parseInt(maxLen / pow10);
-
- // right, put it into the correct bracket
- var barLen;
- if(firstChar > 5) {
- barLen = 5;
- } else if(firstChar > 2) {
- barLen = 2;
- } else {
- barLen = 1;
- }
-
- // scale it up the correct power of 10
- return barLen * pow10;
- },
-
- /**
- * Method: update
- * Update the size of the bars, and the labels they contain.
- */
- update: function() {
- var res = this.map.getResolution();
- if (!res) {
- return;
- }
-
- var curMapUnits = this.map.getUnits();
- var inches = OpenLayers.INCHES_PER_UNIT;
-
- // convert maxWidth to map units
- var maxSizeData = this.maxWidth * res * inches[curMapUnits];
- var geodesicRatio = 1;
- if(this.geodesic === true) {
- var maxSizeGeodesic = (this.map.getGeodesicPixelSize().w ||
- 0.000001) * this.maxWidth;
- var maxSizeKilometers = maxSizeData / inches["km"];
- geodesicRatio = maxSizeGeodesic / maxSizeKilometers;
- maxSizeData *= geodesicRatio;
- }
-
- // decide whether to use large or small scale units
- var topUnits;
- var bottomUnits;
- if(maxSizeData > 100000) {
- topUnits = this.topOutUnits;
- bottomUnits = this.bottomOutUnits;
- } else {
- topUnits = this.topInUnits;
- bottomUnits = this.bottomInUnits;
- }
-
- // and to map units units
- var topMax = maxSizeData / inches[topUnits];
- var bottomMax = maxSizeData / inches[bottomUnits];
-
- // now trim this down to useful block length
- var topRounded = this.getBarLen(topMax);
- var bottomRounded = this.getBarLen(bottomMax);
-
- // and back to display units
- topMax = topRounded / inches[curMapUnits] * inches[topUnits];
- bottomMax = bottomRounded / inches[curMapUnits] * inches[bottomUnits];
-
- // and to pixel units
- var topPx = topMax / res / geodesicRatio;
- var bottomPx = bottomMax / res / geodesicRatio;
-
- // now set the pixel widths
- // and the values inside them
-
- if (this.eBottom.style.visibility == "visible"){
- this.eBottom.style.width = Math.round(bottomPx) + "px";
- this.eBottom.innerHTML = bottomRounded + " " + bottomUnits ;
- }
-
- if (this.eTop.style.visibility == "visible"){
- this.eTop.style.width = Math.round(topPx) + "px";
- this.eTop.innerHTML = topRounded + " " + topUnits;
- }
-
- },
-
- CLASS_NAME: "OpenLayers.Control.ScaleLine"
-});
-
-/* ======================================================================
- OpenLayers/Icon.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.Icon
- *
- * The icon represents a graphical icon on the screen. Typically used in
- * conjunction with a <OpenLayers.Marker> to represent markers on a screen.
- *
- * An icon has a url, size and position. It also contains an offset which
- * allows the center point to be represented correctly. This can be
- * provided either as a fixed offset or a function provided to calculate
- * the desired offset.
- *
- */
-OpenLayers.Icon = OpenLayers.Class({
-
- /**
- * Property: url
- * {String} image url
- */
- url: null,
-
- /**
- * Property: size
- * {<OpenLayers.Size>|Object} An OpenLayers.Size or
- * an object with a 'w' and 'h' properties.
- */
- size: null,
-
- /**
- * Property: offset
- * {<OpenLayers.Pixel>|Object} distance in pixels to offset the
- * image when being rendered. An OpenLayers.Pixel or an object
- * with a 'x' and 'y' properties.
- */
- offset: null,
-
- /**
- * Property: calculateOffset
- * {Function} Function to calculate the offset (based on the size)
- */
- calculateOffset: null,
-
- /**
- * Property: imageDiv
- * {DOMElement}
- */
- imageDiv: null,
-
- /**
- * Property: px
- * {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an object
- * with a 'x' and 'y' properties.
- */
- px: null,
-
- /**
- * Constructor: OpenLayers.Icon
- * Creates an icon, which is an image tag in a div.
- *
- * url - {String}
- * size - {<OpenLayers.Size>|Object} An OpenLayers.Size or an
- * object with a 'w' and 'h'
- * properties.
- * offset - {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an
- * object with a 'x' and 'y'
- * properties.
- * calculateOffset - {Function}
- */
- initialize: function(url, size, offset, calculateOffset) {
- this.url = url;
- this.size = size || {w: 20, h: 20};
- this.offset = offset || {x: -(this.size.w/2), y: -(this.size.h/2)};
- this.calculateOffset = calculateOffset;
-
- var id = OpenLayers.Util.createUniqueID("OL_Icon_");
- this.imageDiv = OpenLayers.Util.createAlphaImageDiv(id);
- },
-
- /**
- * Method: destroy
- * Nullify references and remove event listeners to prevent circular
- * references and memory leaks
- */
- destroy: function() {
- // erase any drawn elements
- this.erase();
-
- OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);
- this.imageDiv.innerHTML = "";
- this.imageDiv = null;
- },
-
- /**
- * Method: clone
- *
- * Returns:
- * {<OpenLayers.Icon>} A fresh copy of the icon.
- */
- clone: function() {
- return new OpenLayers.Icon(this.url,
- this.size,
- this.offset,
- this.calculateOffset);
- },
-
- /**
- * Method: setSize
- *
- * Parameters:
- * size - {<OpenLayers.Size>|Object} An OpenLayers.Size or
- * an object with a 'w' and 'h' properties.
- */
- setSize: function(size) {
- if (size != null) {
- this.size = size;
- }
- this.draw();
- },
-
- /**
- * Method: setUrl
- *
- * Parameters:
- * url - {String}
- */
- setUrl: function(url) {
- if (url != null) {
- this.url = url;
- }
- this.draw();
- },
-
- /**
- * Method: draw
- * Move the div to the given pixel.
- *
- * Parameters:
- * px - {<OpenLayers.Pixel>|Object} An OpenLayers.Pixel or an
- * object with a 'x' and 'y' properties.
- *
- * Returns:
- * {DOMElement} A new DOM Image of this icon set at the location passed-in
- */
- draw: function(px) {
- OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,
- null,
- null,
- this.size,
- this.url,
- "absolute");
- this.moveTo(px);
- return this.imageDiv;
- },
-
- /**
- * Method: erase
- * Erase the underlying image element.
- */
- erase: function() {
- if (this.imageDiv != null && this.imageDiv.parentNode != null) {
- OpenLayers.Element.remove(this.imageDiv);
- }
- },
-
- /**
- * Method: setOpacity
- * Change the icon's opacity
- *
- * Parameters:
- * opacity - {float}
- */
- setOpacity: function(opacity) {
- OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null,
- null, null, null, null, opacity);
-
- },
-
- /**
- * Method: moveTo
- * move icon to passed in px.
- *
- * Parameters:
- * px - {<OpenLayers.Pixel>|Object} the pixel position to move to.
- * An OpenLayers.Pixel or an object with a 'x' and 'y' properties.
- */
- moveTo: function (px) {
- //if no px passed in, use stored location
- if (px != null) {
- this.px = px;
- }
-
- if (this.imageDiv != null) {
- if (this.px == null) {
- this.display(false);
- } else {
- if (this.calculateOffset) {
- this.offset = this.calculateOffset(this.size);
- }
- OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, {
- x: this.px.x + this.offset.x,
- y: this.px.y + this.offset.y
- });
- }
- }
- },
-
- /**
- * Method: display
- * Hide or show the icon
- *
- * Parameters:
- * display - {Boolean}
- */
- display: function(display) {
- this.imageDiv.style.display = (display) ? "" : "none";
- },
-
-
- /**
- * APIMethod: isDrawn
- *
- * Returns:
- * {Boolean} Whether or not the icon is drawn.
- */
- isDrawn: function() {
- // nodeType 11 for ie, whose nodes *always* have a parentNode
- // (of type document fragment)
- var isDrawn = (this.imageDiv && this.imageDiv.parentNode &&
- (this.imageDiv.parentNode.nodeType != 11));
-
- return isDrawn;
- },
-
- CLASS_NAME: "OpenLayers.Icon"
-});
-/* ======================================================================
- OpenLayers/Marker.js
- ====================================================================== */
-
-/* Copyright (c) 2006-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
- * @requires OpenLayers/Icon.js
- */
-
-/**
- * Class: OpenLayers.Marker
- * Instances of OpenLayers.Marker are a combination of a
- * <OpenLayers.LonLat> and an <OpenLayers.Icon>.
- *
- * Markers are generally added to a special layer called
- * <OpenLayers.Layer.Markers>.
- *
- * Example:
- * (code)
- * var markers = new OpenLayers.Layer.Markers( "Markers" );
- * map.addLayer(markers);
- *
- * var size = new OpenLayers.Size(21,25);
- * var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
- * var icon = new OpenLayers.Icon('http://www.openlayers.org/dev/img/marker.png', size, offset);
- * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon));
- * markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon.clone()));
- *
- * (end)
- *
- * Note that if you pass an icon into the Marker constructor, it will take
- * that icon and use it. This means that you should not share icons between
- * markers -- you use them once, but you should clone() for any additional
- * markers using that same icon.
- */
-OpenLayers.Marker = OpenLayers.Class({
-
- /**
- * Property: icon
- * {<OpenLayers.Icon>} The icon used by this marker.
- */
- icon: null,
-
- /**
- * Property: lonlat
- * {<OpenLayers.LonLat>} location of object
- */
- lonlat: null,
-
- /**
- * Property: events
- * {<OpenLayers.Events>} the event handler.
- */
- events: null,
-
- /**
- * Property: map
- * {<OpenLayers.Map>} the map this marker is attached to
- */
- map: null,
-
- /**
- * Constructor: OpenLayers.Marker
- *
- * Parameters:
- * lonlat - {<OpenLayers.LonLat>} the position of this marker
- * icon - {<OpenLayers.Icon>} the icon for this marker
- */
- initialize: function(lonlat, icon) {
- this.lonlat = lonlat;
-
- var newIcon = (icon) ? icon : OpenLayers.Marker.defaultIcon();
- if (this.icon == null) {
- this.icon = newIcon;
- } else {
- this.icon.url = newIcon.url;
- this.icon.size = newIcon.size;
- this.icon.offset = newIcon.offset;
- this.icon.calculateOffset = newIcon.calculateOffset;
- }
- this.events = new OpenLayers.Events(this, this.icon.imageDiv);
- },
-
- /**
- * APIMethod: destroy
- * Destroy the marker. You must first remove the marker from any
- * layer which it has been added to, or you will get buggy behavior.
- * (This can not be done within the marker since the marker does not
- * know which layer it is attached to.)
- */
- destroy: function() {
- // erase any drawn features
- this.erase();
-
- this.map = null;
-
- this.events.destroy();
- this.events = null;
-
- if (this.icon != null) {
- this.icon.destroy();
- this.icon = null;
- }
- },
-
- /**
- * Method: draw
- * Calls draw on the icon, and returns that output.
- *
- * Parameters:
- * px - {<OpenLayers.Pixel>}
- *
- * Returns:
- * {DOMElement} A new DOM Image with this marker's icon set at the
- * location passed-in
- */
- draw: function(px) {
- return this.icon.draw(px);
- },
-
- /**
- * Method: erase
- * Erases any drawn elements for this marker.
- */
- erase: function() {
- if (this.icon != null) {
- this.icon.erase();
- }
- },
-
- /**
- * Method: moveTo
- * Move the marker to the new location.
- *
- * Parameters:
- * px - {<OpenLayers.Pixel>|Object} the pixel position to move to.
- * An OpenLayers.Pixel or an object with a 'x' and 'y' properties.
- */
- moveTo: function (px) {
- if ((px != null) && (this.icon != null)) {
- this.icon.moveTo(px);
- }
- this.lonlat = this.map.getLonLatFromLayerPx(px);
- },
-
- /**
- * APIMethod: isDrawn
- *
- * Returns:
- * {Boolean} Whether or not the marker is drawn.
- */
- isDrawn: function() {
- var isDrawn = (this.icon && this.icon.isDrawn());
- return isDrawn;
- },
-
- /**
- * Method: onScreen
- *
- * Returns:
- * {Boolean} Whether or not the marker is currently visible on screen.
- */
- onScreen:function() {
-
- var onScreen = false;
- if (this.map) {
- var screenBounds = this.map.getExtent();
- onScreen = screenBounds.containsLonLat(this.lonlat);
- }
- return onScreen;
- },
-
- /**
- * Method: inflate
- * Englarges the markers icon by the specified ratio.
- *
- * Parameters:
- * inflate - {float} the ratio to enlarge the marker by (passing 2
- * will double the size).
- */
- inflate: function(inflate) {
- if (this.icon) {
- this.icon.setSize({
- w: this.icon.size.w * inflate,
- h: this.icon.size.h * inflate
- });
- }
- },
-
- /**
- * Method: setOpacity
- * Change the opacity of the marker by changin the opacity of
- * its icon
- *
- * Parameters:
- * opacity - {float} Specified as fraction (0.4, etc)
- */
- setOpacity: function(opacity) {
- this.icon.setOpacity(opacity);
- },
-
- /**
- * Method: setUrl
- * Change URL of the Icon Image.
- *
- * url - {String}
- */
- setUrl: function(url) {
- this.icon.setUrl(url);
- },
-
- /**
- * Method: display
- * Hide or show the icon
- *
- * display - {Boolean}
- */
- display: function(display) {
- this.icon.display(display);
- },
-
- CLASS_NAME: "OpenLayers.Marker"
-});
-
-
-/**
- * Function: defaultIcon
- * Creates a default <OpenLayers.Icon>.
- *
- * Returns:
- * {<OpenLayers.Icon>} A default OpenLayers.Icon to use for a marker
- */
-OpenLayers.Marker.defaultIcon = function() {
- return new OpenLayers.Icon(OpenLayers.Util.getImageLocation("marker.png"),
- {w: 21, h: 25}, {x: -10.5, y: -25});
-};
-
-
-/* ======================================================================
- OpenLayers/Format/GeoJSON.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/Format/JSON.js
- * @requires OpenLayers/Feature/Vector.js
- * @requires OpenLayers/Geometry/Point.js
- * @requires OpenLayers/Geometry/MultiPoint.js
- * @requires OpenLayers/Geometry/LineString.js
- * @requires OpenLayers/Geometry/MultiLineString.js
- * @requires OpenLayers/Geometry/Polygon.js
- * @requires OpenLayers/Geometry/MultiPolygon.js
- * @requires OpenLayers/Console.js
- */
-
-/**
- * Class: OpenLayers.Format.GeoJSON
- * Read and write GeoJSON. Create a new parser with the
- * <OpenLayers.Format.GeoJSON> constructor.
- *
- * Inherits from:
- * - <OpenLayers.Format.JSON>
- */
-OpenLayers.Format.GeoJSON = OpenLayers.Class(OpenLayers.Format.JSON, {
-
- /**
- * APIProperty: ignoreExtraDims
- * {Boolean} Ignore dimensions higher than 2 when reading geometry
- * coordinates.
- */
- ignoreExtraDims: false,
-
- /**
- * Constructor: OpenLayers.Format.GeoJSON
- * Create a new parser for GeoJSON.
- *
- * Parameters:
- * options - {Object} An optional object whose properties will be set on
- * this instance.
- */
-
- /**
- * APIMethod: read
- * Deserialize a GeoJSON string.
- *
- * Parameters:
- * json - {String} A GeoJSON string
- * type - {String} Optional string that determines the structure of
- * the output. Supported values are "Geometry", "Feature", and
- * "FeatureCollection". If absent or null, a default of
- * "FeatureCollection" is assumed.
- * filter - {Function} A function which will be called for every key and
- * value at every level of the final result. Each value will be
- * replaced by the result of the filter function. This can be used to
- * reform generic objects into instances of classes, or to transform
- * date strings into Date objects.
- *
- * Returns:
- * {Object} The return depends on the value of the type argument. If type
- * is "FeatureCollection" (the default), the return will be an array
- * of <OpenLayers.Feature.Vector>. If type is "Geometry", the input json
- * must represent a single geometry, and the return will be an
- * <OpenLayers.Geometry>. If type is "Feature", the input json must
- * represent a single feature, and the return will be an
- * <OpenLayers.Feature.Vector>.
- */
- read: function(json, type, filter) {
- type = (type) ? type : "FeatureCollection";
- var results = null;
- var obj = null;
- if (typeof json == "string") {
- obj = OpenLayers.Format.JSON.prototype.read.apply(this,
- [json, filter]);
- } else {
- obj = json;
- }
- if(!obj) {
- OpenLayers.Console.error("Bad JSON: " + json);
- } else if(typeof(obj.type) != "string") {
- OpenLayers.Console.error("Bad GeoJSON - no type: " + json);
- } else if(this.isValidType(obj, type)) {
- switch(type) {
- case "Geometry":
- try {
- results = this.parseGeometry(obj);
- } catch(err) {
- OpenLayers.Console.error(err);
- }
- break;
- case "Feature":
- try {
- results = this.parseFeature(obj);
- results.type = "Feature";
- } catch(err) {
- OpenLayers.Console.error(err);
- }
- break;
- case "FeatureCollection":
- // for type FeatureCollection, we allow input to be any type
- results = [];
- switch(obj.type) {
- case "Feature":
- try {
- results.push(this.parseFeature(obj));
- } catch(err) {
- results = null;
- OpenLayers.Console.error(err);
- }
- break;
- case "FeatureCollection":
- for(var i=0, len=obj.features.length; i<len; ++i) {
- try {
- results.push(this.parseFeature(obj.features[i]));
- } catch(err) {
- results = null;
- OpenLayers.Console.error(err);
- }
- }
- break;
- default:
- try {
- var geom = this.parseGeometry(obj);
- results.push(new OpenLayers.Feature.Vector(geom));
- } catch(err) {
- results = null;
- OpenLayers.Console.error(err);
- }
- }
- break;
- }
- }
- return results;
- },
-
- /**
- * Method: isValidType
- * Check if a GeoJSON object is a valid representative of the given type.
- *
- * Returns:
- * {Boolean} The object is valid GeoJSON object of the given type.
- */
- isValidType: function(obj, type) {
- var valid = false;
- switch(type) {
- case "Geometry":
- if(OpenLayers.Util.indexOf(
- ["Point", "MultiPoint", "LineString", "MultiLineString",
- "Polygon", "MultiPolygon", "Box", "GeometryCollection"],
- obj.type) == -1) {
- // unsupported geometry type
- OpenLayers.Console.error("Unsupported geometry type: " +
- obj.type);
- } else {
- valid = true;
- }
- break;
- case "FeatureCollection":
- // allow for any type to be converted to a feature collection
- valid = true;
- break;
- default:
- // for Feature types must match
- if(obj.type == type) {
- valid = true;
- } else {
- OpenLayers.Console.error("Cannot convert types from " +
- obj.type + " to " + type);
- }
- }
- return valid;
- },
-
- /**
- * Method: parseFeature
- * Convert a feature object from GeoJSON into an
- * <OpenLayers.Feature.Vector>.
- *
- * Parameters:
- * obj - {Object} An object created from a GeoJSON object
- *
- * Returns:
- * {<OpenLayers.Feature.Vector>} A feature.
- */
- parseFeature: function(obj) {
- var feature, geometry, attributes, bbox;
- attributes = (obj.properties) ? obj.properties : {};
- bbox = (obj.geometry && obj.geometry.bbox) || obj.bbox;
- try {
- geometry = this.parseGeometry(obj.geometry);
- } catch(err) {
- // deal with bad geometries
- throw err;
- }
- feature = new OpenLayers.Feature.Vector(geometry, attributes);
- if(bbox) {
- feature.bounds = OpenLayers.Bounds.fromArray(bbox);
- }
- if(obj.id) {
- feature.fid = obj.id;
- }
- return feature;
- },
-
- /**
- * Method: parseGeometry
- * Convert a geometry object from GeoJSON into an <OpenLayers.Geometry>.
- *
- * Parameters:
- * obj - {Object} An object created from a GeoJSON object
- *
- * Returns:
- * {<OpenLayers.Geometry>} A geometry.
- */
- parseGeometry: function(obj) {
- if (obj == null) {
- return null;
- }
- var geometry, collection = false;
- if(obj.type == "GeometryCollection") {
- if(!(OpenLayers.Util.isArray(obj.geometries))) {
- throw "GeometryCollection must have geometries array: " + obj;
- }
- var numGeom = obj.geometries.length;
- var components = new Array(numGeom);
- for(var i=0; i<numGeom; ++i) {
- components[i] = this.parseGeometry.apply(
- this, [obj.geometries[i]]
- );
- }
- geometry = new OpenLayers.Geometry.Collection(components);
- collection = true;
- } else {
- if(!(OpenLayers.Util.isArray(obj.coordinates))) {
- throw "Geometry must have coordinates array: " + obj;
- }
- if(!this.parseCoords[obj.type.toLowerCase()]) {
- throw "Unsupported geometry type: " + obj.type;
- }
- try {
- geometry = this.parseCoords[obj.type.toLowerCase()].apply(
- this, [obj.coordinates]
- );
- } catch(err) {
- // deal with bad coordinates
- throw err;
- }
- }
- // We don't reproject collections because the children are reprojected
- // for us when they are created.
- if (this.internalProjection && this.externalProjection && !collection) {
- geometry.transform(this.externalProjection,
- this.internalProjection);
- }
- return geometry;
- },
-
- /**
- * Property: parseCoords
- * Object with properties corresponding to the GeoJSON geometry types.
- * Property values are functions that do the actual parsing.
- */
- parseCoords: {
- /**
- * Method: parseCoords.point
- * Convert a coordinate array from GeoJSON into an
- * <OpenLayers.Geometry>.
- *
- * Parameters:
- * array - {Object} The coordinates array from the GeoJSON fragment.
- *
- * Returns:
- * {<OpenLayers.Geometry>} A geometry.
- */
- "point": function(array) {
- if (this.ignoreExtraDims == false &&
- array.length != 2) {
- throw "Only 2D points are supported: " + array;
- }
- return new OpenLayers.Geometry.Point(array[0], array[1]);
- },
-
- /**
- * Method: parseCoords.multipoint
- * Convert a coordinate array from GeoJSON into an
- * <OpenLayers.Geometry>.
- *
- * Parameters:
- * array - {Object} The coordinates array from the GeoJSON fragment.
- *
- * Returns:
- * {<OpenLayers.Geometry>} A geometry.
- */
- "multipoint": function(array) {
- var points = [];
- var p = null;
- for(var i=0, len=array.length; i<len; ++i) {
- try {
- p = this.parseCoords["point"].apply(this, [array[i]]);
- } catch(err) {
- throw err;
- }
- points.push(p);
- }
- return new OpenLayers.Geometry.MultiPoint(points);
- },
-
- /**
- * Method: parseCoords.linestring
- * Convert a coordinate array from GeoJSON into an
- * <OpenLayers.Geometry>.
- *
- * Parameters:
- * array - {Object} The coordinates array from the GeoJSON fragment.
- *
- * Returns:
- * {<OpenLayers.Geometry>} A geometry.
- */
- "linestring": function(array) {
- var points = [];
- var p = null;
- for(var i=0, len=array.length; i<len; ++i) {
- try {
- p = this.parseCoords["point"].apply(this, [array[i]]);
- } catch(err) {
- throw err;
- }
- points.push(p);
- }
- return new OpenLayers.Geometry.LineString(points);
- },
-
- /**
- * Method: parseCoords.multilinestring
- * Convert a coordinate array from GeoJSON into an
- * <OpenLayers.Geometry>.
- *
- * Parameters:
- * array - {Object} The coordinates array from the GeoJSON fragment.
- *
- * Returns:
- * {<OpenLayers.Geometry>} A geometry.
- */
- "multilinestring": function(array) {
- var lines = [];
- var l = null;
- for(var i=0, len=array.length; i<len; ++i) {
- try {
- l = this.parseCoords["linestring"].apply(this, [array[i]]);
- } catch(err) {
- throw err;
- }
- lines.push(l);
- }
- return new OpenLayers.Geometry.MultiLineString(lines);
- },
-
- /**
- * Method: parseCoords.polygon
- * Convert a coordinate array from GeoJSON into an
- * <OpenLayers.Geometry>.
- *
- * Returns:
- * {<OpenLayers.Geometry>} A geometry.
- */
- "polygon": function(array) {
- var rings = [];
- var r, l;
- for(var i=0, len=array.length; i<len; ++i) {
- try {
- l = this.parseCoords["linestring"].apply(this, [array[i]]);
- } catch(err) {
- throw err;
- }
- r = new OpenLayers.Geometry.LinearRing(l.components);
- rings.push(r);
- }
- return new OpenLayers.Geometry.Polygon(rings);
- },
-
- /**
- * Method: parseCoords.multipolygon
- * Convert a coordinate array from GeoJSON into an
- * <OpenLayers.Geometry>.
- *
- * Parameters:
- * array - {Object} The coordinates array from the GeoJSON fragment.
- *
- * Returns:
- * {<OpenLayers.Geometry>} A geometry.
- */
- "multipolygon": function(array) {
- var polys = [];
- var p = null;
- for(var i=0, len=array.length; i<len; ++i) {
- try {
- p = this.parseCoords["polygon"].apply(this, [array[i]]);
- } catch(err) {
- throw err;
- }
- polys.push(p);
- }
- return new OpenLayers.Geometry.MultiPolygon(polys);
- },
-
- /**
- * Method: parseCoords.box
- * Convert a coordinate array from GeoJSON into an
- * <OpenLayers.Geometry>.
- *
- * Parameters:
- * array - {Object} The coordinates array from the GeoJSON fragment.
- *
- * Returns:
- * {<OpenLayers.Geometry>} A geometry.
- */
- "box": function(array) {
- if(array.length != 2) {
- throw "GeoJSON box coordinates must have 2 elements";
- }
- return new OpenLayers.Geometry.Polygon([
- new OpenLayers.Geometry.LinearRing([
- new OpenLayers.Geometry.Point(array[0][0], array[0][1]),
- new OpenLayers.Geometry.Point(array[1][0], array[0][1]),
- new OpenLayers.Geometry.Point(array[1][0], array[1][1]),
- new OpenLayers.Geometry.Point(array[0][0], array[1][1]),
- new OpenLayers.Geometry.Point(array[0][0], array[0][1])
- ])
- ]);
- }
-
- },
-
- /**
- * APIMethod: write
- * Serialize a feature, geometry, array of features into a GeoJSON string.
- *
- * Parameters:
- * obj - {Object} An <OpenLayers.Feature.Vector>, <OpenLayers.Geometry>,
- * or an array of features.
- * pretty - {Boolean} Structure the output with newlines and indentation.
- * Default is false.
- *
- * Returns:
- * {String} The GeoJSON string representation of the input geometry,
- * features, or array of features.
- */
- write: function(obj, pretty) {
- var geojson = {
- "type": null
- };
- if(OpenLayers.Util.isArray(obj)) {
- geojson.type = "FeatureCollection";
- var numFeatures = obj.length;
- geojson.features = new Array(numFeatures);
- for(var i=0; i<numFeatures; ++i) {
- var element = obj[i];
- if(!element instanceof OpenLayers.Feature.Vector) {
- var msg = "FeatureCollection only supports collections " +
- "of features: " + element;
- throw msg;
- }
- geojson.features[i] = this.extract.feature.apply(
- this, [element]
- );
- }
- } else if (obj.CLASS_NAME.indexOf("OpenLayers.Geometry") == 0) {
- geojson = this.extract.geometry.apply(this, [obj]);
- } else if (obj instanceof OpenLayers.Feature.Vector) {
- geojson = this.extract.feature.apply(this, [obj]);
- if(obj.layer && obj.layer.projection) {
- geojson.crs = this.createCRSObject(obj);
- }
- }
- return OpenLayers.Format.JSON.prototype.write.apply(this,
- [geojson, pretty]);
- },
-
- /**
- * Method: createCRSObject
- * Create the CRS object for an object.
- *
- * Parameters:
- * object - {<OpenLayers.Feature.Vector>}
- *
- * Returns:
- * {Object} An object which can be assigned to the crs property
- * of a GeoJSON object.
- */
- createCRSObject: function(object) {
- var proj = object.layer.projection.toString();
- var crs = {};
- if (proj.match(/epsg:/i)) {
- var code = parseInt(proj.substring(proj.indexOf(":") + 1));
- if (code == 4326) {
- crs = {
- "type": "name",
- "properties": {
- "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
- }
- };
- } else {
- crs = {
- "type": "name",
- "properties": {
- "name": "EPSG:" + code
- }
- };
- }
- }
- return crs;
- },
-
- /**
- * Property: extract
- * Object with properties corresponding to the GeoJSON types.
- * Property values are functions that do the actual value extraction.
- */
- extract: {
- /**
- * Method: extract.feature
- * Return a partial GeoJSON object representing a single feature.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- *
- * Returns:
- * {Object} An object representing the point.
- */
- 'feature': function(feature) {
- var geom = this.extract.geometry.apply(this, [feature.geometry]);
- var json = {
- "type": "Feature",
- "properties": feature.attributes,
- "geometry": geom
- };
- if (feature.fid != null) {
- json.id = feature.fid;
- }
- return json;
- },
-
- /**
- * Method: extract.geometry
- * Return a GeoJSON object representing a single geometry.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {Object} An object representing the geometry.
- */
- 'geometry': function(geometry) {
- if (geometry == null) {
- return null;
- }
- if (this.internalProjection && this.externalProjection) {
- geometry = geometry.clone();
- geometry.transform(this.internalProjection,
- this.externalProjection);
- }
- var geometryType = geometry.CLASS_NAME.split('.')[2];
- var data = this.extract[geometryType.toLowerCase()].apply(this, [geometry]);
- var json;
- if(geometryType == "Collection") {
- json = {
- "type": "GeometryCollection",
- "geometries": data
- };
- } else {
- json = {
- "type": geometryType,
- "coordinates": data
- };
- }
-
- return json;
- },
-
- /**
- * Method: extract.point
- * Return an array of coordinates from a point.
- *
- * Parameters:
- * point - {<OpenLayers.Geometry.Point>}
- *
- * Returns:
- * {Array} An array of coordinates representing the point.
- */
- 'point': function(point) {
- return [point.x, point.y];
- },
-
- /**
- * Method: extract.multipoint
- * Return an array of point coordinates from a multipoint.
- *
- * Parameters:
- * multipoint - {<OpenLayers.Geometry.MultiPoint>}
- *
- * Returns:
- * {Array} An array of point coordinate arrays representing
- * the multipoint.
- */
- 'multipoint': function(multipoint) {
- var array = [];
- for(var i=0, len=multipoint.components.length; i<len; ++i) {
- array.push(this.extract.point.apply(this, [multipoint.components[i]]));
- }
- return array;
- },
-
- /**
- * Method: extract.linestring
- * Return an array of coordinate arrays from a linestring.
- *
- * Parameters:
- * linestring - {<OpenLayers.Geometry.LineString>}
- *
- * Returns:
- * {Array} An array of coordinate arrays representing
- * the linestring.
- */
- 'linestring': function(linestring) {
- var array = [];
- for(var i=0, len=linestring.components.length; i<len; ++i) {
- array.push(this.extract.point.apply(this, [linestring.components[i]]));
- }
- return array;
- },
-
- /**
- * Method: extract.multilinestring
- * Return an array of linestring arrays from a linestring.
- *
- * Parameters:
- * multilinestring - {<OpenLayers.Geometry.MultiLineString>}
- *
- * Returns:
- * {Array} An array of linestring arrays representing
- * the multilinestring.
- */
- 'multilinestring': function(multilinestring) {
- var array = [];
- for(var i=0, len=multilinestring.components.length; i<len; ++i) {
- array.push(this.extract.linestring.apply(this, [multilinestring.components[i]]));
- }
- return array;
- },
-
- /**
- * Method: extract.polygon
- * Return an array of linear ring arrays from a polygon.
- *
- * Parameters:
- * polygon - {<OpenLayers.Geometry.Polygon>}
- *
- * Returns:
- * {Array} An array of linear ring arrays representing the polygon.
- */
- 'polygon': function(polygon) {
- var array = [];
- for(var i=0, len=polygon.components.length; i<len; ++i) {
- array.push(this.extract.linestring.apply(this, [polygon.components[i]]));
- }
- return array;
- },
-
- /**
- * Method: extract.multipolygon
- * Return an array of polygon arrays from a multipolygon.
- *
- * Parameters:
- * multipolygon - {<OpenLayers.Geometry.MultiPolygon>}
- *
- * Returns:
- * {Array} An array of polygon arrays representing
- * the multipolygon
- */
- 'multipolygon': function(multipolygon) {
- var array = [];
- for(var i=0, len=multipolygon.components.length; i<len; ++i) {
- array.push(this.extract.polygon.apply(this, [multipolygon.components[i]]));
- }
- return array;
- },
-
- /**
- * Method: extract.collection
- * Return an array of geometries from a geometry collection.
- *
- * Parameters:
- * collection - {<OpenLayers.Geometry.Collection>}
- *
- * Returns:
- * {Array} An array of geometry objects representing the geometry
- * collection.
- */
- 'collection': function(collection) {
- var len = collection.components.length;
- var array = new Array(len);
- for(var i=0; i<len; ++i) {
- array[i] = this.extract.geometry.apply(
- this, [collection.components[i]]
- );
- }
- return array;
- }
-
-
- },
-
- CLASS_NAME: "OpenLayers.Format.GeoJSON"
-
-});
-/* ======================================================================
OpenLayers/Strategy/Paging.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -60252,11 +61578,11 @@
});
/* ======================================================================
OpenLayers/Popup/Anchored.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -60451,11 +61777,11 @@
});
/* ======================================================================
OpenLayers/Popup/Framed.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -60798,11 +62124,11 @@
});
/* ======================================================================
OpenLayers/Handler/Box.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -61046,11 +62372,11 @@
});
/* ======================================================================
OpenLayers/Control/ZoomBox.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -61117,11 +62443,12 @@
* Parameters:
* position - {<OpenLayers.Bounds>} or {<OpenLayers.Pixel>}
*/
zoomBox: function (position) {
if (position instanceof OpenLayers.Bounds) {
- var bounds;
+ var bounds,
+ targetCenterPx = position.getCenterPixel();
if (!this.out) {
var minXY = this.map.getLonLatFromPixel({
x: position.left,
y: position.bottom
});
@@ -61130,47 +62457,59 @@
y: position.top
});
bounds = new OpenLayers.Bounds(minXY.lon, minXY.lat,
maxXY.lon, maxXY.lat);
} else {
- var pixWidth = Math.abs(position.right-position.left);
- var pixHeight = Math.abs(position.top-position.bottom);
+ var pixWidth = position.right - position.left;
+ var pixHeight = position.bottom - position.top;
var zoomFactor = Math.min((this.map.size.h / pixHeight),
(this.map.size.w / pixWidth));
var extent = this.map.getExtent();
- var center = this.map.getLonLatFromPixel(
- position.getCenterPixel());
+ var center = this.map.getLonLatFromPixel(targetCenterPx);
var xmin = center.lon - (extent.getWidth()/2)*zoomFactor;
var xmax = center.lon + (extent.getWidth()/2)*zoomFactor;
var ymin = center.lat - (extent.getHeight()/2)*zoomFactor;
var ymax = center.lat + (extent.getHeight()/2)*zoomFactor;
bounds = new OpenLayers.Bounds(xmin, ymin, xmax, ymax);
}
// always zoom in/out
- var lastZoom = this.map.getZoom();
- this.map.zoomToExtent(bounds);
+ var lastZoom = this.map.getZoom(),
+ size = this.map.getSize(),
+ centerPx = {x: size.w / 2, y: size.h / 2},
+ zoom = this.map.getZoomForExtent(bounds),
+ oldRes = this.map.getResolution(),
+ newRes = this.map.getResolutionForZoom(zoom);
+ if (oldRes == newRes) {
+ this.map.setCenter(this.map.getLonLatFromPixel(targetCenterPx));
+ } else {
+ var zoomOriginPx = {
+ x: (oldRes * targetCenterPx.x - newRes * centerPx.x) /
+ (oldRes - newRes),
+ y: (oldRes * targetCenterPx.y - newRes * centerPx.y) /
+ (oldRes - newRes)
+ };
+ this.map.zoomTo(zoom, zoomOriginPx);
+ }
if (lastZoom == this.map.getZoom() && this.alwaysZoom == true){
this.map.zoomTo(lastZoom + (this.out ? -1 : 1));
}
} else if (this.zoomOnClick) { // it's a pixel
if (!this.out) {
- this.map.setCenter(this.map.getLonLatFromPixel(position),
- this.map.getZoom() + 1);
+ this.map.zoomTo(this.map.getZoom() + 1, position);
} else {
- this.map.setCenter(this.map.getLonLatFromPixel(position),
- this.map.getZoom() - 1);
+ this.map.zoomTo(this.map.getZoom() - 1, position);
}
}
},
CLASS_NAME: "OpenLayers.Control.ZoomBox"
});
/* ======================================================================
OpenLayers/Control/DragPan.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -61200,15 +62539,16 @@
panned: false,
/**
* Property: interval
* {Integer} The number of milliseconds that should ellapse before
- * panning the map again. Defaults to 1 millisecond. In most cases
- * you won't want to change this value. For slow machines/devices
- * larger values can be tried out.
+ * panning the map again. Defaults to 0 milliseconds, which means that
+ * no separate cycle is used for panning. In most cases you won't want
+ * to change this value. For slow machines/devices larger values can be
+ * tried out.
*/
- interval: 1,
+ interval: 0,
/**
* APIProperty: documentDrag
* {Boolean} If set to true, mouse dragging will continue even if the
* mouse cursor leaves the map viewport. Default is false.
@@ -61224,15 +62564,15 @@
/**
* APIProperty: enableKinetic
* {Boolean} Set this option to enable "kinetic dragging". Can be
* set to true or to an object. If set to an object this
* object will be passed to the {<OpenLayers.Kinetic>}
- * constructor. Defaults to false.
- * If you set this property, you should ensure that
- * OpenLayers/Kinetic.js is included in your build config
+ * constructor. Defaults to true.
+ * To get kinetic dragging, ensure that OpenLayers/Kinetic.js is
+ * included in your build config.
*/
- enableKinetic: false,
+ enableKinetic: true,
/**
* APIProperty: kineticInterval
* {Integer} Interval in milliseconds between 2 steps in the "kinetic
* scrolling". Applies only if enableKinetic is set. Defaults
@@ -61245,11 +62585,11 @@
* Method: draw
* Creates a Drag handler, using <panMap> and
* <panMapDone> as callbacks.
*/
draw: function() {
- if(this.enableKinetic) {
+ if (this.enableKinetic && OpenLayers.Kinetic) {
var config = {interval: this.kineticInterval};
if(typeof this.enableKinetic === "object") {
config = OpenLayers.Util.extend(config, this.enableKinetic);
}
this.kinetic = new OpenLayers.Kinetic(config);
@@ -61325,11 +62665,11 @@
});
/* ======================================================================
OpenLayers/Control/Navigation.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -61404,11 +62744,13 @@
zoomWheelEnabled: true,
/**
* Property: mouseWheelOptions
* {Object} Options passed to the MouseWheel control (only useful if
- * <zoomWheelEnabled> is set to true)
+ * <zoomWheelEnabled> is set to true). Default is no options for maps
+ * with fractionalZoom set to true, otherwise
+ * {cumulative: false, interval: 50, maxDelta: 6}
*/
mouseWheelOptions: null,
/**
* APIProperty: handleRightClicks
@@ -61535,14 +62877,19 @@
);
this.zoomBox = new OpenLayers.Control.ZoomBox(
{map: this.map, keyMask: this.zoomBoxKeyMask});
this.dragPan.draw();
this.zoomBox.draw();
+ var wheelOptions = this.map.fractionalZoom ? {} : {
+ cumulative: false,
+ interval: 50,
+ maxDelta: 6
+ };
this.handlers.wheel = new OpenLayers.Handler.MouseWheel(
- this, {"up" : this.wheelUp,
- "down": this.wheelDown},
- this.mouseWheelOptions );
+ this, {up : this.wheelUp, down: this.wheelDown},
+ OpenLayers.Util.extend(wheelOptions, this.mouseWheelOptions)
+ );
if (OpenLayers.Control.PinchZoom) {
this.pinchZoom = new OpenLayers.Control.PinchZoom(
OpenLayers.Util.extend(
{map: this.map}, this.pinchZoomOptions));
}
@@ -61565,23 +62912,21 @@
*
* Parameters:
* evt - {Event}
*/
defaultDblClick: function (evt) {
- var newCenter = this.map.getLonLatFromViewPortPx( evt.xy );
- this.map.setCenter(newCenter, this.map.zoom + 1);
+ this.map.zoomTo(this.map.zoom + 1, evt.xy);
},
/**
* Method: defaultDblRightClick
*
* Parameters:
* evt - {Event}
*/
defaultDblRightClick: function (evt) {
- var newCenter = this.map.getLonLatFromViewPortPx( evt.xy );
- this.map.setCenter(newCenter, this.map.zoom - 1);
+ this.map.zoomTo(this.map.zoom - 1, evt.xy);
},
/**
* Method: wheelChange
*
@@ -61591,26 +62936,18 @@
*/
wheelChange: function(evt, deltaZ) {
if (!this.map.fractionalZoom) {
deltaZ = Math.round(deltaZ);
}
- var currentZoom = this.map.getZoom();
- var newZoom = this.map.getZoom() + deltaZ;
+ var currentZoom = this.map.getZoom(),
+ newZoom = currentZoom + deltaZ;
newZoom = Math.max(newZoom, 0);
newZoom = Math.min(newZoom, this.map.getNumZoomLevels());
if (newZoom === currentZoom) {
return;
}
- var size = this.map.getSize();
- var deltaX = size.w/2 - evt.xy.x;
- var deltaY = evt.xy.y - size.h/2;
- var newRes = this.map.baseLayer.getResolutionForZoom(newZoom);
- var zoomPoint = this.map.getLonLatFromPixel(evt.xy);
- var newCenter = new OpenLayers.LonLat(
- zoomPoint.lon + deltaX * newRes,
- zoomPoint.lat + deltaY * newRes );
- this.map.setCenter( newCenter, newZoom );
+ this.map.zoomTo(newZoom, evt.xy);
},
/**
* Method: wheelUp
* User spun scroll wheel up
@@ -61677,11 +63014,11 @@
});
/* ======================================================================
OpenLayers/Control/DrawFeature.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -61910,11 +63247,11 @@
});
/* ======================================================================
OpenLayers/Handler/Polygon.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -62219,11 +63556,11 @@
});
/* ======================================================================
OpenLayers/Control/EditingToolbar.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -62304,11 +63641,11 @@
});
/* ======================================================================
OpenLayers/Format/WMSGetFeatureInfo.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -62326,16 +63663,16 @@
/**
* APIProperty: layerIdentifier
* {String} All xml nodes containing this search criteria will populate an
* internal array of layer nodes.
- */
+ */
layerIdentifier: '_layer',
/**
* APIProperty: featureIdentifier
- * {String} All xml nodes containing this search criteria will populate an
+ * {String} All xml nodes containing this search criteria will populate an
* internal array of feature nodes for each layer node found.
*/
featureIdentifier: '_feature',
/**
@@ -62394,12 +63731,12 @@
} else {
result = data;
}
return result;
},
-
-
+
+
/**
* Method: read_msGMLOutput
* Parse msGMLOutput nodes.
*
* Parameters:
@@ -62418,29 +63755,29 @@
var layerName = node.nodeName;
if (node.prefix) {
layerName = layerName.split(':')[1];
}
var layerName = layerName.replace(this.layerIdentifier, '');
- var featureNodes = this.getSiblingNodesByTagCriteria(node,
+ var featureNodes = this.getSiblingNodesByTagCriteria(node,
this.featureIdentifier);
if (featureNodes) {
for (var j = 0; j < featureNodes.length; j++) {
var featureNode = featureNodes[j];
var geomInfo = this.parseGeometry(featureNode);
var attributes = this.parseAttributes(featureNode);
- var feature = new OpenLayers.Feature.Vector(geomInfo.geometry,
+ var feature = new OpenLayers.Feature.Vector(geomInfo.geometry,
attributes, null);
feature.bounds = geomInfo.bounds;
feature.type = layerName;
response.push(feature);
}
}
}
}
return response;
},
-
+
/**
* Method: read_FeatureInfoResponse
* Parse FeatureInfoResponse nodes.
*
* Parameters:
@@ -62456,11 +63793,11 @@
for(var i=0, len=featureNodes.length;i<len;i++) {
var featureNode = featureNodes[i];
var geom = null;
- // attributes can be actual attributes on the FIELDS tag,
+ // attributes can be actual attributes on the FIELDS tag,
// or FIELD children
var attributes = {};
var j;
var jlen = featureNode.attributes.length;
if (jlen > 0) {
@@ -62471,11 +63808,11 @@
} else {
var nodes = featureNode.childNodes;
for (j=0, jlen=nodes.length; j<jlen; ++j) {
var node = nodes[j];
if (node.nodeType != 3) {
- attributes[node.getAttribute("name")] =
+ attributes[node.getAttribute("name")] =
node.getAttribute("value");
}
}
}
@@ -62486,22 +63823,22 @@
return response;
},
/**
* Method: getSiblingNodesByTagCriteria
- * Recursively searches passed xml node and all it's descendant levels for
- * nodes whose tagName contains the passed search string. This returns an
- * array of all sibling nodes which match the criteria from the highest
+ * Recursively searches passed xml node and all it's descendant levels for
+ * nodes whose tagName contains the passed search string. This returns an
+ * array of all sibling nodes which match the criteria from the highest
* hierarchial level from which a match is found.
- *
+ *
* Parameters:
* node - {DOMElement} An xml node
- * criteria - {String} Search string which will match some part of a tagName
- *
+ * criteria - {String} Search string which will match some part of a tagName
+ *
* Returns:
* Array({DOMElement}) An array of sibling xml nodes
- */
+ */
getSiblingNodesByTagCriteria: function(node, criteria){
var nodes = [];
var children, tagName, n, matchNodes, child;
if (node && node.hasChildNodes()) {
children = node.childNodes;
@@ -62519,11 +63856,11 @@
} else {
matchNodes = this.getSiblingNodesByTagCriteria(
child, criteria);
if(matchNodes.length > 0){
- (nodes.length == 0) ?
+ (nodes.length == 0) ?
nodes = matchNodes : nodes.push(matchNodes);
}
}
}
@@ -62537,15 +63874,15 @@
* Parameters:
* node - {<DOMElement>}
*
* Returns:
* {Object} An attributes object.
- *
+ *
* Notes:
* Assumes that attributes are direct child xml nodes of the passed node
- * and contain only a single text node.
- */
+ * and contain only a single text node.
+ */
parseAttributes: function(node){
var attributes = {};
if (node.nodeType == 1) {
var children = node.childNodes;
var n = children.length;
@@ -62555,38 +63892,46 @@
var grandchildren = child.childNodes;
var name = (child.prefix) ?
child.nodeName.split(":")[1] : child.nodeName;
if (grandchildren.length == 0) {
attributes[name] = null;
- } else if (grandchildren.length == 1) {
+ } else if (grandchildren.length == 1 ||
+ // to include separate big tag (with Firefox)
+ // without including boundedBy and geom.
+ grandchildren[0].nodeValue.replace(
+ this.regExes.trimSpace, "").length > 0) {
var grandchild = grandchildren[0];
if (grandchild.nodeType == 3 ||
- grandchild.nodeType == 4) {
- var value = grandchild.nodeValue.replace(
- this.regExes.trimSpace, "");
- attributes[name] = value;
+ grandchild.nodeType == 4) {
+ // wholeText doesn't exist everywhere but we need it for FireFox
+ // see i.e.: http://msdn.microsoft.com/en-us/library/ie/ff974769%28v=vs.85%29.aspx
+ var attribute = grandchild.wholeText ?
+ grandchild.wholeText :
+ grandchild.nodeValue;
+ attributes[name] = attribute.replace(
+ this.regExes.trimSpace, "");
}
}
}
}
}
return attributes;
},
/**
* Method: parseGeometry
- * Parse the geometry and the feature bounds out of the node using
+ * Parse the geometry and the feature bounds out of the node using
* Format.GML
*
* Parameters:
* node - {<DOMElement>}
*
* Returns:
* {Object} An object containing the geometry and the feature bounds
*/
parseGeometry: function(node) {
- // we need to use the old Format.GML parser since we do not know the
+ // we need to use the old Format.GML parser since we do not know the
// geometry name
if (!this.gmlFormat) {
this.gmlFormat = new OpenLayers.Format.GML();
}
var feature = this.gmlFormat.parseFeature(node);
@@ -62598,1139 +63943,1200 @@
}
return {geometry: geometry, bounds: bounds};
},
CLASS_NAME: "OpenLayers.Format.WMSGetFeatureInfo"
-
-});
-/* ======================================================================
- Rico/license.js
- ====================================================================== */
-/**
- * @license Apache 2
- *
- * Contains portions of Rico <http://openrico.org/>
- *
- * Copyright 2005 Sabre Airline Solutions
- *
- * 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.
- */
-/* ======================================================================
- Rico/Color.js
- ====================================================================== */
-
-/**
- * @requires Rico/license.js
- * @requires OpenLayers/Console.js
- * @requires OpenLayers/BaseTypes/Class.js
- * @requires OpenLayers/BaseTypes/Element.js
- */
-
-
-/*
- * This file has been edited substantially from the Rico-released version by
- * the OpenLayers development team.
- */
-
-OpenLayers.Console.warn("OpenLayers.Rico is deprecated");
-
-OpenLayers.Rico = OpenLayers.Rico || {};
-OpenLayers.Rico.Color = OpenLayers.Class({
-
- initialize: function(red, green, blue) {
- this.rgb = { r: red, g : green, b : blue };
- },
-
- setRed: function(r) {
- this.rgb.r = r;
- },
-
- setGreen: function(g) {
- this.rgb.g = g;
- },
-
- setBlue: function(b) {
- this.rgb.b = b;
- },
-
- setHue: function(h) {
-
- // get an HSB model, and set the new hue...
- var hsb = this.asHSB();
- hsb.h = h;
-
- // convert back to RGB...
- this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
- },
-
- setSaturation: function(s) {
- // get an HSB model, and set the new hue...
- var hsb = this.asHSB();
- hsb.s = s;
-
- // convert back to RGB and set values...
- this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
- },
-
- setBrightness: function(b) {
- // get an HSB model, and set the new hue...
- var hsb = this.asHSB();
- hsb.b = b;
-
- // convert back to RGB and set values...
- this.rgb = OpenLayers.Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
- },
-
- darken: function(percent) {
- var hsb = this.asHSB();
- this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
- },
-
- brighten: function(percent) {
- var hsb = this.asHSB();
- this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
- },
-
- blend: function(other) {
- this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
- this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
- this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
- },
-
- isBright: function() {
- var hsb = this.asHSB();
- return this.asHSB().b > 0.5;
- },
-
- isDark: function() {
- return ! this.isBright();
- },
-
- asRGB: function() {
- return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
- },
-
- asHex: function() {
- return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
- },
-
- asHSB: function() {
- return OpenLayers.Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
- },
-
- toString: function() {
- return this.asHex();
- }
-
});
-
-OpenLayers.Rico.Color.createFromHex = function(hexCode) {
- if(hexCode.length==4) {
- var shortHexCode = hexCode;
- var hexCode = '#';
- for(var i=1;i<4;i++) {
- hexCode += (shortHexCode.charAt(i) +
-shortHexCode.charAt(i));
- }
- }
- if ( hexCode.indexOf('#') == 0 ) {
- hexCode = hexCode.substring(1);
- }
- var red = hexCode.substring(0,2);
- var green = hexCode.substring(2,4);
- var blue = hexCode.substring(4,6);
- return new OpenLayers.Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
-};
-
-/**
- * Factory method for creating a color from the background of
- * an HTML element.
- */
-OpenLayers.Rico.Color.createColorFromBackground = function(elem) {
-
- var actualColor =
- OpenLayers.Element.getStyle(OpenLayers.Util.getElement(elem),
- "backgroundColor");
-
- if ( actualColor == "transparent" && elem.parentNode ) {
- return OpenLayers.Rico.Color.createColorFromBackground(elem.parentNode);
- }
- if ( actualColor == null ) {
- return new OpenLayers.Rico.Color(255,255,255);
- }
- if ( actualColor.indexOf("rgb(") == 0 ) {
- var colors = actualColor.substring(4, actualColor.length - 1 );
- var colorArray = colors.split(",");
- return new OpenLayers.Rico.Color( parseInt( colorArray[0] ),
- parseInt( colorArray[1] ),
- parseInt( colorArray[2] ) );
-
- }
- else if ( actualColor.indexOf("#") == 0 ) {
- return OpenLayers.Rico.Color.createFromHex(actualColor);
- }
- else {
- return new OpenLayers.Rico.Color(255,255,255);
- }
-};
-
-OpenLayers.Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
-
- var red = 0;
- var green = 0;
- var blue = 0;
-
- if (saturation == 0) {
- red = parseInt(brightness * 255.0 + 0.5);
- green = red;
- blue = red;
- }
- else {
- var h = (hue - Math.floor(hue)) * 6.0;
- var f = h - Math.floor(h);
- var p = brightness * (1.0 - saturation);
- var q = brightness * (1.0 - saturation * f);
- var t = brightness * (1.0 - (saturation * (1.0 - f)));
-
- switch (parseInt(h)) {
- case 0:
- red = (brightness * 255.0 + 0.5);
- green = (t * 255.0 + 0.5);
- blue = (p * 255.0 + 0.5);
- break;
- case 1:
- red = (q * 255.0 + 0.5);
- green = (brightness * 255.0 + 0.5);
- blue = (p * 255.0 + 0.5);
- break;
- case 2:
- red = (p * 255.0 + 0.5);
- green = (brightness * 255.0 + 0.5);
- blue = (t * 255.0 + 0.5);
- break;
- case 3:
- red = (p * 255.0 + 0.5);
- green = (q * 255.0 + 0.5);
- blue = (brightness * 255.0 + 0.5);
- break;
- case 4:
- red = (t * 255.0 + 0.5);
- green = (p * 255.0 + 0.5);
- blue = (brightness * 255.0 + 0.5);
- break;
- case 5:
- red = (brightness * 255.0 + 0.5);
- green = (p * 255.0 + 0.5);
- blue = (q * 255.0 + 0.5);
- break;
- }
- }
-
- return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
-};
-
-OpenLayers.Rico.Color.RGBtoHSB = function(r, g, b) {
-
- var hue;
- var saturation;
- var brightness;
-
- var cmax = (r > g) ? r : g;
- if (b > cmax) {
- cmax = b;
- }
- var cmin = (r < g) ? r : g;
- if (b < cmin) {
- cmin = b;
- }
- brightness = cmax / 255.0;
- if (cmax != 0) {
- saturation = (cmax - cmin)/cmax;
- } else {
- saturation = 0;
- }
- if (saturation == 0) {
- hue = 0;
- } else {
- var redc = (cmax - r)/(cmax - cmin);
- var greenc = (cmax - g)/(cmax - cmin);
- var bluec = (cmax - b)/(cmax - cmin);
-
- if (r == cmax) {
- hue = bluec - greenc;
- } else if (g == cmax) {
- hue = 2.0 + redc - bluec;
- } else {
- hue = 4.0 + greenc - redc;
- }
- hue = hue / 6.0;
- if (hue < 0) {
- hue = hue + 1.0;
- }
- }
-
- return { h : hue, s : saturation, b : brightness };
-};
-
/* ======================================================================
- Rico/Corner.js
+ OpenLayers/Format/GeoJSON.js
====================================================================== */
-/**
- * @requires OpenLayers/Console.js
- * @requires Rico/Color.js
- */
-
-
-/*
- * This file has been edited substantially from the Rico-released
- * version by the OpenLayers development team.
- *
- * Copyright 2005 Sabre Airline Solutions
- *
- * 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.
- *
- */
-
-OpenLayers.Console.warn("OpenLayers.Rico is deprecated");
-
-OpenLayers.Rico = OpenLayers.Rico || {};
-OpenLayers.Rico.Corner = {
-
- round: function(e, options) {
- e = OpenLayers.Util.getElement(e);
- this._setOptions(options);
-
- var color = this.options.color;
- if ( this.options.color == "fromElement" ) {
- color = this._background(e);
- }
- var bgColor = this.options.bgColor;
- if ( this.options.bgColor == "fromParent" ) {
- bgColor = this._background(e.offsetParent);
- }
- this._roundCornersImpl(e, color, bgColor);
- },
-
- /** This is a helper function to change the background
- * color of <div> that has had Rico rounded corners added.
- *
- * It seems we cannot just set the background color for the
- * outer <div> so each <span> element used to create the
- * corners must have its background color set individually.
- *
- * @param {DOM} theDiv - A child of the outer <div> that was
- * supplied to the `round` method.
- *
- * @param {String} newColor - The new background color to use.
- */
- changeColor: function(theDiv, newColor) {
-
- theDiv.style.backgroundColor = newColor;
-
- var spanElements = theDiv.parentNode.getElementsByTagName("span");
-
- for (var currIdx = 0; currIdx < spanElements.length; currIdx++) {
- spanElements[currIdx].style.backgroundColor = newColor;
- }
- },
-
-
- /** This is a helper function to change the background
- * opacity of <div> that has had Rico rounded corners added.
- *
- * See changeColor (above) for algorithm explanation
- *
- * @param {DOM} theDiv A child of the outer <div> that was
- * supplied to the `round` method.
- *
- * @param {int} newOpacity The new opacity to use (0-1).
- */
- changeOpacity: function(theDiv, newOpacity) {
-
- 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 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 <div> that was
- * supplied to the `round` method.
- *
- * @param {Object} options - list of options
- */
- reRound: function(theDiv, options) {
-
- 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);
- }
- },
-
- _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 = "<div " + style + ">" + el.innerHTML + "</div>";
- },
-
- _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"));
- }
- el.style.paddingTop = 0;
- el.insertBefore(corner,el.firstChild);
- },
-
- _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);
- },
-
- _createCorner: function(bgColor) {
- var corner = document.createElement("div");
- corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor);
- return corner;
- },
-
- _createCornerSlice: function(color,bgColor, n, position) {
- var slice = document.createElement("span");
-
- var inStyle = slice.style;
- inStyle.backgroundColor = color;
- inStyle.display = "block";
- inStyle.height = "1px";
- inStyle.overflow = "hidden";
- inStyle.fontSize = "1px";
-
- 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";
- }
-
- if ( !this.options.compact && (n == (this.options.numSlices-1)) ) {
- inStyle.height = "2px";
- }
- this._setMargin(slice, n, position);
- this._setBorder(slice, n, position);
- return slice;
- },
-
- _setOptions: function(options) {
- this.options = {
- corners : "all",
- color : "fromElement",
- bgColor : "fromParent",
- blend : true,
- border : false,
- compact : false
- };
- OpenLayers.Util.extend(this.options, options || {});
-
- this.options.numSlices = this.options.compact ? 2 : 4;
- if ( this._isTransparent() ) {
- this.options.blend = false;
- }
- },
-
- _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 "";
- },
-
- _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 "";
- }
-
- if(this.options.corners.indexOf("bl") >=0) {
- return "left";
- } else if(this.options.corners.indexOf("br")>=0) {
- return "right";
- }
- return "";
- },
-
- _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 "";
- }
- },
-
-
- _setMargin: function(el, n, corners) {
- var marginSize = this._marginSize(n);
- var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
-
- 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";
- }
- },
-
- _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";
- }
- },
-
- _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];
- }
- },
-
- _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;
- },
-
- _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/Popup/AnchoredBubble.js
- ====================================================================== */
-
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Popup/Anchored.js
+ * @requires OpenLayers/Format/JSON.js
+ * @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/MultiPoint.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/MultiLineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/MultiPolygon.js
* @requires OpenLayers/Console.js
- * @requires Rico/Corner.js
*/
/**
- * Class: OpenLayers.Popup.AnchoredBubble
- * This class is *deprecated*. Use {<OpenLayers.Popup.Anchored>} and
- * round corners using CSS3's border-radius property.
- *
- * Inherits from:
- * - <OpenLayers.Popup.Anchored>
+ * Class: OpenLayers.Format.GeoJSON
+ * Read and write GeoJSON. Create a new parser with the
+ * <OpenLayers.Format.GeoJSON> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.JSON>
*/
-OpenLayers.Popup.AnchoredBubble =
- OpenLayers.Class(OpenLayers.Popup.Anchored, {
+OpenLayers.Format.GeoJSON = OpenLayers.Class(OpenLayers.Format.JSON, {
/**
- * Property: rounded
- * {Boolean} Has the popup been rounded yet?
- */
- rounded: false,
+ * APIProperty: ignoreExtraDims
+ * {Boolean} Ignore dimensions higher than 2 when reading geometry
+ * coordinates.
+ */
+ ignoreExtraDims: false,
- /**
- * Constructor: OpenLayers.Popup.AnchoredBubble
- *
+ /**
+ * Constructor: OpenLayers.Format.GeoJSON
+ * Create a new parser for GeoJSON.
+ *
* Parameters:
- * id - {String}
- * lonlat - {<OpenLayers.LonLat>}
- * contentSize - {<OpenLayers.Size>}
- * contentHTML - {String}
- * anchor - {Object} Object to which we'll anchor the popup. Must expose
- * a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>)
- * (Note that this is generally an <OpenLayers.Icon>).
- * closeBox - {Boolean}
- * closeBoxCallback - {Function} Function to be called on closeBox click.
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
*/
- initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox,
- closeBoxCallback) {
- OpenLayers.Console.warn('AnchoredBubble is deprecated');
-
- this.padding = new OpenLayers.Bounds(
- 0, OpenLayers.Popup.AnchoredBubble.CORNER_SIZE,
- 0, OpenLayers.Popup.AnchoredBubble.CORNER_SIZE
- );
- OpenLayers.Popup.Anchored.prototype.initialize.apply(this, arguments);
- },
-
- /**
- * Method: draw
- *
+ /**
+ * APIMethod: read
+ * Deserialize a GeoJSON string.
+ *
* Parameters:
- * px - {<OpenLayers.Pixel>}
- *
- * Returns:
- * {DOMElement} Reference to a div that contains the drawn popup.
+ * json - {String} A GeoJSON string
+ * type - {String} Optional string that determines the structure of
+ * the output. Supported values are "Geometry", "Feature", and
+ * "FeatureCollection". If absent or null, a default of
+ * "FeatureCollection" is assumed.
+ * filter - {Function} A function which will be called for every key and
+ * value at every level of the final result. Each value will be
+ * replaced by the result of the filter function. This can be used to
+ * reform generic objects into instances of classes, or to transform
+ * date strings into Date objects.
+ *
+ * Returns:
+ * {Object} The return depends on the value of the type argument. If type
+ * is "FeatureCollection" (the default), the return will be an array
+ * of <OpenLayers.Feature.Vector>. If type is "Geometry", the input json
+ * must represent a single geometry, and the return will be an
+ * <OpenLayers.Geometry>. If type is "Feature", the input json must
+ * represent a single feature, and the return will be an
+ * <OpenLayers.Feature.Vector>.
*/
- draw: function(px) {
-
- OpenLayers.Popup.Anchored.prototype.draw.apply(this, arguments);
-
- this.setContentHTML();
-
- //set the popup color and opacity
- this.setBackgroundColor();
- this.setOpacity();
-
- return this.div;
+ read: function(json, type, filter) {
+ type = (type) ? type : "FeatureCollection";
+ var results = null;
+ var obj = null;
+ if (typeof json == "string") {
+ obj = OpenLayers.Format.JSON.prototype.read.apply(this,
+ [json, filter]);
+ } else {
+ obj = json;
+ }
+ if(!obj) {
+ OpenLayers.Console.error("Bad JSON: " + json);
+ } else if(typeof(obj.type) != "string") {
+ OpenLayers.Console.error("Bad GeoJSON - no type: " + json);
+ } else if(this.isValidType(obj, type)) {
+ switch(type) {
+ case "Geometry":
+ try {
+ results = this.parseGeometry(obj);
+ } catch(err) {
+ OpenLayers.Console.error(err);
+ }
+ break;
+ case "Feature":
+ try {
+ results = this.parseFeature(obj);
+ results.type = "Feature";
+ } catch(err) {
+ OpenLayers.Console.error(err);
+ }
+ break;
+ case "FeatureCollection":
+ // for type FeatureCollection, we allow input to be any type
+ results = [];
+ switch(obj.type) {
+ case "Feature":
+ try {
+ results.push(this.parseFeature(obj));
+ } catch(err) {
+ results = null;
+ OpenLayers.Console.error(err);
+ }
+ break;
+ case "FeatureCollection":
+ for(var i=0, len=obj.features.length; i<len; ++i) {
+ try {
+ results.push(this.parseFeature(obj.features[i]));
+ } catch(err) {
+ results = null;
+ OpenLayers.Console.error(err);
+ }
+ }
+ break;
+ default:
+ try {
+ var geom = this.parseGeometry(obj);
+ results.push(new OpenLayers.Feature.Vector(geom));
+ } catch(err) {
+ results = null;
+ OpenLayers.Console.error(err);
+ }
+ }
+ break;
+ }
+ }
+ return results;
},
-
+
/**
- * Method: updateRelativePosition
- * The popup has been moved to a new relative location, in which case
- * we will want to re-do the rico corners.
+ * Method: isValidType
+ * Check if a GeoJSON object is a valid representative of the given type.
+ *
+ * Returns:
+ * {Boolean} The object is valid GeoJSON object of the given type.
*/
- updateRelativePosition: function() {
- this.setRicoCorners();
+ isValidType: function(obj, type) {
+ var valid = false;
+ switch(type) {
+ case "Geometry":
+ if(OpenLayers.Util.indexOf(
+ ["Point", "MultiPoint", "LineString", "MultiLineString",
+ "Polygon", "MultiPolygon", "Box", "GeometryCollection"],
+ obj.type) == -1) {
+ // unsupported geometry type
+ OpenLayers.Console.error("Unsupported geometry type: " +
+ obj.type);
+ } else {
+ valid = true;
+ }
+ break;
+ case "FeatureCollection":
+ // allow for any type to be converted to a feature collection
+ valid = true;
+ break;
+ default:
+ // for Feature types must match
+ if(obj.type == type) {
+ valid = true;
+ } else {
+ OpenLayers.Console.error("Cannot convert types from " +
+ obj.type + " to " + type);
+ }
+ }
+ return valid;
},
-
+
/**
- * APIMethod: setSize
- *
+ * Method: parseFeature
+ * Convert a feature object from GeoJSON into an
+ * <OpenLayers.Feature.Vector>.
+ *
* Parameters:
- * contentSize - {<OpenLayers.Size>} the new size for the popup's
- * contents div (in pixels).
+ * obj - {Object} An object created from a GeoJSON object
+ *
+ * Returns:
+ * {<OpenLayers.Feature.Vector>} A feature.
*/
- setSize:function(contentSize) {
- OpenLayers.Popup.Anchored.prototype.setSize.apply(this, arguments);
-
- this.setRicoCorners();
- },
-
+ parseFeature: function(obj) {
+ var feature, geometry, attributes, bbox;
+ attributes = (obj.properties) ? obj.properties : {};
+ bbox = (obj.geometry && obj.geometry.bbox) || obj.bbox;
+ try {
+ geometry = this.parseGeometry(obj.geometry);
+ } catch(err) {
+ // deal with bad geometries
+ throw err;
+ }
+ feature = new OpenLayers.Feature.Vector(geometry, attributes);
+ if(bbox) {
+ feature.bounds = OpenLayers.Bounds.fromArray(bbox);
+ }
+ if(obj.id) {
+ feature.fid = obj.id;
+ }
+ return feature;
+ },
+
/**
- * APIMethod: setBackgroundColor
- *
+ * Method: parseGeometry
+ * Convert a geometry object from GeoJSON into an <OpenLayers.Geometry>.
+ *
* Parameters:
- * color - {String}
+ * obj - {Object} An object created from a GeoJSON object
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
*/
- setBackgroundColor:function(color) {
- if (color != undefined) {
- this.backgroundColor = color;
+ parseGeometry: function(obj) {
+ if (obj == null) {
+ return null;
}
-
- if (this.div != null) {
- if (this.contentDiv != null) {
- this.div.style.background = "transparent";
- OpenLayers.Rico.Corner.changeColor(this.groupDiv,
- this.backgroundColor);
+ var geometry, collection = false;
+ if(obj.type == "GeometryCollection") {
+ if(!(OpenLayers.Util.isArray(obj.geometries))) {
+ throw "GeometryCollection must have geometries array: " + obj;
}
+ var numGeom = obj.geometries.length;
+ var components = new Array(numGeom);
+ for(var i=0; i<numGeom; ++i) {
+ components[i] = this.parseGeometry.apply(
+ this, [obj.geometries[i]]
+ );
+ }
+ geometry = new OpenLayers.Geometry.Collection(components);
+ collection = true;
+ } else {
+ if(!(OpenLayers.Util.isArray(obj.coordinates))) {
+ throw "Geometry must have coordinates array: " + obj;
+ }
+ if(!this.parseCoords[obj.type.toLowerCase()]) {
+ throw "Unsupported geometry type: " + obj.type;
+ }
+ try {
+ geometry = this.parseCoords[obj.type.toLowerCase()].apply(
+ this, [obj.coordinates]
+ );
+ } catch(err) {
+ // deal with bad coordinates
+ throw err;
+ }
}
- },
+ // We don't reproject collections because the children are reprojected
+ // for us when they are created.
+ if (this.internalProjection && this.externalProjection && !collection) {
+ geometry.transform(this.externalProjection,
+ this.internalProjection);
+ }
+ return geometry;
+ },
/**
- * APIMethod: setOpacity
- *
- * Parameters:
- * opacity - {float}
+ * Property: parseCoords
+ * Object with properties corresponding to the GeoJSON geometry types.
+ * Property values are functions that do the actual parsing.
*/
- setOpacity:function(opacity) {
- OpenLayers.Popup.Anchored.prototype.setOpacity.call(this, opacity);
+ parseCoords: {
+ /**
+ * Method: parseCoords.point
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "point": function(array) {
+ if (this.ignoreExtraDims == false &&
+ array.length != 2) {
+ throw "Only 2D points are supported: " + array;
+ }
+ return new OpenLayers.Geometry.Point(array[0], array[1]);
+ },
- if (this.div != null) {
- if (this.groupDiv != null) {
- OpenLayers.Rico.Corner.changeOpacity(this.groupDiv,
- this.opacity);
+ /**
+ * Method: parseCoords.multipoint
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "multipoint": function(array) {
+ var points = [];
+ var p = null;
+ for(var i=0, len=array.length; i<len; ++i) {
+ try {
+ p = this.parseCoords["point"].apply(this, [array[i]]);
+ } catch(err) {
+ throw err;
+ }
+ points.push(p);
}
+ return new OpenLayers.Geometry.MultiPoint(points);
+ },
+
+ /**
+ * Method: parseCoords.linestring
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "linestring": function(array) {
+ var points = [];
+ var p = null;
+ for(var i=0, len=array.length; i<len; ++i) {
+ try {
+ p = this.parseCoords["point"].apply(this, [array[i]]);
+ } catch(err) {
+ throw err;
+ }
+ points.push(p);
+ }
+ return new OpenLayers.Geometry.LineString(points);
+ },
+
+ /**
+ * Method: parseCoords.multilinestring
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "multilinestring": function(array) {
+ var lines = [];
+ var l = null;
+ for(var i=0, len=array.length; i<len; ++i) {
+ try {
+ l = this.parseCoords["linestring"].apply(this, [array[i]]);
+ } catch(err) {
+ throw err;
+ }
+ lines.push(l);
+ }
+ return new OpenLayers.Geometry.MultiLineString(lines);
+ },
+
+ /**
+ * Method: parseCoords.polygon
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "polygon": function(array) {
+ var rings = [];
+ var r, l;
+ for(var i=0, len=array.length; i<len; ++i) {
+ try {
+ l = this.parseCoords["linestring"].apply(this, [array[i]]);
+ } catch(err) {
+ throw err;
+ }
+ r = new OpenLayers.Geometry.LinearRing(l.components);
+ rings.push(r);
+ }
+ return new OpenLayers.Geometry.Polygon(rings);
+ },
+
+ /**
+ * Method: parseCoords.multipolygon
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "multipolygon": function(array) {
+ var polys = [];
+ var p = null;
+ for(var i=0, len=array.length; i<len; ++i) {
+ try {
+ p = this.parseCoords["polygon"].apply(this, [array[i]]);
+ } catch(err) {
+ throw err;
+ }
+ polys.push(p);
+ }
+ return new OpenLayers.Geometry.MultiPolygon(polys);
+ },
+
+ /**
+ * Method: parseCoords.box
+ * Convert a coordinate array from GeoJSON into an
+ * <OpenLayers.Geometry>.
+ *
+ * Parameters:
+ * array - {Object} The coordinates array from the GeoJSON fragment.
+ *
+ * Returns:
+ * {<OpenLayers.Geometry>} A geometry.
+ */
+ "box": function(array) {
+ if(array.length != 2) {
+ throw "GeoJSON box coordinates must have 2 elements";
+ }
+ return new OpenLayers.Geometry.Polygon([
+ new OpenLayers.Geometry.LinearRing([
+ new OpenLayers.Geometry.Point(array[0][0], array[0][1]),
+ new OpenLayers.Geometry.Point(array[1][0], array[0][1]),
+ new OpenLayers.Geometry.Point(array[1][0], array[1][1]),
+ new OpenLayers.Geometry.Point(array[0][0], array[1][1]),
+ new OpenLayers.Geometry.Point(array[0][0], array[0][1])
+ ])
+ ]);
}
- },
-
- /**
- * Method: setBorder
- * Always sets border to 0. Bubble Popups can not have a border.
- *
+
+ },
+
+ /**
+ * APIMethod: write
+ * Serialize a feature, geometry, array of features into a GeoJSON string.
+ *
* Parameters:
- * border - {Integer}
+ * obj - {Object} An <OpenLayers.Feature.Vector>, <OpenLayers.Geometry>,
+ * or an array of features.
+ * pretty - {Boolean} Structure the output with newlines and indentation.
+ * Default is false.
+ *
+ * Returns:
+ * {String} The GeoJSON string representation of the input geometry,
+ * features, or array of features.
*/
- setBorder:function(border) {
- this.border = 0;
- },
-
- /**
- * Method: setRicoCorners
- * Update RICO corners according to the popup's current relative postion.
- */
- setRicoCorners:function() {
-
- var corners = this.getCornersToRound(this.relativePosition);
- var options = {corners: corners,
- color: this.backgroundColor,
- bgColor: "transparent",
- blend: false};
-
- if (!this.rounded) {
- OpenLayers.Rico.Corner.round(this.div, options);
- this.rounded = true;
- } else {
- OpenLayers.Rico.Corner.reRound(this.groupDiv, options);
- //set the popup color and opacity
- this.setBackgroundColor();
- this.setOpacity();
+ write: function(obj, pretty) {
+ var geojson = {
+ "type": null
+ };
+ if(OpenLayers.Util.isArray(obj)) {
+ geojson.type = "FeatureCollection";
+ var numFeatures = obj.length;
+ geojson.features = new Array(numFeatures);
+ for(var i=0; i<numFeatures; ++i) {
+ var element = obj[i];
+ if(!element instanceof OpenLayers.Feature.Vector) {
+ var msg = "FeatureCollection only supports collections " +
+ "of features: " + element;
+ throw msg;
+ }
+ geojson.features[i] = this.extract.feature.apply(
+ this, [element]
+ );
+ }
+ } else if (obj.CLASS_NAME.indexOf("OpenLayers.Geometry") == 0) {
+ geojson = this.extract.geometry.apply(this, [obj]);
+ } else if (obj instanceof OpenLayers.Feature.Vector) {
+ geojson = this.extract.feature.apply(this, [obj]);
+ if(obj.layer && obj.layer.projection) {
+ geojson.crs = this.createCRSObject(obj);
+ }
}
+ return OpenLayers.Format.JSON.prototype.write.apply(this,
+ [geojson, pretty]);
},
- /**
- * Method: getCornersToRound
- *
+ /**
+ * Method: createCRSObject
+ * Create the CRS object for an object.
+ *
+ * Parameters:
+ * object - {<OpenLayers.Feature.Vector>}
+ *
* Returns:
- * {String} The proper corners string ("tr tl bl br") for rico to round.
+ * {Object} An object which can be assigned to the crs property
+ * of a GeoJSON object.
*/
- getCornersToRound:function() {
+ createCRSObject: function(object) {
+ var proj = object.layer.projection.toString();
+ var crs = {};
+ if (proj.match(/epsg:/i)) {
+ var code = parseInt(proj.substring(proj.indexOf(":") + 1));
+ if (code == 4326) {
+ crs = {
+ "type": "name",
+ "properties": {
+ "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
+ }
+ };
+ } else {
+ crs = {
+ "type": "name",
+ "properties": {
+ "name": "EPSG:" + code
+ }
+ };
+ }
+ }
+ return crs;
+ },
+
+ /**
+ * Property: extract
+ * Object with properties corresponding to the GeoJSON types.
+ * Property values are functions that do the actual value extraction.
+ */
+ extract: {
+ /**
+ * Method: extract.feature
+ * Return a partial GeoJSON object representing a single feature.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ *
+ * Returns:
+ * {Object} An object representing the point.
+ */
+ 'feature': function(feature) {
+ var geom = this.extract.geometry.apply(this, [feature.geometry]);
+ var json = {
+ "type": "Feature",
+ "properties": feature.attributes,
+ "geometry": geom
+ };
+ if (feature.fid != null) {
+ json.id = feature.fid;
+ }
+ return json;
+ },
+
+ /**
+ * Method: extract.geometry
+ * Return a GeoJSON object representing a single geometry.
+ *
+ * Parameters:
+ * geometry - {<OpenLayers.Geometry>}
+ *
+ * Returns:
+ * {Object} An object representing the geometry.
+ */
+ 'geometry': function(geometry) {
+ if (geometry == null) {
+ return null;
+ }
+ if (this.internalProjection && this.externalProjection) {
+ geometry = geometry.clone();
+ geometry.transform(this.internalProjection,
+ this.externalProjection);
+ }
+ var geometryType = geometry.CLASS_NAME.split('.')[2];
+ var data = this.extract[geometryType.toLowerCase()].apply(this, [geometry]);
+ var json;
+ if(geometryType == "Collection") {
+ json = {
+ "type": "GeometryCollection",
+ "geometries": data
+ };
+ } else {
+ json = {
+ "type": geometryType,
+ "coordinates": data
+ };
+ }
+
+ return json;
+ },
- var corners = ['tl', 'tr', 'bl', 'br'];
+ /**
+ * Method: extract.point
+ * Return an array of coordinates from a point.
+ *
+ * Parameters:
+ * point - {<OpenLayers.Geometry.Point>}
+ *
+ * Returns:
+ * {Array} An array of coordinates representing the point.
+ */
+ 'point': function(point) {
+ return [point.x, point.y];
+ },
- //we want to round all the corners _except_ the opposite one.
- var corner = OpenLayers.Bounds.oppositeQuadrant(this.relativePosition);
- OpenLayers.Util.removeItem(corners, corner);
+ /**
+ * Method: extract.multipoint
+ * Return an array of point coordinates from a multipoint.
+ *
+ * Parameters:
+ * multipoint - {<OpenLayers.Geometry.MultiPoint>}
+ *
+ * Returns:
+ * {Array} An array of point coordinate arrays representing
+ * the multipoint.
+ */
+ 'multipoint': function(multipoint) {
+ var array = [];
+ for(var i=0, len=multipoint.components.length; i<len; ++i) {
+ array.push(this.extract.point.apply(this, [multipoint.components[i]]));
+ }
+ return array;
+ },
+
+ /**
+ * Method: extract.linestring
+ * Return an array of coordinate arrays from a linestring.
+ *
+ * Parameters:
+ * linestring - {<OpenLayers.Geometry.LineString>}
+ *
+ * Returns:
+ * {Array} An array of coordinate arrays representing
+ * the linestring.
+ */
+ 'linestring': function(linestring) {
+ var array = [];
+ for(var i=0, len=linestring.components.length; i<len; ++i) {
+ array.push(this.extract.point.apply(this, [linestring.components[i]]));
+ }
+ return array;
+ },
- return corners.join(" ");
- },
+ /**
+ * Method: extract.multilinestring
+ * Return an array of linestring arrays from a linestring.
+ *
+ * Parameters:
+ * multilinestring - {<OpenLayers.Geometry.MultiLineString>}
+ *
+ * Returns:
+ * {Array} An array of linestring arrays representing
+ * the multilinestring.
+ */
+ 'multilinestring': function(multilinestring) {
+ var array = [];
+ for(var i=0, len=multilinestring.components.length; i<len; ++i) {
+ array.push(this.extract.linestring.apply(this, [multilinestring.components[i]]));
+ }
+ return array;
+ },
+
+ /**
+ * Method: extract.polygon
+ * Return an array of linear ring arrays from a polygon.
+ *
+ * Parameters:
+ * polygon - {<OpenLayers.Geometry.Polygon>}
+ *
+ * Returns:
+ * {Array} An array of linear ring arrays representing the polygon.
+ */
+ 'polygon': function(polygon) {
+ var array = [];
+ for(var i=0, len=polygon.components.length; i<len; ++i) {
+ array.push(this.extract.linestring.apply(this, [polygon.components[i]]));
+ }
+ return array;
+ },
- CLASS_NAME: "OpenLayers.Popup.AnchoredBubble"
-});
+ /**
+ * Method: extract.multipolygon
+ * Return an array of polygon arrays from a multipolygon.
+ *
+ * Parameters:
+ * multipolygon - {<OpenLayers.Geometry.MultiPolygon>}
+ *
+ * Returns:
+ * {Array} An array of polygon arrays representing
+ * the multipolygon
+ */
+ 'multipolygon': function(multipolygon) {
+ var array = [];
+ for(var i=0, len=multipolygon.components.length; i<len; ++i) {
+ array.push(this.extract.polygon.apply(this, [multipolygon.components[i]]));
+ }
+ return array;
+ },
+
+ /**
+ * Method: extract.collection
+ * Return an array of geometries from a geometry collection.
+ *
+ * Parameters:
+ * collection - {<OpenLayers.Geometry.Collection>}
+ *
+ * Returns:
+ * {Array} An array of geometry objects representing the geometry
+ * collection.
+ */
+ 'collection': function(collection) {
+ var len = collection.components.length;
+ var array = new Array(len);
+ for(var i=0; i<len; ++i) {
+ array[i] = this.extract.geometry.apply(
+ this, [collection.components[i]]
+ );
+ }
+ return array;
+ }
+
-/**
- * Constant: CORNER_SIZE
- * {Integer} 5. Border space for the RICO corners.
- */
-OpenLayers.Popup.AnchoredBubble.CORNER_SIZE = 5;
+ },
+ CLASS_NAME: "OpenLayers.Format.GeoJSON"
+
+});
/* ======================================================================
- OpenLayers/Strategy/BBOX.js
+ OpenLayers/Protocol/WFS/v1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Strategy.js
- * @requires OpenLayers/Filter/Spatial.js
+ * @requires OpenLayers/Protocol/WFS.js
*/
/**
- * Class: OpenLayers.Strategy.BBOX
- * A simple strategy that reads new features when the viewport invalidates
- * some bounds.
+ * Class: OpenLayers.Protocol.WFS.v1
+ * Abstract class for for v1.0.0 and v1.1.0 protocol.
*
* Inherits from:
- * - <OpenLayers.Strategy>
+ * - <OpenLayers.Protocol>
*/
-OpenLayers.Strategy.BBOX = OpenLayers.Class(OpenLayers.Strategy, {
+OpenLayers.Protocol.WFS.v1 = OpenLayers.Class(OpenLayers.Protocol, {
/**
- * Property: bounds
- * {<OpenLayers.Bounds>} The current data bounds (in the same projection
- * as the layer - not always the same projection as the map).
+ * Property: version
+ * {String} WFS version number.
*/
- bounds: null,
+ version: null,
- /**
- * Property: resolution
- * {Float} The current data resolution.
- */
- resolution: null,
-
/**
- * APIProperty: ratio
- * {Float} The ratio of the data bounds to the viewport bounds (in each
- * dimension). Default is 2.
+ * Property: srsName
+ * {String} Name of spatial reference system. Default is "EPSG:4326".
*/
- ratio: 2,
+ srsName: "EPSG:4326",
+
+ /**
+ * Property: featureType
+ * {String} Local feature typeName.
+ */
+ featureType: null,
+
+ /**
+ * Property: featureNS
+ * {String} Feature namespace.
+ */
+ featureNS: null,
+
+ /**
+ * Property: geometryName
+ * {String} Name of the geometry attribute for features. Default is
+ * "the_geom" for WFS <version> 1.0, and null for higher versions.
+ */
+ geometryName: "the_geom",
+ /**
+ * Property: maxFeatures
+ * {Integer} Optional maximum number of features to retrieve.
+ */
+
+ /**
+ * Property: schema
+ * {String} Optional schema location that will be included in the
+ * schemaLocation attribute value. Note that the feature type schema
+ * is required for a strict XML validator (on transactions with an
+ * insert for example), but is *not* required by the WFS specification
+ * (since the server is supposed to know about feature type schemas).
+ */
+ schema: null,
+
+ /**
+ * Property: featurePrefix
+ * {String} Namespace alias for feature type. Default is "feature".
+ */
+ featurePrefix: "feature",
+
+ /**
+ * Property: formatOptions
+ * {Object} Optional options for the format. If a format is not provided,
+ * this property can be used to extend the default format options.
+ */
+ formatOptions: null,
+
/**
- * Property: resFactor
- * {Float} Optional factor used to determine when previously requested
- * features are invalid. If set, the resFactor will be compared to the
- * resolution of the previous request to the current map resolution.
- * If resFactor > (old / new) and 1/resFactor < (old / new). If you
- * set a resFactor of 1, data will be requested every time the
- * resolution changes. If you set a resFactor of 3, data will be
- * requested if the old resolution is 3 times the new, or if the new is
- * 3 times the old. If the old bounds do not contain the new bounds
- * new data will always be requested (with or without considering
- * resFactor).
+ * Property: readFormat
+ * {<OpenLayers.Format>} For WFS requests it is possible to get a
+ * different output format than GML. In that case, we cannot parse
+ * the response with the default format (WFST) and we need a different
+ * format for reading.
*/
- resFactor: null,
+ readFormat: null,
/**
- * Property: response
- * {<OpenLayers.Protocol.Response>} The protocol response object returned
- * by the layer protocol.
+ * Property: readOptions
+ * {Object} Optional object to pass to format's read.
*/
- response: null,
-
+ readOptions: null,
+
/**
- * Constructor: OpenLayers.Strategy.BBOX
- * Create a new BBOX strategy.
+ * Constructor: OpenLayers.Protocol.WFS
+ * A class for giving layers WFS protocol.
*
* Parameters:
* options - {Object} Optional object whose properties will be set on the
* instance.
+ *
+ * Valid options properties:
+ * url - {String} URL to send requests to (required).
+ * featureType - {String} Local (without prefix) feature typeName (required).
+ * featureNS - {String} Feature namespace (required, but can be autodetected
+ * during the first query if GML is used as readFormat and
+ * featurePrefix is provided and matches the prefix used by the server
+ * for this featureType).
+ * featurePrefix - {String} Feature namespace alias (optional - only used
+ * for writing if featureNS is provided). Default is 'feature'.
+ * geometryName - {String} Name of geometry attribute. The default is
+ * 'the_geom' for WFS <version> 1.0, and null for higher versions. If
+ * null, it will be set to the name of the first geometry found in the
+ * first read operation.
+ * multi - {Boolean} If set to true, geometries will be casted to Multi
+ * geometries before they are written in a transaction. No casting will
+ * be done when reading features.
*/
+ initialize: function(options) {
+ OpenLayers.Protocol.prototype.initialize.apply(this, [options]);
+ if(!options.format) {
+ this.format = OpenLayers.Format.WFST(OpenLayers.Util.extend({
+ version: this.version,
+ featureType: this.featureType,
+ featureNS: this.featureNS,
+ featurePrefix: this.featurePrefix,
+ geometryName: this.geometryName,
+ srsName: this.srsName,
+ schema: this.schema
+ }, this.formatOptions));
+ }
+ if (!options.geometryName && parseFloat(this.format.version) > 1.0) {
+ this.setGeometryName(null);
+ }
+ },
/**
- * Method: activate
- * Set up strategy with regard to reading new batches of remote data.
- *
- * Returns:
- * {Boolean} The strategy was successfully activated.
+ * APIMethod: destroy
+ * Clean up the protocol.
*/
- activate: function() {
- var activated = OpenLayers.Strategy.prototype.activate.call(this);
- if(activated) {
- this.layer.events.on({
- "moveend": this.update,
- "refresh": this.update,
- "visibilitychanged": this.update,
- scope: this
- });
- this.update();
+ destroy: function() {
+ if(this.options && !this.options.format) {
+ this.format.destroy();
}
- return activated;
+ this.format = null;
+ OpenLayers.Protocol.prototype.destroy.apply(this);
},
-
+
/**
- * Method: deactivate
- * Tear down strategy with regard to reading new batches of remote data.
- *
- * Returns:
- * {Boolean} The strategy was successfully deactivated.
+ * APIMethod: read
+ * Construct a request for reading new features. Since WFS splits the
+ * basic CRUD operations into GetFeature requests (for read) and
+ * Transactions (for all others), this method does not make use of the
+ * format's read method (that is only about reading transaction
+ * responses).
+ *
+ * Parameters:
+ * options - {Object} Options for the read operation, in addition to the
+ * options set on the instance (options set here will take precedence).
+ *
+ * To use a configured protocol to get e.g. a WFS hit count, applications
+ * could do the following:
+ *
+ * (code)
+ * protocol.read({
+ * readOptions: {output: "object"},
+ * resultType: "hits",
+ * maxFeatures: null,
+ * callback: function(resp) {
+ * // process resp.numberOfFeatures here
+ * }
+ * });
+ * (end)
+ *
+ * To use a configured protocol to use WFS paging (if supported by the
+ * server), applications could do the following:
+ *
+ * (code)
+ * protocol.read({
+ * startIndex: 0,
+ * count: 50
+ * });
+ * (end)
+ *
+ * To limit the attributes returned by the GetFeature request, applications
+ * can use the propertyNames option to specify the properties to include in
+ * the response:
+ *
+ * (code)
+ * protocol.read({
+ * propertyNames: ["DURATION", "INTENSITY"]
+ * });
+ * (end)
*/
- deactivate: function() {
- var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
- if(deactivated) {
- this.layer.events.un({
- "moveend": this.update,
- "refresh": this.update,
- "visibilitychanged": this.update,
- scope: this
- });
- }
- return deactivated;
+ read: function(options) {
+ OpenLayers.Protocol.prototype.read.apply(this, arguments);
+ options = OpenLayers.Util.extend({}, options);
+ OpenLayers.Util.applyDefaults(options, this.options || {});
+ var response = new OpenLayers.Protocol.Response({requestType: "read"});
+
+ var data = OpenLayers.Format.XML.prototype.write.apply(
+ this.format, [this.format.writeNode("wfs:GetFeature", options)]
+ );
+
+ response.priv = OpenLayers.Request.POST({
+ url: options.url,
+ callback: this.createCallback(this.handleRead, response, options),
+ params: options.params,
+ headers: options.headers,
+ data: data
+ });
+
+ return response;
},
/**
- * Method: update
- * Callback function called on "moveend" or "refresh" layer events.
+ * APIMethod: setFeatureType
+ * Change the feature type on the fly.
*
* Parameters:
- * options - {Object} Optional object whose properties will determine
- * the behaviour of this Strategy
+ * featureType - {String} Local (without prefix) feature typeName.
+ */
+ setFeatureType: function(featureType) {
+ this.featureType = featureType;
+ this.format.featureType = featureType;
+ },
+
+ /**
+ * APIMethod: setGeometryName
+ * Sets the geometryName option after instantiation.
*
- * Valid options include:
- * force - {Boolean} if true, new data must be unconditionally read.
- * noAbort - {Boolean} if true, do not abort previous requests.
+ * Parameters:
+ * geometryName - {String} Name of geometry attribute.
*/
- update: function(options) {
- var mapBounds = this.getMapBounds();
- if (mapBounds !== null && ((options && options.force) ||
- (this.layer.visibility && this.layer.calculateInRange() && this.invalidBounds(mapBounds)))) {
- this.calculateBounds(mapBounds);
- this.resolution = this.layer.map.getResolution();
- this.triggerRead(options);
- }
+ setGeometryName: function(geometryName) {
+ this.geometryName = geometryName;
+ this.format.geometryName = geometryName;
},
/**
- * Method: getMapBounds
- * Get the map bounds expressed in the same projection as this layer.
+ * Method: handleRead
+ * Deal with response from the read request.
*
- * Returns:
- * {<OpenLayers.Bounds>} Map bounds in the projection of the layer.
+ * Parameters:
+ * response - {<OpenLayers.Protocol.Response>} The response object to pass
+ * to the user callback.
+ * options - {Object} The user options passed to the read call.
*/
- getMapBounds: function() {
- if (this.layer.map === null) {
- return null;
+ handleRead: function(response, options) {
+ options = OpenLayers.Util.extend({}, options);
+ OpenLayers.Util.applyDefaults(options, this.options);
+
+ if(options.callback) {
+ var request = response.priv;
+ if(request.status >= 200 && request.status < 300) {
+ // success
+ var result = this.parseResponse(request, options.readOptions);
+ if (result && result.success !== false) {
+ if (options.readOptions && options.readOptions.output == "object") {
+ OpenLayers.Util.extend(response, result);
+ } else {
+ response.features = result;
+ }
+ response.code = OpenLayers.Protocol.Response.SUCCESS;
+ } else {
+ // failure (service exception)
+ response.code = OpenLayers.Protocol.Response.FAILURE;
+ response.error = result;
+ }
+ } else {
+ // failure
+ response.code = OpenLayers.Protocol.Response.FAILURE;
+ }
+ options.callback.call(options.scope, response);
}
- var bounds = this.layer.map.getExtent();
- if(bounds && !this.layer.projection.equals(
- this.layer.map.getProjectionObject())) {
- bounds = bounds.clone().transform(
- this.layer.map.getProjectionObject(), this.layer.projection
- );
- }
- return bounds;
},
/**
- * Method: invalidBounds
- * Determine whether the previously requested set of features is invalid.
- * This occurs when the new map bounds do not contain the previously
- * requested bounds. In addition, if <resFactor> is set, it will be
- * considered.
+ * Method: parseResponse
+ * Read HTTP response body and return features
*
* Parameters:
- * mapBounds - {<OpenLayers.Bounds>} the current map extent, will be
- * retrieved from the map object if not provided
+ * request - {XMLHttpRequest} The request object
+ * options - {Object} Optional object to pass to format's read
*
* Returns:
- * {Boolean}
+ * {Object} or {Array({<OpenLayers.Feature.Vector>})} or
+ * {<OpenLayers.Feature.Vector>}
+ * An object with a features property, an array of features or a single
+ * feature.
*/
- invalidBounds: function(mapBounds) {
- if(!mapBounds) {
- mapBounds = this.getMapBounds();
+ parseResponse: function(request, options) {
+ var doc = request.responseXML;
+ if(!doc || !doc.documentElement) {
+ doc = request.responseText;
}
- var invalid = !this.bounds || !this.bounds.containsBounds(mapBounds);
- if(!invalid && this.resFactor) {
- var ratio = this.resolution / this.layer.map.getResolution();
- invalid = (ratio >= this.resFactor || ratio <= (1 / this.resFactor));
+ if(!doc || doc.length <= 0) {
+ return null;
}
- return invalid;
+ var result = (this.readFormat !== null) ? this.readFormat.read(doc) :
+ this.format.read(doc, options);
+ if (!this.featureNS) {
+ var format = this.readFormat || this.format;
+ this.featureNS = format.featureNS;
+ // no need to auto-configure again on subsequent reads
+ format.autoConfig = false;
+ if (!this.geometryName) {
+ this.setGeometryName(format.geometryName);
+ }
+ }
+ return result;
},
-
+
/**
- * Method: calculateBounds
+ * Method: commit
+ * Given a list of feature, assemble a batch request for update, create,
+ * and delete transactions. A commit call on the prototype amounts
+ * to writing a WFS transaction - so the write method on the format
+ * is used.
*
* Parameters:
- * mapBounds - {<OpenLayers.Bounds>} the current map extent, will be
- * retrieved from the map object if not provided
+ * features - {Array(<OpenLayers.Feature.Vector>)}
+ * options - {Object}
+ *
+ * Valid options properties:
+ * nativeElements - {Array({Object})} Array of objects with information for writing
+ * out <Native> elements, these objects have vendorId, safeToIgnore and
+ * value properties. The <Native> element is intended to allow access to
+ * vendor specific capabilities of any particular web feature server or
+ * datastore.
+ *
+ * Returns:
+ * {<OpenLayers.Protocol.Response>} A response object with a features
+ * property containing any insertIds and a priv property referencing
+ * the XMLHttpRequest object.
*/
- calculateBounds: function(mapBounds) {
- if(!mapBounds) {
- mapBounds = this.getMapBounds();
- }
- var center = mapBounds.getCenterLonLat();
- var dataWidth = mapBounds.getWidth() * this.ratio;
- var dataHeight = mapBounds.getHeight() * this.ratio;
- this.bounds = new OpenLayers.Bounds(
- center.lon - (dataWidth / 2),
- center.lat - (dataHeight / 2),
- center.lon + (dataWidth / 2),
- center.lat + (dataHeight / 2)
- );
+ commit: function(features, options) {
+
+ options = OpenLayers.Util.extend({}, options);
+ OpenLayers.Util.applyDefaults(options, this.options);
+
+ var response = new OpenLayers.Protocol.Response({
+ requestType: "commit",
+ reqFeatures: features
+ });
+ response.priv = OpenLayers.Request.POST({
+ url: options.url,
+ headers: options.headers,
+ data: this.format.write(features, options),
+ callback: this.createCallback(this.handleCommit, response, options)
+ });
+
+ return response;
},
/**
- * Method: triggerRead
- *
+ * Method: handleCommit
+ * Called when the commit request returns.
+ *
* Parameters:
- * options - {Object} Additional options for the protocol's read method
- * (optional)
- *
- * Returns:
- * {<OpenLayers.Protocol.Response>} The protocol response object
- * returned by the layer protocol.
+ * response - {<OpenLayers.Protocol.Response>} The response object to pass
+ * to the user callback.
+ * options - {Object} The user options passed to the commit call.
*/
- triggerRead: function(options) {
- if (this.response && !(options && options.noAbort === true)) {
- this.layer.protocol.abort(this.response);
- this.layer.events.triggerEvent("loadend");
+ handleCommit: function(response, options) {
+ if(options.callback) {
+ var request = response.priv;
+
+ // ensure that we have an xml doc
+ var data = request.responseXML;
+ if(!data || !data.documentElement) {
+ data = request.responseText;
+ }
+
+ var obj = this.format.read(data) || {};
+
+ response.insertIds = obj.insertIds || [];
+ if (obj.success) {
+ response.code = OpenLayers.Protocol.Response.SUCCESS;
+ } else {
+ response.code = OpenLayers.Protocol.Response.FAILURE;
+ response.error = obj;
+ }
+ options.callback.call(options.scope, response);
}
- var evt = {filter: this.createFilter()};
- this.layer.events.triggerEvent("loadstart", evt);
- this.response = this.layer.protocol.read(
- OpenLayers.Util.applyDefaults({
- filter: evt.filter,
- callback: this.merge,
- scope: this
- }, options));
},
-
+
/**
- * Method: createFilter
- * Creates a spatial BBOX filter. If the layer that this strategy belongs
- * to has a filter property, this filter will be combined with the BBOX
- * filter.
+ * Method: filterDelete
+ * Send a request that deletes all features by their filter.
*
- * Returns
- * {<OpenLayers.Filter>} The filter object.
+ * Parameters:
+ * filter - {<OpenLayers.Filter>} filter
*/
- createFilter: function() {
- var filter = new OpenLayers.Filter.Spatial({
- type: OpenLayers.Filter.Spatial.BBOX,
- value: this.bounds,
- projection: this.layer.projection
+ filterDelete: function(filter, options) {
+ options = OpenLayers.Util.extend({}, options);
+ OpenLayers.Util.applyDefaults(options, this.options);
+
+ var response = new OpenLayers.Protocol.Response({
+ requestType: "commit"
+ });
+
+ var root = this.format.createElementNSPlus("wfs:Transaction", {
+ attributes: {
+ service: "WFS",
+ version: this.version
+ }
});
- if (this.layer.filter) {
- filter = new OpenLayers.Filter.Logical({
- type: OpenLayers.Filter.Logical.AND,
- filters: [this.layer.filter, filter]
- });
+
+ var deleteNode = this.format.createElementNSPlus("wfs:Delete", {
+ attributes: {
+ typeName: (options.featureNS ? this.featurePrefix + ":" : "") +
+ options.featureType
+ }
+ });
+
+ if(options.featureNS) {
+ deleteNode.setAttribute("xmlns:" + this.featurePrefix, options.featureNS);
}
- return filter;
+ var filterNode = this.format.writeNode("ogc:Filter", filter);
+
+ deleteNode.appendChild(filterNode);
+
+ root.appendChild(deleteNode);
+
+ var data = OpenLayers.Format.XML.prototype.write.apply(
+ this.format, [root]
+ );
+
+ return OpenLayers.Request.POST({
+ url: this.url,
+ callback : options.callback || function(){},
+ data: data
+ });
+
},
-
+
/**
- * Method: merge
- * Given a list of features, determine which ones to add to the layer.
- * If the layer projection differs from the map projection, features
- * will be transformed from the layer projection to the map projection.
+ * Method: abort
+ * Abort an ongoing request, the response object passed to
+ * this method must come from this protocol (as a result
+ * of a read, or commit operation).
*
* Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object passed
- * by the protocol.
+ * response - {<OpenLayers.Protocol.Response>}
*/
- merge: function(resp) {
- this.layer.destroyFeatures();
- if (resp.success()) {
- var features = resp.features;
- if(features && features.length > 0) {
- var remote = this.layer.projection;
- var local = this.layer.map.getProjectionObject();
- if(!local.equals(remote)) {
- var geom;
- for(var i=0, len=features.length; i<len; ++i) {
- geom = features[i].geometry;
- if(geom) {
- geom.transform(remote, local);
- }
- }
- }
- this.layer.addFeatures(features);
- }
- } else {
- this.bounds = null;
+ abort: function(response) {
+ if (response) {
+ response.priv.abort();
}
- this.response = null;
- this.layer.events.triggerEvent("loadend", {response: resp});
},
-
- CLASS_NAME: "OpenLayers.Strategy.BBOX"
+
+ CLASS_NAME: "OpenLayers.Protocol.WFS.v1"
});
/* ======================================================================
OpenLayers/Format/SLD/v1_0_0_GeoServer.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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.js
* @requires OpenLayers/Format/SLD/v1_0_0.js
*/
/**
* Class: OpenLayers.Format.SLD/v1_0_0_GeoServer
@@ -63776,11 +65182,11 @@
readers: OpenLayers.Util.applyDefaults({
"sld": OpenLayers.Util.applyDefaults({
"Priority": function(node, obj) {
var value = this.readers.ogc._expression.call(this, node);
if (value) {
- obj.priority = value;
+ obj.priority = OpenLayers.String.trim(value);
}
},
"VendorOption": function(node, obj) {
if (!obj.vendorOptions) {
obj.vendorOptions = {};
@@ -63874,11 +65280,11 @@
});
/* ======================================================================
OpenLayers/Protocol/CSW.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -63908,11 +65314,11 @@
};
/* ======================================================================
OpenLayers/Protocol/WFS/v1_1_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -63980,11 +65386,11 @@
});
/* ======================================================================
OpenLayers/Format/WMTSCapabilities.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -64054,10 +65460,13 @@
* layer - {String} The layer identifier.
*
* Optional config properties:
* matrixSet - {String} The matrix set identifier, required if there is
* more than one matrix set in the layer capabilities.
+ * projection - {String} The desired CRS when no matrixSet is specified.
+ * eg: "EPSG:3857". If the desired projection is not available,
+ * an error is thrown.
* style - {String} The name of the style
* format - {String} Image format for the layer. Default is the first
* format returned in the GetCapabilities response.
* param - {Object} The dimensions values eg: {"Year": "2012"}
*
@@ -64096,10 +65505,23 @@
// find the matrixSet definition
var matrixSet;
if (config.matrixSet) {
matrixSet = contents.tileMatrixSets[config.matrixSet];
+ } else if (config.projection) {
+ for (var i=0,l=layerDef.tileMatrixSetLinks.length;i<l;i++) {
+ if (contents.tileMatrixSets[
+ layerDef.tileMatrixSetLinks[i].tileMatrixSet
+ ].supportedCRS.replace(
+ /urn:ogc:def:crs:(\w+):(.*:)?(\w+)$/, "$1:$3"
+ ) === config.projection) {
+
+ matrixSet = contents.tileMatrixSets[
+ layerDef.tileMatrixSetLinks[i].tileMatrixSet];
+ break;
+ }
+ }
} else if (layerDef.tileMatrixSetLinks.length >= 1) {
matrixSet = contents.tileMatrixSets[
layerDef.tileMatrixSetLinks[0].tileMatrixSet];
}
if (!matrixSet) {
@@ -64122,11 +65544,10 @@
var http = capabilities.operationsMetadata.GetTile.dcp.http;
// Get first get method
if (http.get[0].constraints) {
var constraints = http.get[0].constraints;
var allowedValues = constraints.GetEncoding.allowedValues;
-
// The OGC documentation is not clear if we should use
// REST or RESTful, ArcGis use RESTful,
// and OpenLayers use REST.
if (!allowedValues.KVP &&
(allowedValues.REST || allowedValues.RESTful)) {
@@ -64149,20 +65570,52 @@
}
var projection = config.projection || matrixSet.supportedCRS.replace(
/urn:ogc:def:crs:(\w+):(.*:)?(\w+)$/, "$1:$3");
var units = config.units ||
- (projection === "EPSG:4326" ? "degrees" : "m");
+ (projection === ("EPSG:4326" || "OGC:CRS84") ? "degrees" : "m");
- var resolutions = [];
- for (var mid in matrixSet.matrixIds) {
- if (matrixSet.matrixIds.hasOwnProperty(mid)) {
- resolutions.push(
- matrixSet.matrixIds[mid].scaleDenominator * 0.28E-3 /
- OpenLayers.METERS_PER_INCH /
- OpenLayers.INCHES_PER_UNIT[units]);
+ // compute server-supported resolutions array
+ var resolutions = [], minScaleDenominator, maxScaleDenominator,
+ reducedMatrixIds = [], tileMatrixSetLink,
+ tileMatrixSetLinks = layerDef.tileMatrixSetLinks;
+ var buildResolutionsArray = function(scaleDenominator) {
+ resolutions.push(
+ scaleDenominator * 0.28E-3 / OpenLayers.METERS_PER_INCH /
+ OpenLayers.INCHES_PER_UNIT[units]
+ );
+ if (!minScaleDenominator || minScaleDenominator > scaleDenominator) {
+ minScaleDenominator = scaleDenominator;
}
+ if (!maxScaleDenominator || maxScaleDenominator < scaleDenominator) {
+ maxScaleDenominator = scaleDenominator;
+ }
+ };
+ for (var j=0, l=tileMatrixSetLinks.length; j<l; j++) {
+ tileMatrixSetLink = tileMatrixSetLinks[j];
+ if (tileMatrixSetLink.tileMatrixSet === matrixSet.identifier) {
+ if (tileMatrixSetLink.tileMatrixSetLimits) {
+ // reformat matrixSet.matrixIds so that identifiers become keys
+ var tmpMatrixIds = {}, mid;
+ for (var k=0, ll=matrixSet.matrixIds.length; k<ll; k++) {
+ tmpMatrixIds[matrixSet.matrixIds[k].identifier] = matrixSet.matrixIds[k];
+ }
+ // compute resolutions array + scale limits
+ for (var k=0, ll=tileMatrixSetLink.tileMatrixSetLimits.length; k<ll; k++) {
+ mid = tmpMatrixIds[tileMatrixSetLink.tileMatrixSetLimits[k].tileMatrix];
+ reducedMatrixIds.push(mid);
+ buildResolutionsArray(mid.scaleDenominator);
+ }
+ } else {
+ // if there are no limits in the tileMatrixSetLink,
+ // use the resolutions from the full tile matrix set
+ for (var k=0, ll=matrixSet.matrixIds.length; k<ll; k++) {
+ buildResolutionsArray(matrixSet.matrixIds[k].scaleDenominator);
+ };
+ }
+ break;
+ }
}
var url;
if (requestEncoding === "REST" && layerDef.resourceUrls) {
url = [];
@@ -64172,12 +65625,11 @@
resourceUrl = layerDef.resourceUrls[t];
if (resourceUrl.format === format && resourceUrl.resourceType === "tile") {
url.push(resourceUrl.template);
}
}
- }
- else {
+ } else {
var httpGet = capabilities.operationsMetadata.GetTile.dcp.http.get;
url = [];
var constraint;
for (var i = 0, ii = httpGet.length; i < ii; i++) {
constraint = httpGet[i].constraints;
@@ -64185,40 +65637,44 @@
GetEncoding.allowedValues[requestEncoding])) {
url.push(httpGet[i].url);
}
}
}
-
- return new OpenLayers.Layer.WMTS(
- OpenLayers.Util.applyDefaults(config, {
- url: url,
- requestEncoding: requestEncoding,
- name: layerDef.title,
- style: style.identifier,
- format: format,
- matrixIds: matrixSet.matrixIds,
- matrixSet: matrixSet.identifier,
- projection: projection,
- units: units,
- resolutions: config.isBaseLayer === false ? undefined :
- resolutions,
- serverResolutions: resolutions,
- tileFullExtent: matrixSet.bounds,
- dimensions: dimensions,
- params: params
- })
- );
+
+ resolutions.sort(function(a,b){
+ return b-a;
+ });
+ var options = OpenLayers.Util.applyDefaults(config, {
+ url: url,
+ requestEncoding: requestEncoding,
+ name: layerDef.title,
+ style: style && style.identifier || "",
+ format: format,
+ matrixIds: reducedMatrixIds.length ?
+ reducedMatrixIds : matrixSet.matrixIds,
+ matrixSet: matrixSet.identifier,
+ projection: projection,
+ units: units,
+ tileFullExtent: matrixSet.bounds,
+ dimensions: dimensions,
+ params: params,
+ resolutions: config.isBaseLayer === false ? undefined :
+ resolutions,
+ serverResolutions: resolutions,
+ minScale: 1/Math.ceil(maxScaleDenominator),
+ maxScale: 1/Math.floor(minScaleDenominator)
+ });
+ return new OpenLayers.Layer.WMTS(options);
},
CLASS_NAME: "OpenLayers.Format.WMTSCapabilities"
-
});
/* ======================================================================
OpenLayers/Layer/Google/v3.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -64229,11 +65685,17 @@
/**
* Constant: OpenLayers.Layer.Google.v3
*
* Mixin providing functionality specific to the Google Maps API v3.
*
- * To use this layer, you must include the GMaps v3 API in your html.
+ * To use this layer, you must include the GMaps v3 API in your html. To match
+ * Google's zoom animation better with OpenLayers animated zooming, configure
+ * your map with a zoomDuration of 10:
+ *
+ * (code)
+ * new OpenLayers.Map('map', {zoomDuration: 10});
+ * (end)
*
* Note that this layer configures the google.maps.map object with the
* "disableDefaultUI" option set to true. Using UI controls that the Google
* Maps API provides is not supported by the OpenLayers API.
*/
@@ -64269,14 +65731,13 @@
*/
animationEnabled: true,
/**
* Method: loadMapObject
- * Load the GMap and register appropriate event listeners. If we can't
- * load GMap2, then display a warning message.
+ * Load the GMap and register appropriate event listeners.
*/
- loadMapObject:function() {
+ loadMapObject: function() {
if (!this.type) {
this.type = google.maps.MapTypeId.ROADMAP;
}
var mapObject;
var cache = OpenLayers.Layer.Google.cache[this.map.id];
@@ -64357,29 +65818,27 @@
}
}
var container = this.mapObject.getDiv();
if (visible === true) {
if (container.parentNode !== map.div) {
- map.div.appendChild(container);
if (!cache.rendered) {
+ var me = this;
google.maps.event.addListenerOnce(this.mapObject, 'tilesloaded', function() {
- cache.googleControl.appendChild(map.viewPortDiv);
cache.rendered = true;
+ me.setGMapVisibility(me.getVisibility());
+ me.moveTo(me.map.getCenter());
});
} else {
+ map.div.appendChild(container);
cache.googleControl.appendChild(map.viewPortDiv);
+ google.maps.event.trigger(this.mapObject, 'resize');
}
- google.maps.event.trigger(this.mapObject, 'resize');
}
this.mapObject.setMapTypeId(type);
- cache.displayed = this.id;
- } else {
- if (cache.googleControl.hasChildNodes()) {
- map.div.appendChild(map.viewPortDiv);
- map.div.removeChild(container);
- }
- delete cache.displayed;
+ } else if (cache.googleControl.hasChildNodes()) {
+ map.div.appendChild(map.viewPortDiv);
+ map.div.removeChild(container);
}
}
},
/**
@@ -64572,11 +66031,11 @@
};
/* ======================================================================
OpenLayers/Format/WPSDescribeProcess.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -64761,18 +66220,24 @@
});
/* ======================================================================
OpenLayers/Format/WKT.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Format.js
* @requires OpenLayers/Feature/Vector.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Geometry/MultiPoint.js
+ * @requires OpenLayers/Geometry/LineString.js
+ * @requires OpenLayers/Geometry/MultiLineString.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Geometry/MultiPolygon.js
*/
/**
* Class: OpenLayers.Format.WKT
* Class for reading and writing Well-Known Text. Create a new instance
@@ -65151,16 +66616,16 @@
});
/* ======================================================================
OpenLayers/WPSProcess.js
====================================================================== */
-/**
- * Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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.
- *
+ * full text of the license. */
+
+/**
* @requires OpenLayers/SingleFile.js
*/
/**
* @requires OpenLayers/Geometry.js
@@ -65656,16 +67121,16 @@
});
/* ======================================================================
OpenLayers/WPSClient.js
====================================================================== */
-/**
- * Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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.
- *
+ * full text of the license. */
+
+/**
* @requires OpenLayers/SingleFile.js
*/
/**
* @requires OpenLayers/Events.js
@@ -65880,475 +67345,263 @@
CLASS_NAME: 'OpenLayers.WPSClient'
});
/* ======================================================================
- OpenLayers/Format/CSWGetRecords/v2_0_2.js
+ OpenLayers/Format/Filter/v2_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Format/XML.js
- * @requires OpenLayers/Format/CSWGetRecords.js
- * @requires OpenLayers/Format/Filter/v1_0_0.js
- * @requires OpenLayers/Format/Filter/v1_1_0.js
- * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ * @requires OpenLayers/Format/Filter/v2.js
+ * @requires OpenLayers/Format/GML/v3.js
*/
/**
- * Class: OpenLayers.Format.CSWGetRecords.v2_0_2
- * A format for creating CSWGetRecords v2.0.2 transactions.
- * Create a new instance with the
- * <OpenLayers.Format.CSWGetRecords.v2_0_2> constructor.
+ * Class: OpenLayers.Format.Filter.v2_0_0
+ * Writes fes:Filter version 2.0.0.
*
- * Inherits from:
- * - <OpenLayers.Format.XML>
+ * Differences from the v1.0.0 parser:
+ * - uses GML v3 instead of GML v2
+ * - reads matchCase attribute on fes:PropertyIsEqual and
+ * fes:PropertyIsNotEqual elements.
+ * - writes matchCase attribute from comparison filters of type EQUAL_TO,
+ * NOT_EQUAL_TO and LIKE.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.GML.v3>
+ * - <OpenLayers.Format.Filter.v1>
*/
-OpenLayers.Format.CSWGetRecords.v2_0_2 = OpenLayers.Class(OpenLayers.Format.XML, {
+OpenLayers.Format.Filter.v2_0_0 = OpenLayers.Class(
+ OpenLayers.Format.GML.v3, OpenLayers.Format.Filter.v2, {
/**
- * Property: namespaces
- * {Object} Mapping of namespace aliases to namespace URIs.
+ * Constant: VERSION
+ * {String} 2.0.0
*/
- namespaces: {
- csw: "http://www.opengis.net/cat/csw/2.0.2",
- dc: "http://purl.org/dc/elements/1.1/",
- dct: "http://purl.org/dc/terms/",
- gmd: "http://www.isotc211.org/2005/gmd",
- geonet: "http://www.fao.org/geonetwork",
- ogc: "http://www.opengis.net/ogc",
- ows: "http://www.opengis.net/ows",
- xlink: "http://www.w3.org/1999/xlink",
- xsi: "http://www.w3.org/2001/XMLSchema-instance"
- },
+ VERSION: "2.0.0",
/**
- * Property: defaultPrefix
- * {String} The default prefix (used by Format.XML).
- */
- defaultPrefix: "csw",
-
- /**
- * Property: version
- * {String} CSW version number.
- */
- version: "2.0.2",
-
- /**
* Property: schemaLocation
- * {String} http://www.opengis.net/cat/csw/2.0.2
- * http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd
+ * {String} http://schemas.opengis.net/filter/2.0/filterAll.xsd
*/
- schemaLocation: "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
+ schemaLocation: "http://schemas.opengis.net/filter/2.0/filterAll.xsd",
/**
- * APIProperty: requestId
- * {String} Value of the requestId attribute of the GetRecords element.
- */
- requestId: null,
-
- /**
- * APIProperty: resultType
- * {String} Value of the resultType attribute of the GetRecords element,
- * specifies the result type in the GetRecords response, "hits" is
- * the default.
- */
- resultType: null,
-
- /**
- * APIProperty: outputFormat
- * {String} Value of the outputFormat attribute of the GetRecords element,
- * specifies the format of the GetRecords response,
- * "application/xml" is the default.
- */
- outputFormat: null,
-
- /**
- * APIProperty: outputSchema
- * {String} Value of the outputSchema attribute of the GetRecords element,
- * specifies the schema of the GetRecords response.
- */
- outputSchema: null,
-
- /**
- * APIProperty: startPosition
- * {String} Value of the startPosition attribute of the GetRecords element,
- * specifies the start position (offset+1) for the GetRecords response,
- * 1 is the default.
- */
- startPosition: null,
-
- /**
- * APIProperty: maxRecords
- * {String} Value of the maxRecords attribute of the GetRecords element,
- * specifies the maximum number of records in the GetRecords response,
- * 10 is the default.
- */
- maxRecords: null,
-
- /**
- * APIProperty: DistributedSearch
- * {String} Value of the csw:DistributedSearch element, used when writing
- * a csw:GetRecords document.
- */
- DistributedSearch: null,
-
- /**
- * APIProperty: ResponseHandler
- * {Array({String})} Values of the csw:ResponseHandler elements, used when
- * writting a csw:GetRecords document.
- */
- ResponseHandler: null,
-
- /**
- * APIProperty: Query
- * {String} Value of the csw:Query element, used when writing a csw:GetRecords
- * document.
- */
- Query: null,
-
- /**
- * Property: regExes
- * Compiled regular expressions for manipulating strings.
- */
- regExes: {
- trimSpace: (/^\s*|\s*$/g),
- removeSpace: (/\s*/g),
- splitSpace: (/\s+/),
- trimComma: (/\s*,\s*/g)
- },
-
- /**
- * Constructor: OpenLayers.Format.CSWGetRecords.v2_0_2
- * A class for parsing and generating CSWGetRecords v2.0.2 transactions.
+ * Constructor: OpenLayers.Format.Filter.v1_1_0
+ * Instances of this class are not created directly. Use the
+ * <OpenLayers.Format.Filter> constructor instead.
*
* Parameters:
- * options - {Object} Optional object whose properties will be set on the
- * instance.
- *
- * Valid options properties (documented as class properties):
- * - requestId
- * - resultType
- * - outputFormat
- * - outputSchema
- * - startPosition
- * - maxRecords
- * - DistributedSearch
- * - ResponseHandler
- * - Query
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
*/
initialize: function(options) {
- OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
+ OpenLayers.Format.GML.v3.prototype.initialize.apply(
+ this, [options]
+ );
},
/**
- * APIMethod: read
- * Parse the response from a GetRecords request.
- */
- read: function(data) {
- if(typeof data == "string") {
- data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
- }
- if(data && data.nodeType == 9) {
- data = data.documentElement;
- }
- var obj = {};
- this.readNode(data, obj);
- return obj;
- },
-
- /**
* Property: readers
* Contains public functions, grouped by namespace prefix, that will
* be applied when a namespaced node is found matching the function
* name. The function will be applied in the scope of this parser
* with two arguments: the node being read and a context object passed
* from the parent.
*/
readers: {
- "csw": {
- "GetRecordsResponse": function(node, obj) {
- obj.records = [];
- this.readChildNodes(node, obj);
- var version = this.getAttributeNS(node, "", 'version');
- if (version != "") {
- obj.version = version;
- }
+ "fes": OpenLayers.Util.applyDefaults({
+ "PropertyIsEqualTo": function(node, obj) {
+ var matchCase = node.getAttribute("matchCase");
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.EQUAL_TO,
+ matchCase: !(matchCase === "false" || matchCase === "0")
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
},
- "RequestId": function(node, obj) {
- obj.RequestId = this.getChildValue(node);
+ "PropertyIsNotEqualTo": function(node, obj) {
+ var matchCase = node.getAttribute("matchCase");
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.NOT_EQUAL_TO,
+ matchCase: !(matchCase === "false" || matchCase === "0")
+ });
+ this.readChildNodes(node, filter);
+ obj.filters.push(filter);
},
- "SearchStatus": function(node, obj) {
- obj.SearchStatus = {};
- var timestamp = this.getAttributeNS(node, "", 'timestamp');
- if (timestamp != "") {
- obj.SearchStatus.timestamp = timestamp;
- }
- },
- "SearchResults": function(node, obj) {
- this.readChildNodes(node, obj);
- var attrs = node.attributes;
- var SearchResults = {};
- for(var i=0, len=attrs.length; i<len; ++i) {
- if ((attrs[i].name == "numberOfRecordsMatched") ||
- (attrs[i].name == "numberOfRecordsReturned") ||
- (attrs[i].name == "nextRecord")) {
- SearchResults[attrs[i].name] = parseInt(attrs[i].nodeValue);
- } else {
- SearchResults[attrs[i].name] = attrs[i].nodeValue;
- }
- }
- obj.SearchResults = SearchResults;
- },
- "SummaryRecord": function(node, obj) {
- var record = {type: "SummaryRecord"};
- this.readChildNodes(node, record);
- obj.records.push(record);
- },
- "BriefRecord": function(node, obj) {
- var record = {type: "BriefRecord"};
- this.readChildNodes(node, record);
- obj.records.push(record);
- },
- "DCMIRecord": function(node, obj) {
- var record = {type: "DCMIRecord"};
- this.readChildNodes(node, record);
- obj.records.push(record);
- },
- "Record": function(node, obj) {
- var record = {type: "Record"};
- this.readChildNodes(node, record);
- obj.records.push(record);
- },
- "*": function(node, obj) {
- var name = node.localName || node.nodeName.split(":").pop();
- obj[name] = this.getChildValue(node);
+ "PropertyIsLike": function(node, obj) {
+ var filter = new OpenLayers.Filter.Comparison({
+ type: OpenLayers.Filter.Comparison.LIKE
+ });
+ this.readChildNodes(node, filter);
+ var wildCard = node.getAttribute("wildCard");
+ var singleChar = node.getAttribute("singleChar");
+ var esc = node.getAttribute("escapeChar");
+ filter.value2regex(wildCard, singleChar, esc);
+ obj.filters.push(filter);
}
- },
- "geonet": {
- "info": function(node, obj) {
- var gninfo = {};
- this.readChildNodes(node, gninfo);
- obj.gninfo = gninfo;
- }
- },
- "dc": {
- // audience, contributor, coverage, creator, date, description, format,
- // identifier, language, provenance, publisher, relation, rights,
- // rightsHolder, source, subject, title, type, URI
- "*": function(node, obj) {
- var name = node.localName || node.nodeName.split(":").pop();
- if (!(OpenLayers.Util.isArray(obj[name]))) {
- obj[name] = [];
- }
- var dc_element = {};
- var attrs = node.attributes;
- for(var i=0, len=attrs.length; i<len; ++i) {
- dc_element[attrs[i].name] = attrs[i].nodeValue;
- }
- dc_element.value = this.getChildValue(node);
- if (dc_element.value != "") {
- obj[name].push(dc_element);
- }
- }
- },
- "dct": {
- // abstract, modified, spatial
- "*": function(node, obj) {
- var name = node.localName || node.nodeName.split(":").pop();
- if (!(OpenLayers.Util.isArray(obj[name]))) {
- obj[name] = [];
- }
- obj[name].push(this.getChildValue(node));
- }
- },
- "ows": OpenLayers.Util.applyDefaults({
- "BoundingBox": function(node, obj) {
- if (obj.bounds) {
- obj.BoundingBox = [{crs: obj.projection, value:
- [
- obj.bounds.left,
- obj.bounds.bottom,
- obj.bounds.right,
- obj.bounds.top
- ]
- }];
- delete obj.projection;
- delete obj.bounds;
- }
- OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]["BoundingBox"].apply(
- this, arguments);
- }
- }, OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"])
+ }, OpenLayers.Format.Filter.v2.prototype.readers["fes"]),
+ "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"],
+ "feature": OpenLayers.Format.GML.v3.prototype.readers["feature"]
},
-
- /**
- * Method: write
- * Given an configuration js object, write a CSWGetRecords request.
- *
- * Parameters:
- * options - {Object} A object mapping the request.
- *
- * Returns:
- * {String} A serialized CSWGetRecords request.
- */
- write: function(options) {
- var node = this.writeNode("csw:GetRecords", options);
- node.setAttribute("xmlns:gmd", this.namespaces.gmd);
- return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
- },
/**
* Property: writers
* As a compliment to the readers property, this structure contains public
* writing functions grouped by namespace alias and named like the
* node names they produce.
*/
writers: {
- "csw": {
- "GetRecords": function(options) {
- if (!options) {
- options = {};
- }
- var node = this.createElementNSPlus("csw:GetRecords", {
- attributes: {
- service: "CSW",
- version: this.version,
- requestId: options.requestId || this.requestId,
- resultType: options.resultType || this.resultType,
- outputFormat: options.outputFormat || this.outputFormat,
- outputSchema: options.outputSchema || this.outputSchema,
- startPosition: options.startPosition || this.startPosition,
- maxRecords: options.maxRecords || this.maxRecords
- }
+ "fes": OpenLayers.Util.applyDefaults({
+ "PropertyIsEqualTo": function(filter) {
+ var node = this.createElementNSPlus("fes:PropertyIsEqualTo", {
+ attributes: {matchCase: filter.matchCase}
});
- if (options.DistributedSearch || this.DistributedSearch) {
- this.writeNode(
- "csw:DistributedSearch",
- options.DistributedSearch || this.DistributedSearch,
- node
- );
- }
- var ResponseHandler = options.ResponseHandler || this.ResponseHandler;
- if (OpenLayers.Util.isArray(ResponseHandler) && ResponseHandler.length > 0) {
- // ResponseHandler must be a non-empty array
- for(var i=0, len=ResponseHandler.length; i<len; i++) {
- this.writeNode(
- "csw:ResponseHandler",
- ResponseHandler[i],
- node
- );
- }
- }
- this.writeNode("Query", options.Query || this.Query, node);
+ // no fes:expression handling for ValueReference for now
+ this.writeNode("ValueReference", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
return node;
},
- "DistributedSearch": function(options) {
- var node = this.createElementNSPlus("csw:DistributedSearch", {
- attributes: {
- hopCount: options.hopCount
- }
+ "PropertyIsNotEqualTo": function(filter) {
+ var node = this.createElementNSPlus("fes:PropertyIsNotEqualTo", {
+ attributes: {matchCase: filter.matchCase}
});
+ // no fes:expression handling for ValueReference for now
+ this.writeNode("ValueReference", filter, node);
+ // handle Literals or Functions for now
+ this.writeOgcExpression(filter.value, node);
return node;
},
- "ResponseHandler": function(options) {
- var node = this.createElementNSPlus("csw:ResponseHandler", {
- value: options.value
+ "PropertyIsLike": function(filter) {
+ var node = this.createElementNSPlus("fes:PropertyIsLike", {
+ attributes: {
+ matchCase: filter.matchCase,
+ wildCard: "*", singleChar: ".", escapeChar: "!"
+ }
});
+ // no fes:expression handling for now
+ this.writeNode("ValueReference", filter, node);
+ // convert regex string to ogc string
+ this.writeNode("Literal", filter.regex2value(), node);
return node;
},
- "Query": function(options) {
- if (!options) {
- options = {};
+ "BBOX": function(filter) {
+ var node = this.createElementNSPlus("fes:BBOX");
+ // ValueReference is optional in 1.1.0
+ filter.property && this.writeNode("ValueReference", filter, node);
+ var box = this.writeNode("gml:Envelope", filter.value);
+ if(filter.projection) {
+ box.setAttribute("srsName", filter.projection);
}
- var node = this.createElementNSPlus("csw:Query", {
- attributes: {
- typeNames: options.typeNames || "csw:Record"
- }
- });
- var ElementName = options.ElementName;
- if (OpenLayers.Util.isArray(ElementName) && ElementName.length > 0) {
- // ElementName must be a non-empty array
- for(var i=0, len=ElementName.length; i<len; i++) {
- this.writeNode(
- "csw:ElementName",
- ElementName[i],
- node
- );
- }
- } else {
+ node.appendChild(box);
+ return node;
+ },
+ "SortBy": function(sortProperties) {
+ var node = this.createElementNSPlus("fes:SortBy");
+ for (var i=0,l=sortProperties.length;i<l;i++) {
this.writeNode(
- "csw:ElementSetName",
- options.ElementSetName || {value: 'summary'},
+ "fes:SortProperty",
+ sortProperties[i],
node
);
}
- if (options.Constraint) {
- this.writeNode(
- "csw:Constraint",
- options.Constraint,
- node
- );
- }
- if (options.SortBy) {
- this.writeNode(
- "ogc:SortBy",
- options.SortBy,
- node
- );
- }
return node;
- },
- "ElementName": function(options) {
- var node = this.createElementNSPlus("csw:ElementName", {
- value: options.value
- });
+ },
+ "SortProperty": function(sortProperty) {
+ var node = this.createElementNSPlus("fes:SortProperty");
+ this.writeNode(
+ "fes:ValueReference",
+ sortProperty,
+ node
+ );
+ this.writeNode(
+ "fes:SortOrder",
+ (sortProperty.order == 'DESC') ? 'DESC' : 'ASC',
+ node
+ );
return node;
},
- "ElementSetName": function(options) {
- var node = this.createElementNSPlus("csw:ElementSetName", {
- attributes: {
- typeNames: options.typeNames
- },
- value: options.value
+ "SortOrder": function(value) {
+ var node = this.createElementNSPlus("fes:SortOrder", {
+ value: value
});
return node;
- },
- "Constraint": function(options) {
- var node = this.createElementNSPlus("csw:Constraint", {
- attributes: {
- version: options.version
- }
- });
- if (options.Filter) {
- var format = new OpenLayers.Format.Filter({
- version: options.version
- });
- node.appendChild(format.write(options.Filter));
- } else if (options.CqlText) {
- var child = this.createElementNSPlus("CqlText", {
- value: options.CqlText.value
- });
- node.appendChild(child);
- }
- return node;
}
- },
- "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"]
+ }, OpenLayers.Format.Filter.v2.prototype.writers["fes"]),
+ "gml": OpenLayers.Format.GML.v3.prototype.writers["gml"],
+ "feature": OpenLayers.Format.GML.v3.prototype.writers["feature"]
},
-
- CLASS_NAME: "OpenLayers.Format.CSWGetRecords.v2_0_2"
+
+ /**
+ * Method: writeSpatial
+ *
+ * Read a {<OpenLayers.Filter.Spatial>} filter and converts it into XML.
+ *
+ * Parameters:
+ * filter - {<OpenLayers.Filter.Spatial>} The filter.
+ * name - {String} Name of the generated XML element.
+ *
+ * Returns:
+ * {DOMElement} The created XML element.
+ */
+ writeSpatial: function(filter, name) {
+ var node = this.createElementNSPlus("fes:"+name);
+ this.writeNode("ValueReference", filter, node);
+ if(filter.value instanceof OpenLayers.Filter.Function) {
+ this.writeNode("Function", filter.value, node);
+ } else {
+ var child;
+ if(filter.value instanceof OpenLayers.Geometry) {
+ child = this.writeNode("feature:_geometry", filter.value).firstChild;
+ } else {
+ child = this.writeNode("gml:Envelope", filter.value);
+ }
+ if(filter.projection) {
+ child.setAttribute("srsName", filter.projection);
+ }
+ node.appendChild(child);
+ }
+ return node;
+ },
+
+ CLASS_NAME: "OpenLayers.Format.Filter.v2_0_0"
+
});
/* ======================================================================
+ Rico/license.js
+ ====================================================================== */
+
+/**
+ * @license Apache 2
+ *
+ * Contains portions of Rico <http://openrico.org/>
+ *
+ * Copyright 2005 Sabre Airline Solutions
+ *
+ * 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.
+ */
+/* ======================================================================
OpenLayers/Marker/Box.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -66468,11 +67721,11 @@
/* ======================================================================
OpenLayers/Format/Text.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -66623,11 +67876,11 @@
});
/* ======================================================================
OpenLayers/Layer/Text.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -66891,20 +68144,179 @@
},
CLASS_NAME: "OpenLayers.Layer.Text"
});
/* ======================================================================
- OpenLayers/Control/Scale.js
+ OpenLayers/Format/WCSDescribeCoverage/v1_1_0.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/Format/WCSDescribeCoverage/v1.js
+ * @requires OpenLayers/Format/OWSCommon/v1_1_0.js
+ * @requires OpenLayers/BaseTypes/Bounds.js
+ */
/**
+ * Class: OpenLayers.Format.WCSDescribeCoverage/v1_1_0
+ * Read WCS DescribeCoverage version 1.1.0.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.WCSDescribeCoverage.v1>
+ */
+OpenLayers.Format.WCSDescribeCoverage.v1_1_0 = OpenLayers.Class(
+ OpenLayers.Format.WCSDescribeCoverage.v1, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ wcs: "http://www.opengis.net/wcs/1.1",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ ows: "http://www.opengis.net/ows/1.1"
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WCSDescribeCoverage.v1_1_0
+ * Create a new parser for WCS DescribeCoverage version 1.1.0.
+ *
+ * Parameters:
+ * options - {Object} An optional object whose properties will be set on
+ * this instance.
+ */
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wcs": {
+ // Root object, contains one or more CoverageDescription entries
+ // In 1.0.0, this was CoverageDescription, in 1.1.0, it's
+ // CoverageDescriptions (plural)
+ "CoverageDescriptions": function(node, obj) {
+ obj.coverageDescriptions = {};
+ this.readChildNodes(node, obj.coverageDescriptions);
+
+ obj.coverageDescriptionKeys = [];
+ for(var key in obj.coverageDescriptions) {
+ obj.coverageDescriptionKeys.push(key);
+ }
+ // This would be more efficient, but only in newer browsers:
+ // obj.coverageDescriptionKeys = Object.keys(obj.coverageDescriptions);
+ },
+ // In 1.0.0, CoverageDescription was called CoverageOffering
+ "CoverageDescription": function(node, descriptions) {
+ var description = {};
+ this.readChildNodes(node, description);
+ descriptions[description.identifier] = description;
+
+ // Provide a consistent handle on the native CRS
+ description.nativeCRS =
+ description.domain.spatialDomain.gridCRS.gridBaseCRS;
+ },
+ "Identifier": function(node, description) {
+ description.identifier = this.getChildValue(node);
+ },
+ "Title": function(node, description) {
+ description.title = this.getChildValue(node);
+ },
+ "Domain": function(node, description) {
+ description.domain = {};
+ this.readChildNodes(node, description.domain);
+ },
+ "SpatialDomain": function(node, domain) {
+ domain.spatialDomain = { boundingBoxes:{} };
+
+ var bb = { BoundingBox:[] };
+
+ this.readChildNodes(node, bb);
+
+ // Repack structure so bounding box list is indexed by CRS --
+ // this will make it easier to find the one we want, and
+ // provides a consistent structure with 1.0.0
+ for(var i=0, len=bb.BoundingBox.length; i<len;i++) {
+ if(!!bb.BoundingBox[i].crs) {
+ domain.spatialDomain.boundingBoxes[bb.BoundingBox[i].crs] =
+ bb.BoundingBox[i].bounds;
+ }
+ }
+ domain.spatialDomain.gridCRS = bb.gridCRS;
+ },
+ "GridCRS": function(node, spatialDomain) {
+ spatialDomain.gridCRS = {};
+ this.readChildNodes(node, spatialDomain.gridCRS);
+ },
+ "GridBaseCRS": function(node, gridCRS) {
+ gridCRS.gridBaseCRS = this.getChildValue(node);
+ },
+ "GridType": function(node, gridCRS) {
+ gridCRS.gridType = this.getChildValue(node);
+ },
+ "GridOrigin": function(node, gridCRS) {
+ var xy = this.getChildValue(node).split(' ');
+ if(xy.length == 2) {
+ gridCRS.gridOrigin = {};
+ gridCRS.gridOrigin.x = Number(xy[0]);
+ gridCRS.gridOrigin.y = Number(xy[1]);
+ }
+ },
+ "GridOffsets": function(node, gridCRS) {
+ var xy = this.getChildValue(node).split(' ');
+ if(xy.length == 2) {
+ gridCRS.gridOffsets = {};
+ gridCRS.gridOffsets.x = Number(xy[0]);
+ gridCRS.gridOffsets.y = Number(xy[1]);
+ }
+ },
+ "GridCS": function(node, gridCRS) {
+ gridCRS.gridCS = this.getChildValue(node);
+ },
+ "SupportedCRS": function(node, description) {
+ if(!!!description.supportedCRSs) {
+ description.supportedCRSs = [];
+ }
+
+ var crs = this.getChildValue(node);
+ description.supportedCRSs.push(crs);
+ },
+ "SupportedFormat": function(node, description) {
+ if(!!!description.supportedFormats) {
+ description.supportedFormats = [];
+ }
+
+ var format = this.getChildValue(node);
+ description.supportedFormats.push(format);
+ }
+ },
+ "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WCSDescribeCoverage.v1_1_0"
+
+});
+/* ======================================================================
+ OpenLayers/Control/Scale.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/Control.js
* @requires OpenLayers/Lang.js
*/
/**
@@ -66995,14 +68407,317 @@
CLASS_NAME: "OpenLayers.Control.Scale"
});
/* ======================================================================
+ OpenLayers/Layer/PointGrid.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/Layer/Vector.js
+ * @requires OpenLayers/Geometry/Polygon.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.PointGrid
+ * A point grid layer dynamically generates a regularly spaced grid of point
+ * features. This is a specialty layer for cases where an application needs
+ * a regular grid of points. It can be used, for example, in an editing
+ * environment to snap to a grid.
+ *
+ * Create a new vector layer with the <OpenLayers.Layer.PointGrid> constructor.
+ * (code)
+ * // create a grid with points spaced at 10 map units
+ * var points = new OpenLayers.Layer.PointGrid({dx: 10, dy: 10});
+ *
+ * // create a grid with different x/y spacing rotated 15 degrees clockwise.
+ * var points = new OpenLayers.Layer.PointGrid({dx: 5, dy: 10, rotation: 15});
+ * (end)
+ *
+ * Inherits from:
+ * - <OpenLayers.Layer.Vector>
+ */
+OpenLayers.Layer.PointGrid = OpenLayers.Class(OpenLayers.Layer.Vector, {
+
+ /**
+ * APIProperty: dx
+ * {Number} Point grid spacing in the x-axis direction (map units).
+ * Read-only. Use the <setSpacing> method to modify this value.
+ */
+ dx: null,
+
+ /**
+ * APIProperty: dy
+ * {Number} Point grid spacing in the y-axis direction (map units).
+ * Read-only. Use the <setSpacing> method to modify this value.
+ */
+ dy: null,
+
+ /**
+ * APIProperty: ratio
+ * {Number} Ratio of the desired grid size to the map viewport size.
+ * Default is 1.5. Larger ratios mean the grid is recalculated less often
+ * while panning. The <maxFeatures> setting has precedence when determining
+ * grid size. Read-only. Use the <setRatio> method to modify this value.
+ */
+ ratio: 1.5,
+
+ /**
+ * APIProperty: maxFeatures
+ * {Number} The maximum number of points to generate in the grid. Default
+ * is 250. Read-only. Use the <setMaxFeatures> method to modify this value.
+ */
+ maxFeatures: 250,
+
+ /**
+ * APIProperty: rotation
+ * {Number} Grid rotation (in degrees clockwise from the positive x-axis).
+ * Default is 0. Read-only. Use the <setRotation> method to modify this
+ * value.
+ */
+ rotation: 0,
+
+ /**
+ * APIProperty: origin
+ * {<OpenLayers.LonLat>} Grid origin. The grid lattice will be aligned with
+ * the origin. If not set at construction, the center of the map's maximum
+ * extent is used. Read-only. Use the <setOrigin> method to modify this
+ * value.
+ */
+ origin: null,
+
+ /**
+ * Property: gridBounds
+ * {<OpenLayers.Bounds>} Internally cached grid bounds (with optional
+ * rotation applied).
+ */
+ gridBounds: null,
+
+ /**
+ * Constructor: OpenLayers.Layer.PointGrid
+ * Creates a new point grid layer.
+ *
+ * Parameters:
+ * config - {Object} An object containing all configuration properties for
+ * the layer. The <dx> and <dy> properties are required to be set at
+ * construction. Any other layer properties may be set in this object.
+ */
+ initialize: function(config) {
+ config = config || {};
+ OpenLayers.Layer.Vector.prototype.initialize.apply(this, [config.name, config]);
+ },
+
+ /**
+ * Method: setMap
+ * The layer has been added to the map.
+ *
+ * Parameters:
+ * map - {<OpenLayers.Map>}
+ */
+ setMap: function(map) {
+ OpenLayers.Layer.Vector.prototype.setMap.apply(this, arguments);
+ map.events.register("moveend", this, this.onMoveEnd);
+ },
+
+ /**
+ * Method: removeMap
+ * The layer has been removed from the map.
+ *
+ * Parameters:
+ * map - {<OpenLayers.Map>}
+ */
+ removeMap: function(map) {
+ map.events.unregister("moveend", this, this.onMoveEnd);
+ OpenLayers.Layer.Vector.prototype.removeMap.apply(this, arguments);
+ },
+
+ /**
+ * APIMethod: setRatio
+ * Set the grid <ratio> property and update the grid. Can only be called
+ * after the layer has been added to a map with a center/extent.
+ *
+ * Parameters:
+ * ratio - {Number}
+ */
+ setRatio: function(ratio) {
+ this.ratio = ratio;
+ this.updateGrid(true);
+ },
+
+ /**
+ * APIMethod: setMaxFeatures
+ * Set the grid <maxFeatures> property and update the grid. Can only be
+ * called after the layer has been added to a map with a center/extent.
+ *
+ * Parameters:
+ * maxFeatures - {Number}
+ */
+ setMaxFeatures: function(maxFeatures) {
+ this.maxFeatures = maxFeatures;
+ this.updateGrid(true);
+ },
+
+ /**
+ * APIMethod: setSpacing
+ * Set the grid <dx> and <dy> properties and update the grid. If only one
+ * argument is provided, it will be set as <dx> and <dy>. Can only be
+ * called after the layer has been added to a map with a center/extent.
+ *
+ * Parameters:
+ * dx - {Number}
+ * dy - {Number}
+ */
+ setSpacing: function(dx, dy) {
+ this.dx = dx;
+ this.dy = dy || dx;
+ this.updateGrid(true);
+ },
+
+ /**
+ * APIMethod: setOrigin
+ * Set the grid <origin> property and update the grid. Can only be called
+ * after the layer has been added to a map with a center/extent.
+ *
+ * Parameters:
+ * origin - {<OpenLayers.LonLat>}
+ */
+ setOrigin: function(origin) {
+ this.origin = origin;
+ this.updateGrid(true);
+ },
+
+ /**
+ * APIMethod: getOrigin
+ * Get the grid <origin> property.
+ *
+ * Returns:
+ * {<OpenLayers.LonLat>} The grid origin.
+ */
+ getOrigin: function() {
+ if (!this.origin) {
+ this.origin = this.map.getExtent().getCenterLonLat();
+ }
+ return this.origin;
+ },
+
+ /**
+ * APIMethod: setRotation
+ * Set the grid <rotation> property and update the grid. Rotation values
+ * are in degrees clockwise from the positive x-axis (negative values
+ * for counter-clockwise rotation). Can only be called after the layer
+ * has been added to a map with a center/extent.
+ *
+ * Parameters:
+ * rotation - {Number} Degrees clockwise from the positive x-axis.
+ */
+ setRotation: function(rotation) {
+ this.rotation = rotation;
+ this.updateGrid(true);
+ },
+
+ /**
+ * Method: onMoveEnd
+ * Listener for map "moveend" events.
+ */
+ onMoveEnd: function() {
+ this.updateGrid();
+ },
+
+ /**
+ * Method: getViewBounds
+ * Gets the (potentially rotated) view bounds for grid calculations.
+ *
+ * Returns:
+ * {<OpenLayers.Bounds>}
+ */
+ getViewBounds: function() {
+ var bounds = this.map.getExtent();
+ if (this.rotation) {
+ var origin = this.getOrigin();
+ var rotationOrigin = new OpenLayers.Geometry.Point(origin.lon, origin.lat);
+ var rect = bounds.toGeometry();
+ rect.rotate(-this.rotation, rotationOrigin);
+ bounds = rect.getBounds();
+ }
+ return bounds;
+ },
+
+ /**
+ * Method: updateGrid
+ * Update the grid.
+ *
+ * Parameters:
+ * force - {Boolean} Update the grid even if the previous bounds are still
+ * valid.
+ */
+ updateGrid: function(force) {
+ if (force || this.invalidBounds()) {
+ var viewBounds = this.getViewBounds();
+ var origin = this.getOrigin();
+ var rotationOrigin = new OpenLayers.Geometry.Point(origin.lon, origin.lat);
+ var viewBoundsWidth = viewBounds.getWidth();
+ var viewBoundsHeight = viewBounds.getHeight();
+ var aspectRatio = viewBoundsWidth / viewBoundsHeight;
+ var maxHeight = Math.sqrt(this.dx * this.dy * this.maxFeatures / aspectRatio);
+ var maxWidth = maxHeight * aspectRatio;
+ var gridWidth = Math.min(viewBoundsWidth * this.ratio, maxWidth);
+ var gridHeight = Math.min(viewBoundsHeight * this.ratio, maxHeight);
+ var center = viewBounds.getCenterLonLat();
+ this.gridBounds = new OpenLayers.Bounds(
+ center.lon - (gridWidth / 2),
+ center.lat - (gridHeight / 2),
+ center.lon + (gridWidth / 2),
+ center.lat + (gridHeight / 2)
+ );
+ var rows = Math.floor(gridHeight / this.dy);
+ var cols = Math.floor(gridWidth / this.dx);
+ var gridLeft = origin.lon + (this.dx * Math.ceil((this.gridBounds.left - origin.lon) / this.dx));
+ var gridBottom = origin.lat + (this.dy * Math.ceil((this.gridBounds.bottom - origin.lat) / this.dy));
+ var features = new Array(rows * cols);
+ var x, y, point;
+ for (var i=0; i<cols; ++i) {
+ x = gridLeft + (i * this.dx);
+ for (var j=0; j<rows; ++j) {
+ y = gridBottom + (j * this.dy);
+ point = new OpenLayers.Geometry.Point(x, y);
+ if (this.rotation) {
+ point.rotate(this.rotation, rotationOrigin);
+ }
+ features[(i*rows)+j] = new OpenLayers.Feature.Vector(point);
+ }
+ }
+ this.destroyFeatures(this.features, {silent: true});
+ this.addFeatures(features, {silent: true});
+ }
+ },
+
+ /**
+ * Method: invalidBounds
+ * Determine whether the previously generated point grid is invalid.
+ * This occurs when the map bounds extends beyond the previously
+ * generated grid bounds.
+ *
+ * Returns:
+ * {Boolean}
+ */
+ invalidBounds: function() {
+ return !this.gridBounds || !this.gridBounds.containsBounds(this.getViewBounds());
+ },
+
+ CLASS_NAME: "OpenLayers.Layer.PointGrid"
+
+});
+/* ======================================================================
OpenLayers/Layer/MapGuide.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -67445,11 +69160,11 @@
});
/* ======================================================================
OpenLayers/Control/Measure.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -67464,11 +69179,11 @@
* Inherits from:
* - <OpenLayers.Control>
*/
OpenLayers.Control.Measure = OpenLayers.Class(OpenLayers.Control, {
- /**
+ /**
* APIProperty: events
* {<OpenLayers.Events>} Events instance for listeners and triggering
* control specific events.
*
* Register a listener for a particular event with the following syntax:
@@ -67488,32 +69203,32 @@
/**
* APIProperty: handlerOptions
* {Object} Used to set non-default properties on the control's handler
*/
-
+
/**
* Property: callbacks
* {Object} The functions that are sent to the handler for callback
*/
callbacks: null,
-
+
/**
- * Property: displaySystem
+ * APIProperty: displaySystem
* {String} Display system for output measurements. Supported values
* are 'english', 'metric', and 'geographic'. Default is 'metric'.
*/
displaySystem: 'metric',
-
+
/**
- * Property: geodesic
+ * APIProperty: geodesic
* {Boolean} Calculate geodesic metrics instead of planar metrics. This
* requires that geometries can be transformed into Geographic/WGS84
* (if that is not already the map projection). Default is false.
*/
geodesic: false,
-
+
/**
* Property: displaySystemUnits
* {Object} Units for various measurement systems. Values are arrays
* of unit abbreviations (from OpenLayers.INCHES_PER_UNIT) in decreasing
* order of length.
@@ -67558,32 +69273,32 @@
*/
immediate : false,
/**
* Constructor: OpenLayers.Control.Measure
- *
+ *
* Parameters:
- * handler - {<OpenLayers.Handler>}
- * options - {Object}
+ * handler - {<OpenLayers.Handler>}
+ * options - {Object}
*/
initialize: function(handler, options) {
OpenLayers.Control.prototype.initialize.apply(this, [options]);
var callbacks = {done: this.measureComplete,
point: this.measurePartial};
if (this.immediate){
callbacks.modify = this.measureImmediate;
}
this.callbacks = OpenLayers.Util.extend(callbacks, this.callbacks);
- // let the handler options override, so old code that passes 'persist'
+ // let the handler options override, so old code that passes 'persist'
// directly to the handler does not need an update
this.handlerOptions = OpenLayers.Util.extend(
{persist: this.persist}, this.handlerOptions
);
this.handler = new handler(this, this.callbacks, this.handlerOptions);
},
-
+
/**
* APIMethod: deactivate
*/
deactivate: function() {
this.cancelDelay();
@@ -67611,11 +69326,11 @@
this.callbacks.modify = this.measureImmediate;
} else {
delete this.callbacks.modify;
}
},
-
+
/**
* Method: updateHandler
*
* Parameters:
* handler - {Function} One of the sketch handler constructors.
@@ -67641,11 +69356,11 @@
*/
measureComplete: function(geometry) {
this.cancelDelay();
this.measure(geometry, "measure");
},
-
+
/**
* Method: measurePartial
* Called each time a new point is added to the measurement sketch.
*
* Parameters:
@@ -67672,13 +69387,15 @@
},
/**
* Method: measureImmediate
* Called each time the measurement sketch is modified.
- *
- * Parameters: point - {<OpenLayers.Geometry.Point>} The point at the
- * mouseposition. feature - {<OpenLayers.Feature.Vector>} The sketch feature.
+ *
+ * Parameters:
+ * point - {<OpenLayers.Geometry.Point>} The point at the mouse position.
+ * feature - {<OpenLayers.Feature.Vector>} The sketch feature.
+ * drawing - {Boolean} Indicates whether we're currently drawing.
*/
measureImmediate : function(point, feature, drawing) {
if (drawing && !this.handler.freehandMode(this.handler.evt)) {
this.cancelDelay();
this.measure(feature.geometry, "measurepartial");
@@ -67717,11 +69434,11 @@
units: stat[1],
order: order,
geometry: geometry
});
},
-
+
/**
* Method: getBestArea
* Based on the <displaySystem> returns the area of a geometry.
*
* Parameters:
@@ -67741,11 +69458,11 @@
break;
}
}
return [area, unit];
},
-
+
/**
* Method: getArea
*
* Parameters:
* geometry - {<OpenLayers.Geometry>}
@@ -67768,11 +69485,11 @@
var inPerMapUnit = OpenLayers.INCHES_PER_UNIT[geomUnits];
area *= Math.pow((inPerMapUnit / inPerDisplayUnit), 2);
}
return area;
},
-
+
/**
* Method: getBestLength
* Based on the <displaySystem> returns the length of a geometry.
*
* Parameters:
@@ -67826,11 +69543,11 @@
});
/* ======================================================================
OpenLayers/Format/WMC/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -67934,11 +69651,11 @@
});
/* ======================================================================
OpenLayers/Format/WMTSCapabilities/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -68051,11 +69768,10 @@
styles: [],
formats: [],
dimensions: [],
tileMatrixSetLinks: []
};
- layer.layers = [];
this.readChildNodes(node, layer);
obj.layers.push(layer);
},
"Style": function(node, obj) {
var style = {};
@@ -68084,16 +69800,43 @@
} else {
// TileMatrixSet as string type in schema
obj.tileMatrixSet = this.getChildValue(node);
}
},
+ "TileMatrixSetLimits": function(node, obj) {
+ obj.tileMatrixSetLimits = [];
+ this.readChildNodes(node, obj);
+ },
+ "TileMatrixLimits": function(node, obj) {
+ var tileMatrixLimits = {};
+ this.readChildNodes(node, tileMatrixLimits);
+ obj.tileMatrixSetLimits.push(tileMatrixLimits);
+ },
+ "MinTileRow": function(node, obj) {
+ obj.minTileRow = parseInt(this.getChildValue(node));
+ },
+ "MaxTileRow": function(node, obj) {
+ obj.maxTileRow = parseInt(this.getChildValue(node));
+ },
+ "MinTileCol": function(node, obj) {
+ obj.minTileCol = parseInt(this.getChildValue(node));
+ },
+ "MaxTileCol": function(node, obj) {
+ obj.maxTileCol = parseInt(this.getChildValue(node));
+ },
"TileMatrix": function(node, obj) {
- var tileMatrix = {
- supportedCRS: obj.supportedCRS
- };
- this.readChildNodes(node, tileMatrix);
- obj.matrixIds.push(tileMatrix);
+ // node could be child of wmts:TileMatrixSet or wmts:TileMatrixLimits
+ if (obj.identifier) {
+ // node is child of wmts:TileMatrixSet
+ var tileMatrix = {
+ supportedCRS: obj.supportedCRS
+ };
+ this.readChildNodes(node, tileMatrix);
+ obj.matrixIds.push(tileMatrix);
+ } else {
+ obj.tileMatrix = this.getChildValue(node);
+ }
},
"ScaleDenominator": function(node, obj) {
obj.scaleDenominator = parseFloat(this.getChildValue(node));
},
"TopLeftCorner": function(node, obj) {
@@ -68142,10 +69885,38 @@
template: node.getAttribute("template"),
resourceType: resourceType
};
obj.resourceUrls.push(resourceUrl);
},
+ "LegendURL": function(node, obj) {
+ obj.legends = obj.legends || [];
+ var legend = {
+ format: node.getAttribute("format"),
+ href: node.getAttribute("xlink:href")
+ };
+ var width = node.getAttribute("width"),
+ height = node.getAttribute("height"),
+ minScaleDenominator = node.getAttribute("minScaleDenominator"),
+ maxScaleDenominator = node.getAttribute("maxScaleDenominator");
+ if (width !== null) {
+ legend.width = parseInt(width);
+ }
+ if (height !== null) {
+ legend.height = parseInt(height);
+ }
+ if (minScaleDenominator !== null) {
+ legend.minScaleDenominator = parseInt(minScaleDenominator);
+ }
+ if (maxScaleDenominator !== null) {
+ legend.maxScaleDenominator = parseInt(maxScaleDenominator);
+ }
+ obj.legends.push(legend);
+ },
+ "InfoFormat": function(node, obj) {
+ obj.infoFormats = obj.infoFormats || [];
+ obj.infoFormats.push(this.getChildValue(node));
+ },
// not used for now, can be added in the future though
/*"Themes": function(node, obj) {
obj.themes = [];
this.readChildNodes(node, obj.themes);
},
@@ -68162,15 +69933,10 @@
"ServiceMetadataURL": function(node, obj) {
obj.serviceMetadataUrl = {};
obj.serviceMetadataUrl.href = node.getAttribute("xlink:href");
// TODO: other attributes of <ServiceMetadataURL> element
},
- "LegendURL": function(node, obj) {
- obj.legend = {};
- obj.legend.href = node.getAttribute("xlink:href");
- obj.legend.format = node.getAttribute("format");
- },
"Dimension": function(node, obj) {
var dimension = {values: []};
this.readChildNodes(node, dimension);
obj.dimensions.push(dimension);
},
@@ -68189,11 +69955,11 @@
});
/* ======================================================================
OpenLayers/Layer/WorldWind.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -68298,11 +70064,11 @@
});
/* ======================================================================
OpenLayers/Popup/FramedCloud.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -68529,11 +70295,11 @@
});
/* ======================================================================
OpenLayers/Format/SOSCapabilities/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -68931,14 +70697,295 @@
CLASS_NAME: "OpenLayers.Handler.Pinch"
});
/* ======================================================================
+ OpenLayers/Format/WFST/v2_0_0.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/Format/WFST/v1.js
+ * @requires OpenLayers/Format/Filter/v2_0_0.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Format.WFST.v2_0_0
+ * A format for creating WFS v2.0.0 transactions. Create a new instance with the
+ * <OpenLayers.Format.WFST.v2_0_0> constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Format.Filter.v2_0_0>
+ * - <OpenLayers.Format.WFST.v1>
+ */
+OpenLayers.Format.WFST.v2_0_0 = OpenLayers.Class(
+ OpenLayers.Format.Filter.v2_0_0, OpenLayers.Format.WFST.v1, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance",
+ wfs: "http://www.opengis.net/wfs/2.0",
+ gml: "http://www.opengis.net/gml/3.2",
+ fes: "http://www.opengis.net/fes/2.0"
+ },
+
+ /**
+ * Property: version
+ * {String} WFS version number.
+ */
+ version: "2.0.0",
+
+ /**
+ * Property: schemaLocations
+ * {Object} Properties are namespace aliases, values are schema locations.
+ */
+ schemaLocations: {
+ "wfs": "http://schemas.opengis.net/wfs/2.0/wfs.xsd"
+ },
+
+ /**
+ * Constructor: OpenLayers.Format.WFST.v2_0_0
+ * A class for parsing and generating WFS v2.0.0 transactions.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will be set on the
+ * instance.
+ *
+ * Valid options properties:
+ * featureType - {String} Local (without prefix) feature typeNames (required).
+ * featureNS - {String} Feature namespace (optional).
+ * featurePrefix - {String} Feature namespace alias (optional - only used
+ * if featureNS is provided). Default is 'feature'.
+ * geometryName - {String} Name of geometry attribute. Default is 'the_geom'.
+ */
+ initialize: function(options) {
+ OpenLayers.Format.Filter.v2_0_0.prototype.initialize.apply(this, [options]);
+ OpenLayers.Format.WFST.v1.prototype.initialize.apply(this, [options]);
+ },
+
+ /**
+ * Method: readNode
+ * Shorthand for applying one of the named readers given the node
+ * namespace and local name. Readers take two args (node, obj) and
+ * generally extend or modify the second.
+ *
+ * Parameters:
+ * node - {DOMElement} The node to be read (required).
+ * obj - {Object} The object to be modified (optional).
+ * first - {Boolean} Should be set to true for the first node read. This
+ * is usually the readNode call in the read method. Without this being
+ * set, auto-configured properties will stick on subsequent reads.
+ *
+ * Returns:
+ * {Object} The input object, modified (or a new one if none was provided).
+ */
+ readNode: function(node, obj, first) {
+ // Not the superclass, only the mixin classes inherit from
+ // Format.GML.v2. We need this because we don't want to get readNode
+ // from the superclass's superclass, which is OpenLayers.Format.XML.
+ return OpenLayers.Format.GML.v3.prototype.readNode.apply(this, arguments);
+ },
+
+ /**
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
+ */
+ readers: {
+ "wfs": OpenLayers.Util.applyDefaults({
+ "FeatureCollection": function(node, obj) {
+ obj.numberReturned = parseInt(node.getAttribute(
+ "numberReturned"));
+ obj.numberMatched = parseInt(node.getAttribute(
+ "numberMatched"));
+ OpenLayers.Format.WFST.v1.prototype.readers["wfs"]["FeatureCollection"].apply(
+ this, arguments);
+ },
+ "TransactionResponse": function(node, obj) {
+ obj.insertIds = [];
+ obj.success = false;
+ this.readChildNodes(node, obj);
+ },
+ "TransactionSummary": function(node, obj) {
+ obj.success = true;
+ },
+ "InsertResults": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "Feature": function(node, container) {
+ var obj = {fids: []};
+ this.readChildNodes(node, obj);
+ container.insertIds.push(obj.fids[0]);
+ },
+ "member": function(node, obj) {
+ this.readChildNodes(node, obj);
+ },
+ "boundedBy": function(node, obj) {
+ var container = {};
+ this.readChildNodes(node, container);
+ if(container.components && container.components.length > 0) {
+ obj.bounds = container.components[0];
+ }
+ }
+
+ }, OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),
+ "gml": OpenLayers.Format.GML.v3.prototype.readers["gml"],
+ "feature": OpenLayers.Format.GML.v3.prototype.readers["feature"],
+ "ows": OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"],
+ "fes": OpenLayers.Format.Filter.v2_0_0.prototype.readers["fes"]
+ },
+
+ /**
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
+ */
+ writers: {
+ "wfs": OpenLayers.Util.applyDefaults({
+ "GetFeature": function(options) {
+ var node = OpenLayers.Format.WFST.v1.prototype.writers["wfs"]["GetFeature"].apply(this, arguments);
+ options && this.setAttributes(node, {
+ resultType: options.resultType,
+ startIndex: options.startIndex,
+ count: options.count
+ });
+ return node;
+ },
+ "Query": function(options) {
+ options = OpenLayers.Util.extend({
+ featureNS: this.featureNS,
+ featurePrefix: this.featurePrefix,
+ featureType: this.featureType,
+ srsName: this.srsName
+ }, options);
+ var prefix = options.featurePrefix;
+ var node = this.createElementNSPlus("wfs:Query", {
+ attributes: {
+ typeNames: (prefix ? prefix + ":" : "") +
+ options.featureType,
+ srsName: options.srsName
+ }
+ });
+ if(options.featureNS) {
+ node.setAttribute("xmlns:" + prefix, options.featureNS);
+ }
+ if(options.propertyNames) {
+ for(var i=0,len = options.propertyNames.length; i<len; i++) {
+ this.writeNode(
+ "wfs:PropertyName",
+ {property: options.propertyNames[i]},
+ node
+ );
+ }
+ }
+ if(options.filter) {
+ this.setFilterProperty(options.filter);
+ this.writeNode("fes:Filter", options.filter, node);
+ }
+ return node;
+ },
+ "Update": function(obj) {
+ var feature = obj.feature;
+ var options = obj.options;
+ var node = this.createElementNSPlus("wfs:Update", {
+ attributes: {
+ handle: options && options.handle,
+ typeName: (this.featureNS ? this.featurePrefix + ":" : "") +
+ this.featureType
+ }
+ });
+ if(this.featureNS) {
+ node.setAttribute("xmlns:" + this.featurePrefix, this.featureNS);
+ }
+
+ // add in geometry
+ var modified = feature.modified;
+ if (this.geometryName !== null && (!modified || modified.geometry !== undefined)) {
+ this.srsName = this.getSrsName(feature);
+ this.writeNode(
+ "Property", {name: this.geometryName, value: feature.geometry}, node
+ );
+ }
+
+ // add in attributes
+ for(var key in feature.attributes) {
+ if(feature.attributes[key] !== undefined &&
+ (!modified || !modified.attributes ||
+ (modified.attributes && (key in modified.attributes)))) {
+ this.writeNode(
+ "Property", {name: key, value: feature.attributes[key]}, node
+ );
+ }
+ }
+
+ // add feature id filter
+ this.writeNode("fes:Filter", new OpenLayers.Filter.FeatureId({
+ fids: [feature.fid]
+ }), node);
+
+ return node;
+ },
+ "Property": function(obj) {
+ var node = this.createElementNSPlus("wfs:Property");
+ this.writeNode("ValueReference", obj.name, node);
+ if(obj.value !== null) {
+ this.writeNode("Value", obj.value, node);
+ }
+ return node;
+ },
+ "PropertyName": function(obj) {
+ return this.createElementNSPlus("wfs:PropertyName", {
+ value: obj.property
+ });
+ },
+ "ValueReference": function(name) {
+ return this.createElementNSPlus("wfs:ValueReference", {value: name});
+ },
+ "Delete": function(obj) {
+ var feature = obj.feature;
+ var options = obj.options;
+ var node = this.createElementNSPlus("wfs:Delete", {
+ attributes: {
+ handle: options && options.handle,
+ typeName: (this.featureNS ? this.featurePrefix + ":" : "") +
+ this.featureType
+ }
+ });
+ if(this.featureNS) {
+ node.setAttribute("xmlns:" + this.featurePrefix, this.featureNS);
+ }
+ this.writeNode("fes:Filter", new OpenLayers.Filter.FeatureId({
+ fids: [feature.fid]
+ }), node);
+ return node;
+ }
+ }, OpenLayers.Format.WFST.v1.prototype.writers["wfs"]),
+ "gml": OpenLayers.Format.GML.v3.prototype.writers["gml"],
+ "feature": OpenLayers.Format.GML.v3.prototype.writers["feature"],
+ "fes": OpenLayers.Format.Filter.v2_0_0.prototype.writers["fes"]
+ },
+
+ CLASS_NAME: "OpenLayers.Format.WFST.v2_0_0"
+});
+/* ======================================================================
OpenLayers/Control/NavToolbar.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -68995,11 +71042,11 @@
});
/* ======================================================================
OpenLayers/Layer/OSM.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -69122,11 +71169,11 @@
});
/* ======================================================================
OpenLayers/Strategy/Refresh.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -69203,10 +71250,14 @@
*/
deactivate: function() {
var deactivated = OpenLayers.Strategy.prototype.deactivate.call(this);
if(deactivated) {
this.stop();
+ this.layer.events.un({
+ "visibilitychanged": this.reset,
+ scope: this
+ });
}
return deactivated;
},
/**
@@ -69260,204 +71311,493 @@
},
CLASS_NAME: "OpenLayers.Strategy.Refresh"
});
/* ======================================================================
- OpenLayers/Control/Geolocate.js
+ OpenLayers/Handler/Hover.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/Control.js
- * @requires OpenLayers/Geometry/Point.js
- * @requires OpenLayers/Projection.js
+ * @requires OpenLayers/Handler.js
*/
/**
- * Class: OpenLayers.Control.Geolocate
- * The Geolocate control wraps w3c geolocation API into control that can be
- * bound to a map, and generate events on location update
- *
- * To use this control requires to load the proj4js library if the projection
- * of the map is not EPSG:4326 or EPSG:900913.
- *
+ * Class: OpenLayers.Handler.Hover
+ * The hover handler is to be used to emulate mouseovers on objects
+ * on the map that aren't DOM elements. For example one can use
+ * this handler to send WMS/GetFeatureInfo requests as the user
+ * moves the mouve over the map.
+ *
* Inherits from:
- * - <OpenLayers.Control>
+ * - <OpenLayers.Handler>
*/
-OpenLayers.Control.Geolocate = OpenLayers.Class(OpenLayers.Control, {
+OpenLayers.Handler.Hover = OpenLayers.Class(OpenLayers.Handler, {
- /**
- * APIProperty: events
- * {<OpenLayers.Events>} Events instance for listeners and triggering
- * control specific events.
- *
- * Register a listener for a particular event with the following syntax:
- * (code)
- * control.events.register(type, obj, listener);
- * (end)
- *
- * Supported event types (in addition to those from <OpenLayers.Control.events>):
- * locationupdated - Triggered when browser return a new position. Listeners will
- * receive an object with a 'position' property which is the browser.geolocation.position
- * native object, as well as a 'point' property which is the location transformed in the
- * current map projection.
- * locationfailed - Triggered when geolocation has failed
- * locationuncapable - Triggered when control is activated on a browser
- * which doesn't support geolocation
+ /**
+ * APIProperty: delay
+ * {Integer} - Number of milliseconds between mousemoves before
+ * the event is considered a hover. Default is 500.
*/
-
+ delay: 500,
+
/**
- * Property: geolocation
- * {Object} The geolocation engine, as a property to be possibly mocked.
+ * APIProperty: pixelTolerance
+ * {Integer} - Maximum number of pixels between mousemoves for
+ * an event to be considered a hover. Default is null.
*/
- geolocation: navigator.geolocation,
+ pixelTolerance: null,
/**
- * APIProperty: bind
- * {Boolean} If true, map center will be set on location update.
+ * APIProperty: stopMove
+ * {Boolean} - Stop other listeners from being notified on mousemoves.
+ * Default is false.
*/
- bind: true,
+ stopMove: false,
/**
- * APIProperty: watch
- * {Boolean} If true, position will be update regularly.
+ * Property: px
+ * {<OpenLayers.Pixel>} - The location of the last mousemove, expressed
+ * in pixels.
*/
- watch: false,
+ px: null,
/**
- * APIProperty: geolocationOptions
- * {Object} Options to pass to the navigator's geolocation API. See
- * <http://dev.w3.org/geo/api/spec-source.html>. No specific
- * option is passed to the geolocation API by default.
+ * Property: timerId
+ * {Number} - The id of the timer.
*/
- geolocationOptions: null,
-
+ timerId: null,
+
/**
- * Constructor: OpenLayers.Control.Geolocate
- * Create a new control to deal with browser geolocation API
+ * Constructor: OpenLayers.Handler.Hover
+ * Construct a hover handler.
*
+ * Parameters:
+ * control - {<OpenLayers.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.
+ * callbacks - {Object} An object with keys corresponding to callbacks
+ * that will be called by the handler. The callbacks should
+ * expect to receive a single argument, the event. Callbacks for
+ * 'move', the mouse is moving, and 'pause', the mouse is pausing,
+ * are supported.
+ * options - {Object} An optional object whose properties will be set on
+ * the handler.
*/
/**
- * Method: destroy
+ * Method: mousemove
+ * Called when the mouse moves on the map.
+ *
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ *
+ * Returns:
+ * {Boolean} Continue propagating this event.
*/
- destroy: function() {
- this.deactivate();
- OpenLayers.Control.prototype.destroy.apply(this, arguments);
+ mousemove: function(evt) {
+ if(this.passesTolerance(evt.xy)) {
+ this.clearTimer();
+ this.callback('move', [evt]);
+ this.px = evt.xy;
+ // clone the evt so original properties can be accessed even
+ // if the browser deletes them during the delay
+ evt = OpenLayers.Util.extend({}, evt);
+ this.timerId = window.setTimeout(
+ OpenLayers.Function.bind(this.delayedCall, this, evt),
+ this.delay
+ );
+ }
+ return !this.stopMove;
},
/**
- * Method: activate
- * Activates the control.
+ * Method: mouseout
+ * Called when the mouse goes out of the map.
*
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ *
* Returns:
- * {Boolean} The control was effectively activated.
+ * {Boolean} Continue propagating this event.
*/
- activate: function () {
- if (!this.geolocation) {
- this.events.triggerEvent("locationuncapable");
- return false;
+ mouseout: function(evt) {
+ if (OpenLayers.Util.mouseLeft(evt, this.map.viewPortDiv)) {
+ this.clearTimer();
+ this.callback('move', [evt]);
}
- if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
- if (this.watch) {
- this.watchId = this.geolocation.watchPosition(
- OpenLayers.Function.bind(this.geolocate, this),
- OpenLayers.Function.bind(this.failure, this),
- this.geolocationOptions
- );
- } else {
- this.getCurrentLocation();
+ return true;
+ },
+
+ /**
+ * Method: passesTolerance
+ * Determine whether the mouse move is within the optional pixel tolerance.
+ *
+ * Parameters:
+ * px - {<OpenLayers.Pixel>}
+ *
+ * Returns:
+ * {Boolean} The mouse move is within the pixel tolerance.
+ */
+ passesTolerance: function(px) {
+ var passes = true;
+ if(this.pixelTolerance && this.px) {
+ var dpx = Math.sqrt(
+ Math.pow(this.px.x - px.x, 2) +
+ Math.pow(this.px.y - px.y, 2)
+ );
+ if(dpx < this.pixelTolerance) {
+ passes = false;
}
- return true;
}
- return false;
+ return passes;
},
/**
- * Method: deactivate
- * Deactivates the control.
+ * Method: clearTimer
+ * Clear the timer and set <timerId> to null.
+ */
+ clearTimer: function() {
+ if(this.timerId != null) {
+ window.clearTimeout(this.timerId);
+ this.timerId = null;
+ }
+ },
+
+ /**
+ * Method: delayedCall
+ * Triggers pause callback.
*
+ * Parameters:
+ * evt - {<OpenLayers.Event>}
+ */
+ delayedCall: function(evt) {
+ this.callback('pause', [evt]);
+ },
+
+ /**
+ * APIMethod: deactivate
+ * Deactivate the handler.
+ *
* Returns:
- * {Boolean} The control was effectively deactivated.
+ * {Boolean} The handler was successfully deactivated.
*/
- deactivate: function () {
- if (this.active && this.watchId !== null) {
- this.geolocation.clearWatch(this.watchId);
+ deactivate: function() {
+ var deactivated = false;
+ if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
+ this.clearTimer();
+ deactivated = true;
}
- return OpenLayers.Control.prototype.deactivate.apply(
- this, arguments
- );
+ return deactivated;
},
+ CLASS_NAME: "OpenLayers.Handler.Hover"
+});
+/* ======================================================================
+ OpenLayers/Control/ModifyFeature/BySegment.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.js
+ * @requires OpenLayers/Control/ModifyFeature.js
+ * @requires OpenLayers/Geometry.js
+ * @requires OpenLayers/Handler/Hover.js
+ */
+
+/**
+ * Class: OpenLayers.Control.ModifyFeature.BySegment
+ * A mixin for the ModifyFeature control to allow editing of large geometries
+ * by editing one segment at a time, the segment which is closest to the
+ * mouse cursor on hover.
+ *
+ * To use this is in combination with OpenLayers.Control.ModifyFeature include
+ * this file in your build and set bySegment to true on the ModifyFeature
+ * control. Also note this code depends on the rbush library which can be
+ * found at: https://github.com/mourner/rbush
+ */
+OpenLayers.Control.ModifyFeature.BySegment = {
+
/**
- * Method: geolocate
- * Activates the control.
+ * APIProperty: hoverTolerance
+ * {Integer} Number of pixels around the hover location to query the
+ * spatial index in order to find the closest segment. Defaults to 25.
+ */
+ hoverTolerance: 25,
+
+ /**
+ * Method: collectVertices
+ * Collect the vertices from the modifiable feature's geometry and push
+ * them on to the control's vertices array.
+ */
+ collectVertices: OpenLayers.Function.Void,
+
+ /**
+ * Method: setMap
+ * Set the map property for the control and all handlers.
*
+ * Parameters:
+ * map - {<OpenLayers.Map>} The control's map.
*/
- geolocate: function (position) {
- var center = new OpenLayers.LonLat(
- position.coords.longitude,
- position.coords.latitude
- ).transform(
- new OpenLayers.Projection("EPSG:4326"),
- this.map.getProjectionObject()
- );
- if (this.bind) {
- this.map.setCenter(center);
+ setMap: function(map) {
+ OpenLayers.Control.ModifyFeature.prototype.setMap.apply(this, arguments);
+ if (!this.handlers.hover) {
+ this.handlers.hover = new OpenLayers.Handler.Hover(this, {
+ move: this.onHoverMove
+ });
}
- this.events.triggerEvent("locationupdated", {
- position: position,
- point: new OpenLayers.Geometry.Point(
- center.lon, center.lat
- )
- });
+ this.handlers.hover.setMap(map);
+ this.layer.events.on({
+ beforefeaturemodified: this.createSpatialIndex,
+ afterfeaturemodified: this.deactivateHover,
+ scope: this
+ });
},
/**
- * APIMethod: getCurrentLocation
+ * Method: deactivateHover
+ * Deactivate the hover handler.
+ */
+ deactivateHover: function() {
+ this.handlers.hover.deactivate();
+ },
+
+ /**
+ * APIMethod: destroy
+ * Take care of things that are not handled in superclass.
+ */
+ destroy: function() {
+ if (this.layer) {
+ this.layer.events.un({
+ beforefeaturemodified: this.createSpatialIndex,
+ afterfeaturemodified: this.deactivateHover,
+ scope: this
+ });
+ }
+ OpenLayers.Control.ModifyFeature.prototype.destroy.apply(this, []);
+ },
+
+ /**
+ * Method: dragStart
+ * Called by the drag handler before a feature is dragged. This method is
+ * used to differentiate between points and vertices
+ * of higher order geometries.
*
- * Returns:
- * {Boolean} Returns true if a event will be fired (successfull
- * registration)
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>} The point or vertex about to be
+ * dragged.
*/
- getCurrentLocation: function() {
- if (!this.active || this.watch) {
- return false;
+ dragStart: function(feature) {
+ OpenLayers.Control.ModifyFeature.prototype.dragStart.apply(this, arguments);
+ this.vertexGeom = feature.geometry.clone();
+ if (this.handlers.drag.stopDown) {
+ this.handlers.hover.deactivate();
}
- this.geolocation.getCurrentPosition(
- OpenLayers.Function.bind(this.geolocate, this),
- OpenLayers.Function.bind(this.failure, this),
- this.geolocationOptions
- );
- return true;
},
/**
- * Method: failure
- * method called on browser's geolocation failure
+ * Method: dragComplete
+ * Called by the drag handler when the feature dragging is complete.
*
+ * Parameters:
+ * vertex - {<OpenLayers.Feature.Vector>} The vertex being dragged.
*/
- failure: function (error) {
- this.events.triggerEvent("locationfailed", {error: error});
+ dragComplete: function(vertex) {
+ this.updateSpatialIndex(vertex);
+ OpenLayers.Control.ModifyFeature.prototype.dragComplete.apply(this, arguments);
+ this.handlers.hover.activate();
},
- CLASS_NAME: "OpenLayers.Control.Geolocate"
-});
+ /**
+ * Method: onHoverMove
+ * Move listener of the hover handler. Draws the 2 vertices of the segment
+ * closest to the mouse cursor, and one virtual vertex in the center of the
+ * segment.
+ *
+ * Parameters:
+ * evt - {Object} The event object.
+ */
+ onHoverMove: function(evt) {
+ if(this.vertices.length > 0) {
+ this.layer.removeFeatures(this.vertices, {silent: true});
+ this.vertices = [];
+ }
+ if(this.virtualVertices.length > 0) {
+ this.layer.removeFeatures(this.virtualVertices, {silent: true});
+ this.virtualVertices = [];
+ }
+ var pixel = evt.xy;
+ var llPx = pixel.add(-this.hoverTolerance/2, this.hoverTolerance/2);
+ var urPx = pixel.add(this.hoverTolerance/2, -this.hoverTolerance/2);
+ var ll = this.map.getLonLatFromPixel(llPx);
+ var ur = this.map.getLonLatFromPixel(urPx);
+ var hits = this.tree.search([ll.lon, ll.lat, ur.lon, ur.lat]);
+ if (hits.length > 0) {
+ var center = this.map.getLonLatFromPixel(pixel);
+ var centerPt = new OpenLayers.Geometry.Point(center.lon, center.lat);
+ var d = Number.MAX_VALUE;
+ var closestHit;
+ for (var i=0, ii = hits.length; i<ii; ++i) {
+ var hit = hits[i];
+ var distance = OpenLayers.Geometry.distanceSquaredToSegment(centerPt, {
+ x1: hit.point1.x,
+ x2: hit.point2.x,
+ y1: hit.point1.y,
+ y2: hit.point2.y
+ }).distance;
+ if (distance < d) {
+ closestHit = hit;
+ }
+ d = distance;
+ }
+ var createVertex = function(geom) {
+ var vertex = new OpenLayers.Feature.Vector(geom);
+ vertex._sketch = true;
+ vertex.renderIntent = this.vertexRenderIntent;
+ this.vertices.push(vertex);
+ };
+ createVertex.call(this, closestHit.point1);
+ createVertex.call(this, closestHit.point2);
+ // create virtual vertex
+ var point = this.createVirtualVertex(closestHit.point1, closestHit.point2);
+ point._previous = closestHit.point1;
+ point._next = closestHit.point2;
+ point._index = -1;
+ point.geometry.parent = closestHit.point1.parent;
+ this.virtualVertices.push(point);
+ }
+ this.layer.addFeatures(this.vertices, {silent: true});
+ this.layer.addFeatures(this.virtualVertices, {silent: true});
+ },
+
+ /**
+ * Method: createSpatialIndex
+ * Creates a spatial index for all the segments of the feature's geometry.
+ *
+ * Parameters:
+ * evt - {Object} The event object.
+ */
+ createSpatialIndex: function(evt) {
+ var feature = evt.feature;
+ var data = [];
+ function collectComponentVertices(geometry) {
+ var i, vertex, component, nextComponent, len;
+ if (geometry.CLASS_NAME !== "OpenLayers.Geometry.Point") {
+ var numVert = geometry.components.length;
+ if (geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
+ numVert -= 1;
+ }
+ nextComponent = geometry.components[0];
+ for (i=1; i<=numVert; ++i) {
+ component = nextComponent;
+ nextComponent = geometry.components[i];
+ if (component.CLASS_NAME == "OpenLayers.Geometry.Point") {
+ var bbox = this.createBBOX(component, nextComponent);
+ bbox.point1 = component;
+ bbox.point2 = nextComponent;
+ data.push(bbox);
+ } else {
+ collectComponentVertices.call(this, component);
+ }
+ }
+ }
+ }
+ collectComponentVertices.call(this, feature.geometry);
+ this.tree = window.rbush();
+ this.tree.load(data);
+ this.handlers.hover.activate();
+ },
+
+ /**
+ * Method: createBBOX
+ * Create an array of 4 points (minx, miny, maxx, maxy) that represents the
+ * bounding box of the 2 provided points.
+ *
+ * Parameters:
+ * point1 - {<OpenLayers.Geometry.Point>} The first point.
+ * point2 - {<OpenLayers.Geometry.Point>} The second point.
+ *
+ * Returns: {Array(float)}
+ */
+ createBBOX: function(point1, point2) {
+ return [
+ point1.x < point2.x ? point1.x : point2.x,
+ point1.y < point2.y ? point1.y : point2.y,
+ point1.x < point2.x ? point2.x : point1.x,
+ point1.y < point2.y ? point2.y : point1.y
+ ];
+ },
+
+ /**
+ * Method: updateSpatialIndex
+ * Update the spatial index after a (virtual) vertex gets moved.
+ *
+ * Parameters:
+ * vertex - {<OpenLayers.Feature.Vector>}
+ */
+ updateSpatialIndex: function(vertex) {
+ // this.vertexGeom is the original location of the vertex
+ var hits = this.tree.search([
+ this.vertexGeom.x,
+ this.vertexGeom.y,
+ this.vertexGeom.x,
+ this.vertexGeom.y
+ ]);
+ var bbox, i, ii;
+ // virtual vertex
+ if (vertex._previous) {
+ // split segment into 2 and add them to spatial index
+ bbox = this.createBBOX(vertex._previous, vertex.geometry);
+ bbox.point1 = vertex._previous;
+ bbox.point2 = vertex.geometry;
+ this.tree.insert(bbox);
+ bbox = this.createBBOX(vertex.geometry, vertex._next);
+ bbox.point1 = vertex.geometry;
+ bbox.point2 = vertex._next;
+ this.tree.insert(bbox);
+ this.tree.remove(hits[0]);
+ delete vertex._next;
+ delete vertex._previous;
+ } else { // normal vertex
+ for (i=0, ii=hits.length; i<ii; ++i) {
+ var hit = hits[i];
+ if (this.vertexGeom.equals(hit.point1)) {
+ bbox = this.createBBOX(vertex.geometry, hit.point2);
+ bbox.point1 = vertex.geometry;
+ bbox.point2 = hit.point2;
+ } else {
+ bbox = this.createBBOX(vertex.geometry, hit.point1);
+ bbox.point1 = hit.point1;
+ bbox.point2 = vertex.geometry;
+ }
+ this.tree.insert(bbox);
+ this.tree.remove(hit);
+ }
+ }
+ this.vertexGeom.destroy();
+ this.vertexGeom = null;
+ }
+
+};
/* ======================================================================
OpenLayers/Layer/ArcGIS93Rest.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Layer/Grid.js
*/
/**
@@ -69584,11 +71924,11 @@
// ArcGIS Server only wants the numeric portion of the projection ID.
var projWords = this.projection.getCode().split(":");
var srid = projWords[projWords.length - 1];
- var imageSize = this.getImageSize();
+ var imageSize = this.getImageSize(bounds);
var newParams = {
'BBOX': bounds.toBBOX(),
'SIZE': imageSize.w + "," + imageSize.h,
// We always want image, the other options were json, image with a whole lotta html around it, etc.
'F': "image",
@@ -69675,198 +72015,14 @@
},
CLASS_NAME: "OpenLayers.Layer.ArcGIS93Rest"
});
/* ======================================================================
- OpenLayers/Handler/Hover.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/Handler.js
- */
-
-/**
- * Class: OpenLayers.Handler.Hover
- * The hover handler is to be used to emulate mouseovers on objects
- * on the map that aren't DOM elements. For example one can use
- * this handler to send WMS/GetFeatureInfo requests as the user
- * moves the mouve over the map.
- *
- * Inherits from:
- * - <OpenLayers.Handler>
- */
-OpenLayers.Handler.Hover = OpenLayers.Class(OpenLayers.Handler, {
-
- /**
- * APIProperty: delay
- * {Integer} - Number of milliseconds between mousemoves before
- * the event is considered a hover. Default is 500.
- */
- delay: 500,
-
- /**
- * APIProperty: pixelTolerance
- * {Integer} - Maximum number of pixels between mousemoves for
- * an event to be considered a hover. Default is null.
- */
- pixelTolerance: null,
-
- /**
- * APIProperty: stopMove
- * {Boolean} - Stop other listeners from being notified on mousemoves.
- * Default is false.
- */
- stopMove: false,
-
- /**
- * Property: px
- * {<OpenLayers.Pixel>} - The location of the last mousemove, expressed
- * in pixels.
- */
- px: null,
-
- /**
- * Property: timerId
- * {Number} - The id of the timer.
- */
- timerId: null,
-
- /**
- * Constructor: OpenLayers.Handler.Hover
- * Construct a hover handler.
- *
- * Parameters:
- * control - {<OpenLayers.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.
- * callbacks - {Object} An object with keys corresponding to callbacks
- * that will be called by the handler. The callbacks should
- * expect to receive a single argument, the event. Callbacks for
- * 'move', the mouse is moving, and 'pause', the mouse is pausing,
- * are supported.
- * options - {Object} An optional object whose properties will be set on
- * the handler.
- */
-
- /**
- * Method: mousemove
- * Called when the mouse moves on the map.
- *
- * Parameters:
- * evt - {<OpenLayers.Event>}
- *
- * Returns:
- * {Boolean} Continue propagating this event.
- */
- mousemove: function(evt) {
- if(this.passesTolerance(evt.xy)) {
- this.clearTimer();
- this.callback('move', [evt]);
- this.px = evt.xy;
- // clone the evt so original properties can be accessed even
- // if the browser deletes them during the delay
- evt = OpenLayers.Util.extend({}, evt);
- this.timerId = window.setTimeout(
- OpenLayers.Function.bind(this.delayedCall, this, evt),
- this.delay
- );
- }
- return !this.stopMove;
- },
-
- /**
- * Method: mouseout
- * Called when the mouse goes out of the map.
- *
- * Parameters:
- * evt - {<OpenLayers.Event>}
- *
- * Returns:
- * {Boolean} Continue propagating this event.
- */
- mouseout: function(evt) {
- if (OpenLayers.Util.mouseLeft(evt, this.map.viewPortDiv)) {
- this.clearTimer();
- this.callback('move', [evt]);
- }
- return true;
- },
-
- /**
- * Method: passesTolerance
- * Determine whether the mouse move is within the optional pixel tolerance.
- *
- * Parameters:
- * px - {<OpenLayers.Pixel>}
- *
- * Returns:
- * {Boolean} The mouse move is within the pixel tolerance.
- */
- passesTolerance: function(px) {
- var passes = true;
- if(this.pixelTolerance && this.px) {
- var dpx = Math.sqrt(
- Math.pow(this.px.x - px.x, 2) +
- Math.pow(this.px.y - px.y, 2)
- );
- if(dpx < this.pixelTolerance) {
- passes = false;
- }
- }
- return passes;
- },
-
- /**
- * Method: clearTimer
- * Clear the timer and set <timerId> to null.
- */
- clearTimer: function() {
- if(this.timerId != null) {
- window.clearTimeout(this.timerId);
- this.timerId = null;
- }
- },
-
- /**
- * Method: delayedCall
- * Triggers pause callback.
- *
- * Parameters:
- * evt - {<OpenLayers.Event>}
- */
- delayedCall: function(evt) {
- this.callback('pause', [evt]);
- },
-
- /**
- * APIMethod: deactivate
- * Deactivate the handler.
- *
- * Returns:
- * {Boolean} The handler was successfully deactivated.
- */
- deactivate: function() {
- var deactivated = false;
- if(OpenLayers.Handler.prototype.deactivate.apply(this, arguments)) {
- this.clearTimer();
- deactivated = true;
- }
- return deactivated;
- },
-
- CLASS_NAME: "OpenLayers.Handler.Hover"
-});
-/* ======================================================================
OpenLayers/Control/GetFeature.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -70463,11 +72619,11 @@
});
/* ======================================================================
OpenLayers/Format/QueryStringFilter.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -70650,11 +72806,11 @@
})();
/* ======================================================================
OpenLayers/Format/WCSCapabilities/v1_1_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -70753,11 +72909,23 @@
}
coverageSummary.supportedFormat.push(format);
}
}
}, OpenLayers.Format.WCSCapabilities.v1.prototype.readers["wcs"]),
- "ows": OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]
+ "ows": OpenLayers.Util.applyDefaults({
+ // ows puts keywords in a dictionary, which doesn't make a
+ // lot of sense in this context; we just want a list, so we'll
+ // override this aspect of the ows parsing.
+ "Keywords": function(node, serviceIdentification) {
+ serviceIdentification.keywords = [];
+ this.readChildNodes(node, serviceIdentification.keywords);
+ },
+ "Keyword": function(node, keywords) {
+ // Append the keyword to the keywords list
+ keywords.push(this.getChildValue(node));
+ }
+ }, OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"])
},
CLASS_NAME: "OpenLayers.Format.WCSCapabilities.v1_1_0"
});
@@ -70991,14 +73159,210 @@
},
CLASS_NAME: "OpenLayers.Control.MousePosition"
});
/* ======================================================================
+ OpenLayers/Control/Geolocate.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/Control.js
+ * @requires OpenLayers/Geometry/Point.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**
+ * Class: OpenLayers.Control.Geolocate
+ * The Geolocate control wraps w3c geolocation API into control that can be
+ * bound to a map, and generate events on location update
+ *
+ * To use this control requires to load the proj4js library if the projection
+ * of the map is not EPSG:4326 or EPSG:900913.
+ *
+ * Inherits from:
+ * - <OpenLayers.Control>
+ */
+OpenLayers.Control.Geolocate = OpenLayers.Class(OpenLayers.Control, {
+
+ /**
+ * APIProperty: events
+ * {<OpenLayers.Events>} Events instance for listeners and triggering
+ * control specific events.
+ *
+ * Register a listener for a particular event with the following syntax:
+ * (code)
+ * control.events.register(type, obj, listener);
+ * (end)
+ *
+ * Supported event types (in addition to those from <OpenLayers.Control.events>):
+ * locationupdated - Triggered when browser return a new position. Listeners will
+ * receive an object with a 'position' property which is the browser.geolocation.position
+ * native object, as well as a 'point' property which is the location transformed in the
+ * current map projection.
+ * locationfailed - Triggered when geolocation has failed
+ * locationuncapable - Triggered when control is activated on a browser
+ * which doesn't support geolocation
+ */
+
+ /**
+ * Property: geolocation
+ * {Object} The geolocation engine, as a property to be possibly mocked.
+ * This is set lazily to avoid a memory leak in IE9.
+ */
+ geolocation: null,
+
+ /**
+ * Property: available
+ * {Boolean} The navigator.geolocation object is available.
+ */
+ available: ('geolocation' in navigator),
+
+ /**
+ * APIProperty: bind
+ * {Boolean} If true, map center will be set on location update.
+ */
+ bind: true,
+
+ /**
+ * APIProperty: watch
+ * {Boolean} If true, position will be update regularly.
+ */
+ watch: false,
+
+ /**
+ * APIProperty: geolocationOptions
+ * {Object} Options to pass to the navigator's geolocation API. See
+ * <http://dev.w3.org/geo/api/spec-source.html>. No specific
+ * option is passed to the geolocation API by default.
+ */
+ geolocationOptions: null,
+
+ /**
+ * Constructor: OpenLayers.Control.Geolocate
+ * Create a new control to deal with browser geolocation API
+ *
+ */
+
+ /**
+ * Method: destroy
+ */
+ destroy: function() {
+ this.deactivate();
+ OpenLayers.Control.prototype.destroy.apply(this, arguments);
+ },
+
+ /**
+ * Method: activate
+ * Activates the control.
+ *
+ * Returns:
+ * {Boolean} The control was effectively activated.
+ */
+ activate: function () {
+ if (this.available && !this.geolocation) {
+ // set lazily to avoid IE9 memory leak
+ this.geolocation = navigator.geolocation;
+ }
+ if (!this.geolocation) {
+ this.events.triggerEvent("locationuncapable");
+ return false;
+ }
+ if (OpenLayers.Control.prototype.activate.apply(this, arguments)) {
+ if (this.watch) {
+ this.watchId = this.geolocation.watchPosition(
+ OpenLayers.Function.bind(this.geolocate, this),
+ OpenLayers.Function.bind(this.failure, this),
+ this.geolocationOptions
+ );
+ } else {
+ this.getCurrentLocation();
+ }
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Method: deactivate
+ * Deactivates the control.
+ *
+ * Returns:
+ * {Boolean} The control was effectively deactivated.
+ */
+ deactivate: function () {
+ if (this.active && this.watchId !== null) {
+ this.geolocation.clearWatch(this.watchId);
+ }
+ return OpenLayers.Control.prototype.deactivate.apply(
+ this, arguments
+ );
+ },
+
+ /**
+ * Method: geolocate
+ * Activates the control.
+ *
+ */
+ geolocate: function (position) {
+ var center = new OpenLayers.LonLat(
+ position.coords.longitude,
+ position.coords.latitude
+ ).transform(
+ new OpenLayers.Projection("EPSG:4326"),
+ this.map.getProjectionObject()
+ );
+ if (this.bind) {
+ this.map.setCenter(center);
+ }
+ this.events.triggerEvent("locationupdated", {
+ position: position,
+ point: new OpenLayers.Geometry.Point(
+ center.lon, center.lat
+ )
+ });
+ },
+
+ /**
+ * APIMethod: getCurrentLocation
+ *
+ * Returns:
+ * {Boolean} Returns true if a event will be fired (successfull
+ * registration)
+ */
+ getCurrentLocation: function() {
+ if (!this.active || this.watch) {
+ return false;
+ }
+ this.geolocation.getCurrentPosition(
+ OpenLayers.Function.bind(this.geolocate, this),
+ OpenLayers.Function.bind(this.failure, this),
+ this.geolocationOptions
+ );
+ return true;
+ },
+
+ /**
+ * Method: failure
+ * method called on browser's geolocation failure
+ *
+ */
+ failure: function (error) {
+ this.events.triggerEvent("locationfailed", {error: error});
+ },
+
+ CLASS_NAME: "OpenLayers.Control.Geolocate"
+});
+/* ======================================================================
OpenLayers/Tile/UTFGrid.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -71250,11 +73614,11 @@
});
/* ======================================================================
OpenLayers/Control/NavigationHistory.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -71674,598 +74038,62 @@
CLASS_NAME: "OpenLayers.Control.NavigationHistory"
});
/* ======================================================================
- OpenLayers/Protocol/HTTP.js
+ OpenLayers/Protocol/WFS/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Protocol.js
- * @requires OpenLayers/Request/XMLHttpRequest.js
+ * @requires OpenLayers/Protocol/WFS/v1.js
+ * @requires OpenLayers/Format/WFST/v1_0_0.js
*/
/**
- * if application uses the query string, for example, for BBOX parameters,
- * OpenLayers/Format/QueryStringFilter.js should be included in the build config file
- */
-
-/**
- * Class: OpenLayers.Protocol.HTTP
- * A basic HTTP protocol for vector layers. Create a new instance with the
- * <OpenLayers.Protocol.HTTP> constructor.
+ * Class: OpenLayers.Protocol.WFS.v1_0_0
+ * A WFS v1.0.0 protocol for vector layers. Create a new instance with the
+ * <OpenLayers.Protocol.WFS.v1_0_0> constructor.
*
* Inherits from:
- * - <OpenLayers.Protocol>
+ * - <OpenLayers.Protocol.WFS.v1>
*/
-OpenLayers.Protocol.HTTP = OpenLayers.Class(OpenLayers.Protocol, {
-
- /**
- * Property: url
- * {String} Service URL, read-only, set through the options
- * passed to constructor.
- */
- url: null,
-
- /**
- * Property: headers
- * {Object} HTTP request headers, read-only, set through the options
- * passed to the constructor,
- * Example: {'Content-Type': 'plain/text'}
- */
- headers: null,
-
- /**
- * Property: params
- * {Object} Parameters of GET requests, read-only, set through the options
- * passed to the constructor,
- * Example: {'bbox': '5,5,5,5'}
- */
- params: null,
+OpenLayers.Protocol.WFS.v1_0_0 = OpenLayers.Class(OpenLayers.Protocol.WFS.v1, {
/**
- * Property: callback
- * {Object} Function to be called when the <read>, <create>,
- * <update>, <delete> or <commit> operation completes, read-only,
- * set through the options passed to the constructor.
+ * Property: version
+ * {String} WFS version number.
*/
- callback: null,
-
- /**
- * Property: scope
- * {Object} Callback execution scope, read-only, set through the
- * options passed to the constructor.
- */
- scope: null,
-
- /**
- * APIProperty: readWithPOST
- * {Boolean} true if read operations are done with POST requests
- * instead of GET, defaults to false.
- */
- readWithPOST: false,
-
- /**
- * APIProperty: updateWithPOST
- * {Boolean} true if update operations are done with POST requests
- * defaults to false.
- */
- updateWithPOST: false,
+ version: "1.0.0",
/**
- * APIProperty: deleteWithPOST
- * {Boolean} true if delete operations are done with POST requests
- * defaults to false.
- * if true, POST data is set to output of format.write().
- */
- deleteWithPOST: false,
-
- /**
- * Property: wildcarded.
- * {Boolean} If true percent signs are added around values
- * read from LIKE filters, for example if the protocol
- * read method is passed a LIKE filter whose property
- * is "foo" and whose value is "bar" the string
- * "foo__ilike=%bar%" will be sent in the query string;
- * defaults to false.
- */
- wildcarded: false,
-
- /**
- * APIProperty: srsInBBOX
- * {Boolean} Include the SRS identifier in BBOX query string parameter.
- * Default is false. If true and the layer has a projection object set,
- * any BBOX filter will be serialized with a fifth item identifying the
- * projection. E.g. bbox=-1000,-1000,1000,1000,EPSG:900913
- */
- srsInBBOX: false,
-
- /**
- * Constructor: OpenLayers.Protocol.HTTP
- * A class for giving layers generic HTTP protocol.
+ * Constructor: OpenLayers.Protocol.WFS.v1_0_0
+ * A class for giving layers WFS v1.0.0 protocol.
*
* Parameters:
* options - {Object} Optional object whose properties will be set on the
* instance.
*
- * Valid options include:
- * url - {String}
- * headers - {Object}
- * params - {Object} URL parameters for GET requests
- * format - {<OpenLayers.Format>}
- * callback - {Function}
- * scope - {Object}
+ * Valid options properties:
+ * featureType - {String} Local (without prefix) feature typeName (required).
+ * featureNS - {String} Feature namespace (optional).
+ * featurePrefix - {String} Feature namespace alias (optional - only used
+ * if featureNS is provided). Default is 'feature'.
+ * geometryName - {String} Name of geometry attribute. Default is 'the_geom'.
*/
- initialize: function(options) {
- options = options || {};
- this.params = {};
- this.headers = {};
- OpenLayers.Protocol.prototype.initialize.apply(this, arguments);
-
- if (!this.filterToParams && OpenLayers.Format.QueryStringFilter) {
- var format = new OpenLayers.Format.QueryStringFilter({
- wildcarded: this.wildcarded,
- srsInBBOX: this.srsInBBOX
- });
- this.filterToParams = function(filter, params) {
- return format.write(filter, params);
- };
- }
- },
-
- /**
- * APIMethod: destroy
- * Clean up the protocol.
- */
- destroy: function() {
- this.params = null;
- this.headers = null;
- OpenLayers.Protocol.prototype.destroy.apply(this);
- },
-
- /**
- * APIMethod: filterToParams
- * Optional method to translate an <OpenLayers.Filter> object into an object
- * that can be serialized as request query string provided. If a custom
- * method is not provided, the filter will be serialized using the
- * <OpenLayers.Format.QueryStringFilter> class.
- *
- * Parameters:
- * filter - {<OpenLayers.Filter>} filter to convert.
- * params - {Object} The parameters object.
- *
- * Returns:
- * {Object} The resulting parameters object.
- */
-
- /**
- * APIMethod: read
- * Construct a request for reading new features.
- *
- * Parameters:
- * options - {Object} Optional object for configuring the request.
- * This object is modified and should not be reused.
- *
- * Valid options:
- * url - {String} Url for the request.
- * params - {Object} Parameters to get serialized as a query string.
- * headers - {Object} Headers to be set on the request.
- * filter - {<OpenLayers.Filter>} Filter to get serialized as a
- * query string.
- * readWithPOST - {Boolean} If the request should be done with POST.
- *
- * Returns:
- * {<OpenLayers.Protocol.Response>} A response object, whose "priv" property
- * references the HTTP request, this object is also passed to the
- * callback function when the request completes, its "features" property
- * is then populated with the features received from the server.
- */
- read: function(options) {
- OpenLayers.Protocol.prototype.read.apply(this, arguments);
- options = options || {};
- options.params = OpenLayers.Util.applyDefaults(
- options.params, this.options.params);
- options = OpenLayers.Util.applyDefaults(options, this.options);
- if (options.filter && this.filterToParams) {
- options.params = this.filterToParams(
- options.filter, options.params
- );
- }
- var readWithPOST = (options.readWithPOST !== undefined) ?
- options.readWithPOST : this.readWithPOST;
- var resp = new OpenLayers.Protocol.Response({requestType: "read"});
- if(readWithPOST) {
- var headers = options.headers || {};
- headers["Content-Type"] = "application/x-www-form-urlencoded";
- resp.priv = OpenLayers.Request.POST({
- url: options.url,
- callback: this.createCallback(this.handleRead, resp, options),
- data: OpenLayers.Util.getParameterString(options.params),
- headers: headers
- });
- } else {
- resp.priv = OpenLayers.Request.GET({
- url: options.url,
- callback: this.createCallback(this.handleRead, resp, options),
- params: options.params,
- headers: options.headers
- });
- }
- return resp;
- },
-
- /**
- * Method: handleRead
- * Individual callbacks are created for read, create and update, should
- * a subclass need to override each one separately.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
- * the user callback.
- * options - {Object} The user options passed to the read call.
- */
- handleRead: function(resp, options) {
- this.handleResponse(resp, options);
- },
-
- /**
- * APIMethod: create
- * Construct a request for writing newly created features.
- *
- * Parameters:
- * features - {Array({<OpenLayers.Feature.Vector>})} or
- * {<OpenLayers.Feature.Vector>}
- * options - {Object} Optional object for configuring the request.
- * This object is modified and should not be reused.
- *
- * Returns:
- * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
- * object, whose "priv" property references the HTTP request, this
- * object is also passed to the callback function when the request
- * completes, its "features" property is then populated with the
- * the features received from the server.
- */
- create: function(features, options) {
- options = OpenLayers.Util.applyDefaults(options, this.options);
-
- var resp = new OpenLayers.Protocol.Response({
- reqFeatures: features,
- requestType: "create"
- });
-
- resp.priv = OpenLayers.Request.POST({
- url: options.url,
- callback: this.createCallback(this.handleCreate, resp, options),
- headers: options.headers,
- data: this.format.write(features)
- });
-
- return resp;
- },
-
- /**
- * Method: handleCreate
- * Called the the request issued by <create> is complete. May be overridden
- * by subclasses.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
- * any user callback.
- * options - {Object} The user options passed to the create call.
- */
- handleCreate: function(resp, options) {
- this.handleResponse(resp, options);
- },
-
- /**
- * APIMethod: update
- * Construct a request updating modified feature.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- * options - {Object} Optional object for configuring the request.
- * This object is modified and should not be reused.
- *
- * Returns:
- * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
- * object, whose "priv" property references the HTTP request, this
- * object is also passed to the callback function when the request
- * completes, its "features" property is then populated with the
- * the feature received from the server.
- */
- update: function(feature, options) {
- options = options || {};
- var url = options.url ||
- feature.url ||
- this.options.url + "/" + feature.fid;
- options = OpenLayers.Util.applyDefaults(options, this.options);
-
- var resp = new OpenLayers.Protocol.Response({
- reqFeatures: feature,
- requestType: "update"
- });
-
- var method = this.updateWithPOST ? "POST" : "PUT";
- resp.priv = OpenLayers.Request[method]({
- url: url,
- callback: this.createCallback(this.handleUpdate, resp, options),
- headers: options.headers,
- data: this.format.write(feature)
- });
-
- return resp;
- },
-
- /**
- * Method: handleUpdate
- * Called the the request issued by <update> is complete. May be overridden
- * by subclasses.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
- * any user callback.
- * options - {Object} The user options passed to the update call.
- */
- handleUpdate: function(resp, options) {
- this.handleResponse(resp, options);
- },
-
- /**
- * APIMethod: delete
- * Construct a request deleting a removed feature.
- *
- * Parameters:
- * feature - {<OpenLayers.Feature.Vector>}
- * options - {Object} Optional object for configuring the request.
- * This object is modified and should not be reused.
- *
- * Returns:
- * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
- * object, whose "priv" property references the HTTP request, this
- * object is also passed to the callback function when the request
- * completes.
- */
- "delete": function(feature, options) {
- options = options || {};
- var url = options.url ||
- feature.url ||
- this.options.url + "/" + feature.fid;
- options = OpenLayers.Util.applyDefaults(options, this.options);
-
- var resp = new OpenLayers.Protocol.Response({
- reqFeatures: feature,
- requestType: "delete"
- });
-
- var method = this.deleteWithPOST ? "POST" : "DELETE";
- var requestOptions = {
- url: url,
- callback: this.createCallback(this.handleDelete, resp, options),
- headers: options.headers
- };
- if (this.deleteWithPOST) {
- requestOptions.data = this.format.write(feature);
- }
- resp.priv = OpenLayers.Request[method](requestOptions);
-
- return resp;
- },
-
- /**
- * Method: handleDelete
- * Called the the request issued by <delete> is complete. May be overridden
- * by subclasses.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
- * any user callback.
- * options - {Object} The user options passed to the delete call.
- */
- handleDelete: function(resp, options) {
- this.handleResponse(resp, options);
- },
-
- /**
- * Method: handleResponse
- * Called by CRUD specific handlers.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
- * any user callback.
- * options - {Object} The user options passed to the create, read, update,
- * or delete call.
- */
- handleResponse: function(resp, options) {
- var request = resp.priv;
- if(options.callback) {
- if(request.status >= 200 && request.status < 300) {
- // success
- if(resp.requestType != "delete") {
- resp.features = this.parseFeatures(request);
- }
- resp.code = OpenLayers.Protocol.Response.SUCCESS;
- } else {
- // failure
- resp.code = OpenLayers.Protocol.Response.FAILURE;
- }
- options.callback.call(options.scope, resp);
- }
- },
-
- /**
- * Method: parseFeatures
- * Read HTTP response body and return features.
- *
- * Parameters:
- * request - {XMLHttpRequest} The request object
- *
- * Returns:
- * {Array({<OpenLayers.Feature.Vector>})} or
- * {<OpenLayers.Feature.Vector>} Array of features or a single feature.
- */
- parseFeatures: function(request) {
- var doc = request.responseXML;
- if (!doc || !doc.documentElement) {
- doc = request.responseText;
- }
- if (!doc || doc.length <= 0) {
- return null;
- }
- return this.format.read(doc);
- },
-
- /**
- * APIMethod: commit
- * Iterate over each feature and take action based on the feature state.
- * Possible actions are create, update and delete.
- *
- * Parameters:
- * features - {Array({<OpenLayers.Feature.Vector>})}
- * options - {Object} Optional object for setting up intermediate commit
- * callbacks.
- *
- * Valid options:
- * create - {Object} Optional object to be passed to the <create> method.
- * update - {Object} Optional object to be passed to the <update> method.
- * delete - {Object} Optional object to be passed to the <delete> method.
- * callback - {Function} Optional function to be called when the commit
- * is complete.
- * scope - {Object} Optional object to be set as the scope of the callback.
- *
- * Returns:
- * {Array(<OpenLayers.Protocol.Response>)} An array of response objects,
- * one per request made to the server, each object's "priv" property
- * references the corresponding HTTP request.
- */
- commit: function(features, options) {
- options = OpenLayers.Util.applyDefaults(options, this.options);
- var resp = [], nResponses = 0;
-
- // Divide up features before issuing any requests. This properly
- // counts requests in the event that any responses come in before
- // all requests have been issued.
- var types = {};
- types[OpenLayers.State.INSERT] = [];
- types[OpenLayers.State.UPDATE] = [];
- types[OpenLayers.State.DELETE] = [];
- var feature, list, requestFeatures = [];
- for(var i=0, len=features.length; i<len; ++i) {
- feature = features[i];
- list = types[feature.state];
- if(list) {
- list.push(feature);
- requestFeatures.push(feature);
- }
- }
- // tally up number of requests
- var nRequests = (types[OpenLayers.State.INSERT].length > 0 ? 1 : 0) +
- types[OpenLayers.State.UPDATE].length +
- types[OpenLayers.State.DELETE].length;
-
- // This response will be sent to the final callback after all the others
- // have been fired.
- var success = true;
- var finalResponse = new OpenLayers.Protocol.Response({
- reqFeatures: requestFeatures
- });
-
- function insertCallback(response) {
- var len = response.features ? response.features.length : 0;
- var fids = new Array(len);
- for(var i=0; i<len; ++i) {
- fids[i] = response.features[i].fid;
- }
- finalResponse.insertIds = fids;
- callback.apply(this, [response]);
- }
-
- function callback(response) {
- this.callUserCallback(response, options);
- success = success && response.success();
- nResponses++;
- if (nResponses >= nRequests) {
- if (options.callback) {
- finalResponse.code = success ?
- OpenLayers.Protocol.Response.SUCCESS :
- OpenLayers.Protocol.Response.FAILURE;
- options.callback.apply(options.scope, [finalResponse]);
- }
- }
- }
-
- // start issuing requests
- var queue = types[OpenLayers.State.INSERT];
- if(queue.length > 0) {
- resp.push(this.create(
- queue, OpenLayers.Util.applyDefaults(
- {callback: insertCallback, scope: this}, options.create
- )
- ));
- }
- queue = types[OpenLayers.State.UPDATE];
- for(var i=queue.length-1; i>=0; --i) {
- resp.push(this.update(
- queue[i], OpenLayers.Util.applyDefaults(
- {callback: callback, scope: this}, options.update
- ))
- );
- }
- queue = types[OpenLayers.State.DELETE];
- for(var i=queue.length-1; i>=0; --i) {
- resp.push(this["delete"](
- queue[i], OpenLayers.Util.applyDefaults(
- {callback: callback, scope: this}, options["delete"]
- ))
- );
- }
- return resp;
- },
-
- /**
- * APIMethod: abort
- * Abort an ongoing request, the response object passed to
- * this method must come from this HTTP protocol (as a result
- * of a create, read, update, delete or commit operation).
- *
- * Parameters:
- * response - {<OpenLayers.Protocol.Response>}
- */
- abort: function(response) {
- if (response) {
- response.priv.abort();
- }
- },
-
- /**
- * Method: callUserCallback
- * This method is used from within the commit method each time an
- * an HTTP response is received from the server, it is responsible
- * for calling the user-supplied callbacks.
- *
- * Parameters:
- * resp - {<OpenLayers.Protocol.Response>}
- * options - {Object} The map of options passed to the commit call.
- */
- callUserCallback: function(resp, options) {
- var opt = options[resp.requestType];
- if(opt && opt.callback) {
- opt.callback.call(opt.scope, resp);
- }
- },
-
- CLASS_NAME: "OpenLayers.Protocol.HTTP"
+
+ CLASS_NAME: "OpenLayers.Protocol.WFS.v1_0_0"
});
/* ======================================================================
OpenLayers/Strategy/Cluster.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -72548,11 +74376,11 @@
});
/* ======================================================================
OpenLayers/Strategy/Filter.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -72711,11 +74539,11 @@
});
/* ======================================================================
OpenLayers/Protocol/SOS.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -72748,11 +74576,11 @@
};
/* ======================================================================
OpenLayers/Format/GeoRSS.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -73161,11 +74989,11 @@
});
/* ======================================================================
OpenLayers/Format/WPSCapabilities.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -73213,11 +75041,11 @@
});
/* ======================================================================
OpenLayers/Format/WPSCapabilities/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -73342,11 +75170,10 @@
* full list of contributors). Published under the 2-clause BSD license.
* See license.txt in the OpenLayers distribution or repository for the
* full text of the license. */
/**
- * @requires OpenLayers/Util/vendorPrefix.js
* @requires OpenLayers/Handler/Pinch.js
*/
/**
* Class: OpenLayers.Control.PinchZoom
@@ -73443,43 +75270,29 @@
var containerOrigin = this.map.layerContainerOriginPx;
var pinchOrigin = this.pinchOrigin;
var current = (this.preserveCenter) ?
this.map.getPixelFromLonLat(this.map.getCenter()) : evt.xy;
- var dx = Math.round((current.x - pinchOrigin.x) + (scale - 1) * (containerOrigin.x - pinchOrigin.x));
- var dy = Math.round((current.y - pinchOrigin.y) + (scale - 1) * (containerOrigin.y - pinchOrigin.y));
+ var dx = Math.round((containerOrigin.x + current.x - pinchOrigin.x) + (scale - 1) * (containerOrigin.x - pinchOrigin.x));
+ var dy = Math.round((containerOrigin.y + current.y - pinchOrigin.y) + (scale - 1) * (containerOrigin.y - pinchOrigin.y));
- this.applyTransform(
- "translate(" + dx + "px, " + dy + "px) scale(" + scale + ")"
- );
+ this.map.applyTransform(dx, dy, scale);
this.currentCenter = current;
},
-
+
/**
- * Method: applyTransform
- * Applies the given transform to layers.
- */
- applyTransform: function(transform) {
- var style = this.map.layerContainerDiv.style;
- var transformProperty = OpenLayers.Util.vendorPrefix.style("transform");
- if (transformProperty) {
- style[transformProperty] = transform;
- }
- },
-
- /**
* Method: pinchDone
*
* Parameters:
* evt - {Event}
* start - {Object} pinch data object related to the touchstart event that
* started the pinch gesture.
* last - {Object} pinch data object related to the last touchmove event
* of the pinch gesture. This give us the final scale of the pinch.
*/
pinchDone: function(evt, start, last) {
- this.applyTransform("");
+ this.map.applyTransform();
var zoom = this.map.getZoomForResolution(this.map.getResolution() / last.scale, true);
if (zoom !== this.map.getZoom() || !this.currentCenter.equals(this.pinchOrigin)) {
var resolution = this.map.getResolutionForZoom(zoom);
var location = this.map.getLonLatFromPixel(this.pinchOrigin);
@@ -73689,21 +75502,277 @@
*
* Parameters:
* evt - {Event}
*/
defaultDblClick: function (evt) {
- var newCenter = this.map.getLonLatFromViewPortPx(evt.xy);
- this.map.setCenter(newCenter, this.map.zoom + 1);
+ this.map.zoomTo(this.map.zoom + 1, evt.xy);
},
CLASS_NAME: "OpenLayers.Control.TouchNavigation"
});
/* ======================================================================
+ Rico/Color.js
+ ====================================================================== */
+
+/**
+ * @requires Rico/license.js
+ * @requires OpenLayers/Console.js
+ * @requires OpenLayers/BaseTypes/Class.js
+ * @requires OpenLayers/BaseTypes/Element.js
+ */
+
+
+/*
+ * This file has been edited substantially from the Rico-released version by
+ * the OpenLayers development team.
+ */
+
+OpenLayers.Console.warn("OpenLayers.Rico is deprecated");
+
+OpenLayers.Rico = OpenLayers.Rico || {};
+OpenLayers.Rico.Color = OpenLayers.Class({
+
+ initialize: function(red, green, blue) {
+ this.rgb = { r: red, g : green, b : blue };
+ },
+
+ setRed: function(r) {
+ this.rgb.r = r;
+ },
+
+ setGreen: function(g) {
+ this.rgb.g = g;
+ },
+
+ setBlue: function(b) {
+ this.rgb.b = b;
+ },
+
+ setHue: function(h) {
+
+ // get an HSB model, and set the new hue...
+ var hsb = this.asHSB();
+ hsb.h = h;
+
+ // convert back to RGB...
+ this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+ },
+
+ setSaturation: function(s) {
+ // get an HSB model, and set the new hue...
+ var hsb = this.asHSB();
+ hsb.s = s;
+
+ // convert back to RGB and set values...
+ this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+ },
+
+ setBrightness: function(b) {
+ // get an HSB model, and set the new hue...
+ var hsb = this.asHSB();
+ hsb.b = b;
+
+ // convert back to RGB and set values...
+ this.rgb = OpenLayers.Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
+ },
+
+ darken: function(percent) {
+ var hsb = this.asHSB();
+ this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
+ },
+
+ brighten: function(percent) {
+ var hsb = this.asHSB();
+ this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
+ },
+
+ blend: function(other) {
+ this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
+ this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
+ this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
+ },
+
+ isBright: function() {
+ var hsb = this.asHSB();
+ return this.asHSB().b > 0.5;
+ },
+
+ isDark: function() {
+ return ! this.isBright();
+ },
+
+ asRGB: function() {
+ return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
+ },
+
+ asHex: function() {
+ return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
+ },
+
+ asHSB: function() {
+ return OpenLayers.Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
+ },
+
+ toString: function() {
+ return this.asHex();
+ }
+
+});
+
+OpenLayers.Rico.Color.createFromHex = function(hexCode) {
+ if(hexCode.length==4) {
+ var shortHexCode = hexCode;
+ var hexCode = '#';
+ for(var i=1;i<4;i++) {
+ hexCode += (shortHexCode.charAt(i) +
+shortHexCode.charAt(i));
+ }
+ }
+ if ( hexCode.indexOf('#') == 0 ) {
+ hexCode = hexCode.substring(1);
+ }
+ var red = hexCode.substring(0,2);
+ var green = hexCode.substring(2,4);
+ var blue = hexCode.substring(4,6);
+ return new OpenLayers.Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
+};
+
+/**
+ * Factory method for creating a color from the background of
+ * an HTML element.
+ */
+OpenLayers.Rico.Color.createColorFromBackground = function(elem) {
+
+ var actualColor =
+ OpenLayers.Element.getStyle(OpenLayers.Util.getElement(elem),
+ "backgroundColor");
+
+ if ( actualColor == "transparent" && elem.parentNode ) {
+ return OpenLayers.Rico.Color.createColorFromBackground(elem.parentNode);
+ }
+ if ( actualColor == null ) {
+ return new OpenLayers.Rico.Color(255,255,255);
+ }
+ if ( actualColor.indexOf("rgb(") == 0 ) {
+ var colors = actualColor.substring(4, actualColor.length - 1 );
+ var colorArray = colors.split(",");
+ return new OpenLayers.Rico.Color( parseInt( colorArray[0] ),
+ parseInt( colorArray[1] ),
+ parseInt( colorArray[2] ) );
+
+ }
+ else if ( actualColor.indexOf("#") == 0 ) {
+ return OpenLayers.Rico.Color.createFromHex(actualColor);
+ }
+ else {
+ return new OpenLayers.Rico.Color(255,255,255);
+ }
+};
+
+OpenLayers.Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
+
+ var red = 0;
+ var green = 0;
+ var blue = 0;
+
+ if (saturation == 0) {
+ red = parseInt(brightness * 255.0 + 0.5);
+ green = red;
+ blue = red;
+ }
+ else {
+ var h = (hue - Math.floor(hue)) * 6.0;
+ var f = h - Math.floor(h);
+ var p = brightness * (1.0 - saturation);
+ var q = brightness * (1.0 - saturation * f);
+ var t = brightness * (1.0 - (saturation * (1.0 - f)));
+
+ switch (parseInt(h)) {
+ case 0:
+ red = (brightness * 255.0 + 0.5);
+ green = (t * 255.0 + 0.5);
+ blue = (p * 255.0 + 0.5);
+ break;
+ case 1:
+ red = (q * 255.0 + 0.5);
+ green = (brightness * 255.0 + 0.5);
+ blue = (p * 255.0 + 0.5);
+ break;
+ case 2:
+ red = (p * 255.0 + 0.5);
+ green = (brightness * 255.0 + 0.5);
+ blue = (t * 255.0 + 0.5);
+ break;
+ case 3:
+ red = (p * 255.0 + 0.5);
+ green = (q * 255.0 + 0.5);
+ blue = (brightness * 255.0 + 0.5);
+ break;
+ case 4:
+ red = (t * 255.0 + 0.5);
+ green = (p * 255.0 + 0.5);
+ blue = (brightness * 255.0 + 0.5);
+ break;
+ case 5:
+ red = (brightness * 255.0 + 0.5);
+ green = (p * 255.0 + 0.5);
+ blue = (q * 255.0 + 0.5);
+ break;
+ }
+ }
+
+ return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
+};
+
+OpenLayers.Rico.Color.RGBtoHSB = function(r, g, b) {
+
+ var hue;
+ var saturation;
+ var brightness;
+
+ var cmax = (r > g) ? r : g;
+ if (b > cmax) {
+ cmax = b;
+ }
+ var cmin = (r < g) ? r : g;
+ if (b < cmin) {
+ cmin = b;
+ }
+ brightness = cmax / 255.0;
+ if (cmax != 0) {
+ saturation = (cmax - cmin)/cmax;
+ } else {
+ saturation = 0;
+ }
+ if (saturation == 0) {
+ hue = 0;
+ } else {
+ var redc = (cmax - r)/(cmax - cmin);
+ var greenc = (cmax - g)/(cmax - cmin);
+ var bluec = (cmax - b)/(cmax - cmin);
+
+ if (r == cmax) {
+ hue = bluec - greenc;
+ } else if (g == cmax) {
+ hue = 2.0 + redc - bluec;
+ } else {
+ hue = 4.0 + greenc - redc;
+ }
+ hue = hue / 6.0;
+ if (hue < 0) {
+ hue = hue + 1.0;
+ }
+ }
+
+ return { h : hue, s : saturation, b : brightness };
+};
+
+/* ======================================================================
OpenLayers/Style2.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -73815,11 +75884,11 @@
});
/* ======================================================================
OpenLayers/Layer/Boxes.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -73895,11 +75964,11 @@
});
/* ======================================================================
OpenLayers/Format/WFSCapabilities/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -74003,325 +76072,896 @@
"SRS": function(node, obj) {
var srs = this.getChildValue(node);
if (srs) {
obj.srs = srs;
}
+ },
+ "LatLongBoundingBox": function(node, obj) {
+ obj.latLongBoundingBox = [
+ parseFloat(node.getAttribute("minx")),
+ parseFloat(node.getAttribute("miny")),
+ parseFloat(node.getAttribute("maxx")),
+ parseFloat(node.getAttribute("maxy"))
+ ];
}
}, OpenLayers.Format.WFSCapabilities.v1.prototype.readers["wfs"])
},
CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1_0_0"
});
/* ======================================================================
- OpenLayers/Layer/PointGrid.js
+ OpenLayers/Format/CSWGetRecords/v2_0_2.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Layer/Vector.js
- * @requires OpenLayers/Geometry/Polygon.js
+ * @requires OpenLayers/Format/XML.js
+ * @requires OpenLayers/Format/CSWGetRecords.js
+ * @requires OpenLayers/Format/Filter/v1_0_0.js
+ * @requires OpenLayers/Format/Filter/v1_1_0.js
+ * @requires OpenLayers/Format/OWSCommon/v1_0_0.js
*/
/**
- * Class: OpenLayers.Layer.PointGrid
- * A point grid layer dynamically generates a regularly spaced grid of point
- * features. This is a specialty layer for cases where an application needs
- * a regular grid of points. It can be used, for example, in an editing
- * environment to snap to a grid.
+ * Class: OpenLayers.Format.CSWGetRecords.v2_0_2
+ * A format for creating CSWGetRecords v2.0.2 transactions.
+ * Create a new instance with the
+ * <OpenLayers.Format.CSWGetRecords.v2_0_2> constructor.
*
- * Create a new vector layer with the <OpenLayers.Layer.PointGrid> constructor.
- * (code)
- * // create a grid with points spaced at 10 map units
- * var points = new OpenLayers.Layer.PointGrid({dx: 10, dy: 10});
- *
- * // create a grid with different x/y spacing rotated 15 degrees clockwise.
- * var points = new OpenLayers.Layer.PointGrid({dx: 5, dy: 10, rotation: 15});
- * (end)
- *
* Inherits from:
- * - <OpenLayers.Layer.Vector>
+ * - <OpenLayers.Format.XML>
*/
-OpenLayers.Layer.PointGrid = OpenLayers.Class(OpenLayers.Layer.Vector, {
+OpenLayers.Format.CSWGetRecords.v2_0_2 = OpenLayers.Class(OpenLayers.Format.XML, {
+
+ /**
+ * Property: namespaces
+ * {Object} Mapping of namespace aliases to namespace URIs.
+ */
+ namespaces: {
+ csw: "http://www.opengis.net/cat/csw/2.0.2",
+ dc: "http://purl.org/dc/elements/1.1/",
+ dct: "http://purl.org/dc/terms/",
+ gmd: "http://www.isotc211.org/2005/gmd",
+ geonet: "http://www.fao.org/geonetwork",
+ ogc: "http://www.opengis.net/ogc",
+ ows: "http://www.opengis.net/ows",
+ xlink: "http://www.w3.org/1999/xlink",
+ xsi: "http://www.w3.org/2001/XMLSchema-instance"
+ },
+
+ /**
+ * Property: defaultPrefix
+ * {String} The default prefix (used by Format.XML).
+ */
+ defaultPrefix: "csw",
+
+ /**
+ * Property: version
+ * {String} CSW version number.
+ */
+ version: "2.0.2",
+
+ /**
+ * Property: schemaLocation
+ * {String} http://www.opengis.net/cat/csw/2.0.2
+ * http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd
+ */
+ schemaLocation: "http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",
/**
- * APIProperty: dx
- * {Number} Point grid spacing in the x-axis direction (map units).
- * Read-only. Use the <setSpacing> method to modify this value.
+ * APIProperty: requestId
+ * {String} Value of the requestId attribute of the GetRecords element.
*/
- dx: null,
+ requestId: null,
/**
- * APIProperty: dy
- * {Number} Point grid spacing in the y-axis direction (map units).
- * Read-only. Use the <setSpacing> method to modify this value.
+ * APIProperty: resultType
+ * {String} Value of the resultType attribute of the GetRecords element,
+ * specifies the result type in the GetRecords response, "hits" is
+ * the default.
*/
- dy: null,
+ resultType: null,
/**
- * APIProperty: ratio
- * {Number} Ratio of the desired grid size to the map viewport size.
- * Default is 1.5. Larger ratios mean the grid is recalculated less often
- * while panning. The <maxFeatures> setting has precedence when determining
- * grid size. Read-only. Use the <setRatio> method to modify this value.
+ * APIProperty: outputFormat
+ * {String} Value of the outputFormat attribute of the GetRecords element,
+ * specifies the format of the GetRecords response,
+ * "application/xml" is the default.
*/
- ratio: 1.5,
+ outputFormat: null,
/**
- * APIProperty: maxFeatures
- * {Number} The maximum number of points to generate in the grid. Default
- * is 250. Read-only. Use the <setMaxFeatures> method to modify this value.
+ * APIProperty: outputSchema
+ * {String} Value of the outputSchema attribute of the GetRecords element,
+ * specifies the schema of the GetRecords response.
*/
- maxFeatures: 250,
+ outputSchema: null,
/**
- * APIProperty: rotation
- * {Number} Grid rotation (in degrees clockwise from the positive x-axis).
- * Default is 0. Read-only. Use the <setRotation> method to modify this
- * value.
+ * APIProperty: startPosition
+ * {String} Value of the startPosition attribute of the GetRecords element,
+ * specifies the start position (offset+1) for the GetRecords response,
+ * 1 is the default.
*/
- rotation: 0,
+ startPosition: null,
/**
- * APIProperty: origin
- * {<OpenLayers.LonLat>} Grid origin. The grid lattice will be aligned with
- * the origin. If not set at construction, the center of the map's maximum
- * extent is used. Read-only. Use the <setOrigin> method to modify this
- * value.
+ * APIProperty: maxRecords
+ * {String} Value of the maxRecords attribute of the GetRecords element,
+ * specifies the maximum number of records in the GetRecords response,
+ * 10 is the default.
*/
- origin: null,
+ maxRecords: null,
/**
- * Property: gridBounds
- * {<OpenLayers.Bounds>} Internally cached grid bounds (with optional
- * rotation applied).
+ * APIProperty: DistributedSearch
+ * {String} Value of the csw:DistributedSearch element, used when writing
+ * a csw:GetRecords document.
*/
- gridBounds: null,
+ DistributedSearch: null,
/**
- * Constructor: OpenLayers.Layer.PointGrid
- * Creates a new point grid layer.
- *
- * Parameters:
- * config - {Object} An object containing all configuration properties for
- * the layer. The <dx> and <dy> properties are required to be set at
- * construction. Any other layer properties may be set in this object.
+ * APIProperty: ResponseHandler
+ * {Array({String})} Values of the csw:ResponseHandler elements, used when
+ * writting a csw:GetRecords document.
*/
- initialize: function(config) {
- config = config || {};
- OpenLayers.Layer.Vector.prototype.initialize.apply(this, [config.name, config]);
- },
-
- /**
- * Method: setMap
- * The layer has been added to the map.
- *
- * Parameters:
- * map - {<OpenLayers.Map>}
+ ResponseHandler: null,
+
+ /**
+ * APIProperty: Query
+ * {String} Value of the csw:Query element, used when writing a csw:GetRecords
+ * document.
*/
- setMap: function(map) {
- OpenLayers.Layer.Vector.prototype.setMap.apply(this, arguments);
- map.events.register("moveend", this, this.onMoveEnd);
+ Query: null,
+
+ /**
+ * Property: regExes
+ * Compiled regular expressions for manipulating strings.
+ */
+ regExes: {
+ trimSpace: (/^\s*|\s*$/g),
+ removeSpace: (/\s*/g),
+ splitSpace: (/\s+/),
+ trimComma: (/\s*,\s*/g)
},
/**
- * Method: removeMap
- * The layer has been removed from the map.
+ * Constructor: OpenLayers.Format.CSWGetRecords.v2_0_2
+ * A class for parsing and generating CSWGetRecords v2.0.2 transactions.
*
* Parameters:
- * map - {<OpenLayers.Map>}
+ * options - {Object} Optional object whose properties will be set on the
+ * instance.
+ *
+ * Valid options properties (documented as class properties):
+ * - requestId
+ * - resultType
+ * - outputFormat
+ * - outputSchema
+ * - startPosition
+ * - maxRecords
+ * - DistributedSearch
+ * - ResponseHandler
+ * - Query
*/
- removeMap: function(map) {
- map.events.unregister("moveend", this, this.onMoveEnd);
- OpenLayers.Layer.Vector.prototype.removeMap.apply(this, arguments);
+ initialize: function(options) {
+ OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
},
+
+ /**
+ * APIMethod: read
+ * Parse the response from a GetRecords request.
+ */
+ read: function(data) {
+ if(typeof data == "string") {
+ data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
+ }
+ if(data && data.nodeType == 9) {
+ data = data.documentElement;
+ }
+ var obj = {};
+ this.readNode(data, obj);
+ return obj;
+ },
/**
- * APIMethod: setRatio
- * Set the grid <ratio> property and update the grid. Can only be called
- * after the layer has been added to a map with a center/extent.
- *
- * Parameters:
- * ratio - {Number}
+ * Property: readers
+ * Contains public functions, grouped by namespace prefix, that will
+ * be applied when a namespaced node is found matching the function
+ * name. The function will be applied in the scope of this parser
+ * with two arguments: the node being read and a context object passed
+ * from the parent.
*/
- setRatio: function(ratio) {
- this.ratio = ratio;
- this.updateGrid(true);
+ readers: {
+ "csw": {
+ "GetRecordsResponse": function(node, obj) {
+ obj.records = [];
+ this.readChildNodes(node, obj);
+ var version = this.getAttributeNS(node, "", 'version');
+ if (version != "") {
+ obj.version = version;
+ }
+ },
+ "RequestId": function(node, obj) {
+ obj.RequestId = this.getChildValue(node);
+ },
+ "SearchStatus": function(node, obj) {
+ obj.SearchStatus = {};
+ var timestamp = this.getAttributeNS(node, "", 'timestamp');
+ if (timestamp != "") {
+ obj.SearchStatus.timestamp = timestamp;
+ }
+ },
+ "SearchResults": function(node, obj) {
+ this.readChildNodes(node, obj);
+ var attrs = node.attributes;
+ var SearchResults = {};
+ for(var i=0, len=attrs.length; i<len; ++i) {
+ if ((attrs[i].name == "numberOfRecordsMatched") ||
+ (attrs[i].name == "numberOfRecordsReturned") ||
+ (attrs[i].name == "nextRecord")) {
+ SearchResults[attrs[i].name] = parseInt(attrs[i].nodeValue);
+ } else {
+ SearchResults[attrs[i].name] = attrs[i].nodeValue;
+ }
+ }
+ obj.SearchResults = SearchResults;
+ },
+ "SummaryRecord": function(node, obj) {
+ var record = {type: "SummaryRecord"};
+ this.readChildNodes(node, record);
+ obj.records.push(record);
+ },
+ "BriefRecord": function(node, obj) {
+ var record = {type: "BriefRecord"};
+ this.readChildNodes(node, record);
+ obj.records.push(record);
+ },
+ "DCMIRecord": function(node, obj) {
+ var record = {type: "DCMIRecord"};
+ this.readChildNodes(node, record);
+ obj.records.push(record);
+ },
+ "Record": function(node, obj) {
+ var record = {type: "Record"};
+ this.readChildNodes(node, record);
+ obj.records.push(record);
+ },
+ "*": function(node, obj) {
+ var name = node.localName || node.nodeName.split(":").pop();
+ obj[name] = this.getChildValue(node);
+ }
+ },
+ "geonet": {
+ "info": function(node, obj) {
+ var gninfo = {};
+ this.readChildNodes(node, gninfo);
+ obj.gninfo = gninfo;
+ }
+ },
+ "dc": {
+ // audience, contributor, coverage, creator, date, description, format,
+ // identifier, language, provenance, publisher, relation, rights,
+ // rightsHolder, source, subject, title, type, URI
+ "*": function(node, obj) {
+ var name = node.localName || node.nodeName.split(":").pop();
+ if (!(OpenLayers.Util.isArray(obj[name]))) {
+ obj[name] = [];
+ }
+ var dc_element = {};
+ var attrs = node.attributes;
+ for(var i=0, len=attrs.length; i<len; ++i) {
+ dc_element[attrs[i].name] = attrs[i].nodeValue;
+ }
+ dc_element.value = this.getChildValue(node);
+ if (dc_element.value != "") {
+ obj[name].push(dc_element);
+ }
+ }
+ },
+ "dct": {
+ // abstract, modified, spatial
+ "*": function(node, obj) {
+ var name = node.localName || node.nodeName.split(":").pop();
+ if (!(OpenLayers.Util.isArray(obj[name]))) {
+ obj[name] = [];
+ }
+ obj[name].push(this.getChildValue(node));
+ }
+ },
+ "ows": OpenLayers.Util.applyDefaults({
+ "BoundingBox": function(node, obj) {
+ if (obj.bounds) {
+ obj.BoundingBox = [{crs: obj.projection, value:
+ [
+ obj.bounds.left,
+ obj.bounds.bottom,
+ obj.bounds.right,
+ obj.bounds.top
+ ]
+ }];
+ delete obj.projection;
+ delete obj.bounds;
+ }
+ OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]["BoundingBox"].apply(
+ this, arguments);
+ }
+ }, OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"])
},
/**
- * APIMethod: setMaxFeatures
- * Set the grid <maxFeatures> property and update the grid. Can only be
- * called after the layer has been added to a map with a center/extent.
+ * Method: write
+ * Given an configuration js object, write a CSWGetRecords request.
*
* Parameters:
- * maxFeatures - {Number}
+ * options - {Object} A object mapping the request.
+ *
+ * Returns:
+ * {String} A serialized CSWGetRecords request.
*/
- setMaxFeatures: function(maxFeatures) {
- this.maxFeatures = maxFeatures;
- this.updateGrid(true);
+ write: function(options) {
+ var node = this.writeNode("csw:GetRecords", options);
+ node.setAttribute("xmlns:gmd", this.namespaces.gmd);
+ return OpenLayers.Format.XML.prototype.write.apply(this, [node]);
},
/**
- * APIMethod: setSpacing
- * Set the grid <dx> and <dy> properties and update the grid. If only one
- * argument is provided, it will be set as <dx> and <dy>. Can only be
- * called after the layer has been added to a map with a center/extent.
- *
- * Parameters:
- * dx - {Number}
- * dy - {Number}
+ * Property: writers
+ * As a compliment to the readers property, this structure contains public
+ * writing functions grouped by namespace alias and named like the
+ * node names they produce.
*/
- setSpacing: function(dx, dy) {
- this.dx = dx;
- this.dy = dy || dx;
- this.updateGrid(true);
+ writers: {
+ "csw": {
+ "GetRecords": function(options) {
+ if (!options) {
+ options = {};
+ }
+ var node = this.createElementNSPlus("csw:GetRecords", {
+ attributes: {
+ service: "CSW",
+ version: this.version,
+ requestId: options.requestId || this.requestId,
+ resultType: options.resultType || this.resultType,
+ outputFormat: options.outputFormat || this.outputFormat,
+ outputSchema: options.outputSchema || this.outputSchema,
+ startPosition: options.startPosition || this.startPosition,
+ maxRecords: options.maxRecords || this.maxRecords
+ }
+ });
+ if (options.DistributedSearch || this.DistributedSearch) {
+ this.writeNode(
+ "csw:DistributedSearch",
+ options.DistributedSearch || this.DistributedSearch,
+ node
+ );
+ }
+ var ResponseHandler = options.ResponseHandler || this.ResponseHandler;
+ if (OpenLayers.Util.isArray(ResponseHandler) && ResponseHandler.length > 0) {
+ // ResponseHandler must be a non-empty array
+ for(var i=0, len=ResponseHandler.length; i<len; i++) {
+ this.writeNode(
+ "csw:ResponseHandler",
+ ResponseHandler[i],
+ node
+ );
+ }
+ }
+ this.writeNode("Query", options.Query || this.Query, node);
+ return node;
+ },
+ "DistributedSearch": function(options) {
+ var node = this.createElementNSPlus("csw:DistributedSearch", {
+ attributes: {
+ hopCount: options.hopCount
+ }
+ });
+ return node;
+ },
+ "ResponseHandler": function(options) {
+ var node = this.createElementNSPlus("csw:ResponseHandler", {
+ value: options.value
+ });
+ return node;
+ },
+ "Query": function(options) {
+ if (!options) {
+ options = {};
+ }
+ var node = this.createElementNSPlus("csw:Query", {
+ attributes: {
+ typeNames: options.typeNames || "csw:Record"
+ }
+ });
+ var ElementName = options.ElementName;
+ if (OpenLayers.Util.isArray(ElementName) && ElementName.length > 0) {
+ // ElementName must be a non-empty array
+ for(var i=0, len=ElementName.length; i<len; i++) {
+ this.writeNode(
+ "csw:ElementName",
+ ElementName[i],
+ node
+ );
+ }
+ } else {
+ this.writeNode(
+ "csw:ElementSetName",
+ options.ElementSetName || {value: 'summary'},
+ node
+ );
+ }
+ if (options.Constraint) {
+ this.writeNode(
+ "csw:Constraint",
+ options.Constraint,
+ node
+ );
+ }
+ if (options.SortBy) {
+ this.writeNode(
+ "ogc:SortBy",
+ options.SortBy,
+ node
+ );
+ }
+ return node;
+ },
+ "ElementName": function(options) {
+ var node = this.createElementNSPlus("csw:ElementName", {
+ value: options.value
+ });
+ return node;
+ },
+ "ElementSetName": function(options) {
+ var node = this.createElementNSPlus("csw:ElementSetName", {
+ attributes: {
+ typeNames: options.typeNames
+ },
+ value: options.value
+ });
+ return node;
+ },
+ "Constraint": function(options) {
+ var node = this.createElementNSPlus("csw:Constraint", {
+ attributes: {
+ version: options.version
+ }
+ });
+ if (options.Filter) {
+ var format = new OpenLayers.Format.Filter({
+ version: options.version
+ });
+ node.appendChild(format.write(options.Filter));
+ } else if (options.CqlText) {
+ var child = this.createElementNSPlus("CqlText", {
+ value: options.CqlText.value
+ });
+ node.appendChild(child);
+ }
+ return node;
+ }
+ },
+ "ogc": OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"]
},
+
+ CLASS_NAME: "OpenLayers.Format.CSWGetRecords.v2_0_2"
+});
+/* ======================================================================
+ OpenLayers/Control/WMTSGetFeatureInfo.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/Control.js
+ * @requires OpenLayers/Handler/Click.js
+ * @requires OpenLayers/Handler/Hover.js
+ * @requires OpenLayers/Request.js
+ * @requires OpenLayers/Format/WMSGetFeatureInfo.js
+ */
+
+/**
+ * Class: OpenLayers.Control.WMTSGetFeatureInfo
+ * The WMTSGetFeatureInfo control uses a WMTS query to get information about a
+ * point on the map. The information may be in a display-friendly format
+ * such as HTML, or a machine-friendly format such as GML, depending on the
+ * server's capabilities and the client's configuration. This control
+ * handles click or hover events, attempts to parse the results using an
+ * OpenLayers.Format, and fires a 'getfeatureinfo' event for each layer
+ * queried.
+ *
+ * Inherits from:
+ * - <OpenLayers.Control>
+ */
+OpenLayers.Control.WMTSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
+
+ /**
+ * APIProperty: hover
+ * {Boolean} Send GetFeatureInfo requests when mouse stops moving.
+ * Default is false.
+ */
+ hover: false,
/**
- * APIMethod: setOrigin
- * Set the grid <origin> property and update the grid. Can only be called
- * after the layer has been added to a map with a center/extent.
+ * Property: requestEncoding
+ * {String} One of "KVP" or "REST". Only KVP encoding is supported at this
+ * time.
+ */
+ requestEncoding: "KVP",
+
+ /**
+ * APIProperty: drillDown
+ * {Boolean} Drill down over all WMTS layers in the map. When
+ * using drillDown mode, hover is not possible. A getfeatureinfo event
+ * will be fired for each layer queried.
+ */
+ drillDown: false,
+
+ /**
+ * APIProperty: maxFeatures
+ * {Integer} Maximum number of features to return from a WMTS query. This
+ * sets the feature_count parameter on WMTS GetFeatureInfo
+ * requests.
+ */
+ maxFeatures: 10,
+
+ /** APIProperty: clickCallback
+ * {String} The click callback to register in the
+ * {<OpenLayers.Handler.Click>} object created when the hover
+ * option is set to false. Default is "click".
+ */
+ clickCallback: "click",
+
+ /**
+ * Property: layers
+ * {Array(<OpenLayers.Layer.WMTS>)} The layers to query for feature info.
+ * If omitted, all map WMTS layers will be considered.
+ */
+ layers: null,
+
+ /**
+ * APIProperty: queryVisible
+ * {Boolean} Filter out hidden layers when searching the map for layers to
+ * query. Default is true.
+ */
+ queryVisible: true,
+
+ /**
+ * Property: infoFormat
+ * {String} The mimetype to request from the server
+ */
+ infoFormat: 'text/html',
+
+ /**
+ * Property: vendorParams
+ * {Object} Additional parameters that will be added to the request, for
+ * WMTS implementations that support them. This could e.g. look like
+ * (start code)
+ * {
+ * radius: 5
+ * }
+ * (end)
+ */
+ vendorParams: {},
+
+ /**
+ * Property: format
+ * {<OpenLayers.Format>} A format for parsing GetFeatureInfo responses.
+ * Default is <OpenLayers.Format.WMSGetFeatureInfo>.
+ */
+ format: null,
+
+ /**
+ * Property: formatOptions
+ * {Object} Optional properties to set on the format (if one is not provided
+ * in the <format> property.
+ */
+ formatOptions: null,
+
+ /**
+ * APIProperty: handlerOptions
+ * {Object} Additional options for the handlers used by this control, e.g.
+ * (start code)
+ * {
+ * "click": {delay: 100},
+ * "hover": {delay: 300}
+ * }
+ * (end)
+ */
+
+ /**
+ * Property: handler
+ * {Object} Reference to the <OpenLayers.Handler> for this control
+ */
+ handler: null,
+
+ /**
+ * Property: hoverRequest
+ * {<OpenLayers.Request>} contains the currently running hover request
+ * (if any).
+ */
+ hoverRequest: null,
+
+ /**
+ * APIProperty: events
+ * {<OpenLayers.Events>} Events instance for listeners and triggering
+ * control specific events.
*
- * Parameters:
- * origin - {<OpenLayers.LonLat>}
+ * Register a listener for a particular event with the following syntax:
+ * (code)
+ * control.events.register(type, obj, listener);
+ * (end)
+ *
+ * Supported event types (in addition to those from <OpenLayers.Control.events>):
+ * beforegetfeatureinfo - Triggered before each request is sent.
+ * The event object has an *xy* property with the position of the
+ * mouse click or hover event that triggers the request and a *layer*
+ * property referencing the layer about to be queried. If a listener
+ * returns false, the request will not be issued.
+ * getfeatureinfo - Triggered when a GetFeatureInfo response is received.
+ * The event object has a *text* property with the body of the
+ * response (String), a *features* property with an array of the
+ * parsed features, an *xy* property with the position of the mouse
+ * click or hover event that triggered the request, a *layer* property
+ * referencing the layer queried and a *request* property with the
+ * request itself. If drillDown is set to true, one event will be fired
+ * for each layer queried.
+ * exception - Triggered when a GetFeatureInfo request fails (with a
+ * status other than 200) or whenparsing fails. Listeners will receive
+ * an event with *request*, *xy*, and *layer* properties. In the case
+ * of a parsing error, the event will also contain an *error* property.
*/
- setOrigin: function(origin) {
- this.origin = origin;
- this.updateGrid(true);
- },
+ /**
+ * Property: pending
+ * {Number} The number of pending requests.
+ */
+ pending: 0,
+
/**
- * APIMethod: getOrigin
- * Get the grid <origin> property.
+ * Constructor: <OpenLayers.Control.WMTSGetFeatureInfo>
*
- * Returns:
- * {<OpenLayers.LonLat>} The grid origin.
+ * Parameters:
+ * options - {Object}
*/
- getOrigin: function() {
- if (!this.origin) {
- this.origin = this.map.getExtent().getCenterLonLat();
+ initialize: function(options) {
+ options = options || {};
+ options.handlerOptions = options.handlerOptions || {};
+
+ OpenLayers.Control.prototype.initialize.apply(this, [options]);
+
+ if (!this.format) {
+ this.format = new OpenLayers.Format.WMSGetFeatureInfo(
+ options.formatOptions
+ );
}
- return this.origin;
+
+ if (this.drillDown === true) {
+ this.hover = false;
+ }
+
+ if (this.hover) {
+ this.handler = new OpenLayers.Handler.Hover(
+ this, {
+ move: this.cancelHover,
+ pause: this.getInfoForHover
+ },
+ OpenLayers.Util.extend(
+ this.handlerOptions.hover || {}, {delay: 250}
+ )
+ );
+ } else {
+ var callbacks = {};
+ callbacks[this.clickCallback] = this.getInfoForClick;
+ this.handler = new OpenLayers.Handler.Click(
+ this, callbacks, this.handlerOptions.click || {}
+ );
+ }
},
-
+
/**
- * APIMethod: setRotation
- * Set the grid <rotation> property and update the grid. Rotation values
- * are in degrees clockwise from the positive x-axis (negative values
- * for counter-clockwise rotation). Can only be called after the layer
- * has been added to a map with a center/extent.
+ * Method: getInfoForClick
+ * Called on click
*
* Parameters:
- * rotation - {Number} Degrees clockwise from the positive x-axis.
+ * evt - {<OpenLayers.Event>}
*/
- setRotation: function(rotation) {
- this.rotation = rotation;
- this.updateGrid(true);
+ getInfoForClick: function(evt) {
+ this.request(evt.xy, {});
},
-
+
/**
- * Method: onMoveEnd
- * Listener for map "moveend" events.
+ * Method: getInfoForHover
+ * Pause callback for the hover handler
+ *
+ * Parameters:
+ * evt - {Object}
*/
- onMoveEnd: function() {
- this.updateGrid();
+ getInfoForHover: function(evt) {
+ this.request(evt.xy, {hover: true});
},
-
+
/**
- * Method: getViewBounds
- * Gets the (potentially rotated) view bounds for grid calculations.
- *
- * Returns:
- * {<OpenLayers.Bounds>}
+ * Method: cancelHover
+ * Cancel callback for the hover handler
*/
- getViewBounds: function() {
- var bounds = this.map.getExtent();
- if (this.rotation) {
- var origin = this.getOrigin();
- var rotationOrigin = new OpenLayers.Geometry.Point(origin.lon, origin.lat);
- var rect = bounds.toGeometry();
- rect.rotate(-this.rotation, rotationOrigin);
- bounds = rect.getBounds();
+ cancelHover: function() {
+ if (this.hoverRequest) {
+ --this.pending;
+ if (this.pending <= 0) {
+ OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+ this.pending = 0;
+ }
+ this.hoverRequest.abort();
+ this.hoverRequest = null;
}
- return bounds;
},
+
+ /**
+ * Method: findLayers
+ * Internal method to get the layers, independent of whether we are
+ * inspecting the map or using a client-provided array
+ */
+ findLayers: function() {
+ var candidates = this.layers || this.map.layers;
+ var layers = [];
+ var layer;
+ for (var i=candidates.length-1; i>=0; --i) {
+ layer = candidates[i];
+ if (layer instanceof OpenLayers.Layer.WMTS &&
+ layer.requestEncoding === this.requestEncoding &&
+ (!this.queryVisible || layer.getVisibility())) {
+ layers.push(layer);
+ if (!this.drillDown || this.hover) {
+ break;
+ }
+ }
+ }
+ return layers;
+ },
/**
- * Method: updateGrid
- * Update the grid.
+ * Method: buildRequestOptions
+ * Build an object with the relevant options for the GetFeatureInfo request.
*
* Parameters:
- * force - {Boolean} Update the grid even if the previous bounds are still
- * valid.
+ * layer - {<OpenLayers.Layer.WMTS>} A WMTS layer.
+ * xy - {<OpenLayers.Pixel>} The position on the map where the
+ * mouse event occurred.
*/
- updateGrid: function(force) {
- if (force || this.invalidBounds()) {
- var viewBounds = this.getViewBounds();
- var origin = this.getOrigin();
- var rotationOrigin = new OpenLayers.Geometry.Point(origin.lon, origin.lat);
- var viewBoundsWidth = viewBounds.getWidth();
- var viewBoundsHeight = viewBounds.getHeight();
- var aspectRatio = viewBoundsWidth / viewBoundsHeight;
- var maxHeight = Math.sqrt(this.dx * this.dy * this.maxFeatures / aspectRatio);
- var maxWidth = maxHeight * aspectRatio;
- var gridWidth = Math.min(viewBoundsWidth * this.ratio, maxWidth);
- var gridHeight = Math.min(viewBoundsHeight * this.ratio, maxHeight);
- var center = viewBounds.getCenterLonLat();
- this.gridBounds = new OpenLayers.Bounds(
- center.lon - (gridWidth / 2),
- center.lat - (gridHeight / 2),
- center.lon + (gridWidth / 2),
- center.lat + (gridHeight / 2)
- );
- var rows = Math.floor(gridHeight / this.dy);
- var cols = Math.floor(gridWidth / this.dx);
- var gridLeft = origin.lon + (this.dx * Math.ceil((this.gridBounds.left - origin.lon) / this.dx));
- var gridBottom = origin.lat + (this.dy * Math.ceil((this.gridBounds.bottom - origin.lat) / this.dy));
- var features = new Array(rows * cols);
- var x, y, point;
- for (var i=0; i<cols; ++i) {
- x = gridLeft + (i * this.dx);
- for (var j=0; j<rows; ++j) {
- y = gridBottom + (j * this.dy);
- point = new OpenLayers.Geometry.Point(x, y);
- if (this.rotation) {
- point.rotate(this.rotation, rotationOrigin);
+ buildRequestOptions: function(layer, xy) {
+ var loc = this.map.getLonLatFromPixel(xy);
+ var getTileUrl = layer.getURL(
+ new OpenLayers.Bounds(loc.lon, loc.lat, loc.lon, loc.lat)
+ );
+ var params = OpenLayers.Util.getParameters(getTileUrl);
+ var tileInfo = layer.getTileInfo(loc);
+ OpenLayers.Util.extend(params, {
+ service: "WMTS",
+ version: layer.version,
+ request: "GetFeatureInfo",
+ infoFormat: this.infoFormat,
+ feature_count: this.maxFeatures,
+ i: tileInfo.i,
+ j: tileInfo.j
+ });
+ OpenLayers.Util.applyDefaults(params, this.vendorParams);
+ return {
+ url: OpenLayers.Util.isArray(layer.url) ? layer.url[0] : layer.url,
+ params: OpenLayers.Util.upperCaseObject(params),
+ callback: function(request) {
+ this.handleResponse(xy, request, layer);
+ },
+ scope: this
+ };
+ },
+
+ /**
+ * Method: request
+ * Sends a GetFeatureInfo request to the WMTS
+ *
+ * Parameters:
+ * xy - {<OpenLayers.Pixel>} The position on the map where the mouse event
+ * occurred.
+ * options - {Object} additional options for this method.
+ *
+ * Valid options:
+ * - *hover* {Boolean} true if we do the request for the hover handler
+ */
+ request: function(xy, options) {
+ options = options || {};
+ var layers = this.findLayers();
+ if (layers.length > 0) {
+ var issue, layer;
+ for (var i=0, len=layers.length; i<len; i++) {
+ layer = layers[i];
+ issue = this.events.triggerEvent("beforegetfeatureinfo", {
+ xy: xy,
+ layer: layer
+ });
+ if (issue !== false) {
+ ++this.pending;
+ var requestOptions = this.buildRequestOptions(layer, xy);
+ var request = OpenLayers.Request.GET(requestOptions);
+ if (options.hover === true) {
+ this.hoverRequest = request;
}
- features[(i*rows)+j] = new OpenLayers.Feature.Vector(point);
}
}
- this.destroyFeatures(this.features, {silent: true});
- this.addFeatures(features, {silent: true});
+ if (this.pending > 0) {
+ OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
+ }
}
},
/**
- * Method: invalidBounds
- * Determine whether the previously generated point grid is invalid.
- * This occurs when the map bounds extends beyond the previously
- * generated grid bounds.
- *
- * Returns:
- * {Boolean}
+ * Method: handleResponse
+ * Handler for the GetFeatureInfo response.
+ *
+ * Parameters:
+ * xy - {<OpenLayers.Pixel>} The position on the map where the mouse event
+ * occurred.
+ * request - {XMLHttpRequest} The request object.
+ * layer - {<OpenLayers.Layer.WMTS>} The queried layer.
*/
- invalidBounds: function() {
- return !this.gridBounds || !this.gridBounds.containsBounds(this.getViewBounds());
+ handleResponse: function(xy, request, layer) {
+ --this.pending;
+ if (this.pending <= 0) {
+ OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
+ this.pending = 0;
+ }
+ if (request.status && (request.status < 200 || request.status >= 300)) {
+ this.events.triggerEvent("exception", {
+ xy: xy,
+ request: request,
+ layer: layer
+ });
+ } else {
+ var doc = request.responseXML;
+ if (!doc || !doc.documentElement) {
+ doc = request.responseText;
+ }
+ var features, except;
+ try {
+ features = this.format.read(doc);
+ } catch (error) {
+ except = true;
+ this.events.triggerEvent("exception", {
+ xy: xy,
+ request: request,
+ error: error,
+ layer: layer
+ });
+ }
+ if (!except) {
+ this.events.triggerEvent("getfeatureinfo", {
+ text: request.responseText,
+ features: features,
+ request: request,
+ xy: xy,
+ layer: layer
+ });
+ }
+ }
},
- CLASS_NAME: "OpenLayers.Layer.PointGrid"
-
+ CLASS_NAME: "OpenLayers.Control.WMTSGetFeatureInfo"
});
/* ======================================================================
OpenLayers/Layer/Zoomify.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/*
@@ -74409,11 +77049,11 @@
// initilize the Zoomify pyramid for given size
this.initializeZoomify(size);
OpenLayers.Layer.Grid.prototype.initialize.apply(this, [
- name, url, size, {}, options
+ name, url, {}, options
]);
},
/**
* Method: initializeZoomify
@@ -74507,10 +77147,31 @@
return obj;
},
/**
+ * Method: createBackBuffer
+ * Create a back buffer.
+ *
+ * Returns:
+ * {DOMElement} The DOM element for the back buffer, undefined if the
+ * grid isn't initialized yet.
+ */
+ createBackBuffer: function() {
+ var backBuffer = OpenLayers.Layer.Grid.prototype.createBackBuffer.apply(this, arguments);
+ if(backBuffer) {
+ var image;
+ for (var i=backBuffer.childNodes.length-1; i>=0; --i) {
+ image = backBuffer.childNodes[i];
+ image._w = image.width;
+ image._h = image.height;
+ }
+ }
+ return backBuffer;
+ },
+
+ /**
* Method: getURL
*
* Parameters:
* bounds - {<OpenLayers.Bounds>}
*
@@ -74551,14 +77212,27 @@
var z = this.getZoomForResolution( res );
var w = this.standardTileSize;
var h = this.standardTileSize;
if (x == this.tierSizeInTiles[z].w -1 ) {
var w = this.tierImageSize[z].w % this.standardTileSize;
+ if (w == 0) {
+ w = this.standardTileSize;
+ }
}
if (y == this.tierSizeInTiles[z].h -1 ) {
var h = this.tierImageSize[z].h % this.standardTileSize;
+ if (h == 0) {
+ h = this.standardTileSize;
+ }
}
+ // in jp2 format, dimensions of tiles are ceiled, that means there may be requested part of image (1px usually) above dimension stated in tierImageSize.
+ if (x == this.tierSizeInTiles[z].w) {
+ w = Math.ceil(this.size.w / Math.pow(2, this.numberOfTiers - 1 - z) - this.tierImageSize[z].w);
+ }
+ if (y == this.tierSizeInTiles[z].h) {
+ h = Math.ceil(this.size.h / Math.pow(2, this.numberOfTiers - 1 - z) - this.tierImageSize[z].h);
+ }
return (new OpenLayers.Size(w, h));
} else {
return this.tileSize;
}
},
@@ -74581,11 +77255,11 @@
});
/* ======================================================================
OpenLayers/Handler/RegularPolygon.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -75014,11 +77688,11 @@
});
/* ======================================================================
OpenLayers/Layer/MapServer.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -75109,11 +77783,11 @@
getURL: function (bounds) {
bounds = this.adjustBounds(bounds);
// Make a list, so that getFullRequestString uses literal ","
var extent = [bounds.left, bounds. bottom, bounds.right, bounds.top];
- var imageSize = this.getImageSize();
+ var imageSize = this.getImageSize(bounds);
// make lists, so that literal ','s are used
var url = this.getFullRequestString(
{mapext: extent,
imgext: extent,
@@ -75199,11 +77873,11 @@
});
/* ======================================================================
OpenLayers/Renderer/VML.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -76188,11 +78862,11 @@
};
/* ======================================================================
OpenLayers/Control/CacheRead.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -76345,466 +79019,670 @@
},
CLASS_NAME: "OpenLayers.Control.CacheRead"
});
/* ======================================================================
- OpenLayers/Protocol/WFS/v1_0_0.js
+ OpenLayers/Protocol/HTTP.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Protocol/WFS/v1.js
- * @requires OpenLayers/Format/WFST/v1_0_0.js
+ * @requires OpenLayers/Protocol.js
+ * @requires OpenLayers/Request/XMLHttpRequest.js
*/
/**
- * Class: OpenLayers.Protocol.WFS.v1_0_0
- * A WFS v1.0.0 protocol for vector layers. Create a new instance with the
- * <OpenLayers.Protocol.WFS.v1_0_0> constructor.
+ * if application uses the query string, for example, for BBOX parameters,
+ * OpenLayers/Format/QueryStringFilter.js should be included in the build config file
+ */
+
+/**
+ * Class: OpenLayers.Protocol.HTTP
+ * A basic HTTP protocol for vector layers. Create a new instance with the
+ * <OpenLayers.Protocol.HTTP> constructor.
*
* Inherits from:
- * - <OpenLayers.Protocol.WFS.v1>
+ * - <OpenLayers.Protocol>
*/
-OpenLayers.Protocol.WFS.v1_0_0 = OpenLayers.Class(OpenLayers.Protocol.WFS.v1, {
-
+OpenLayers.Protocol.HTTP = OpenLayers.Class(OpenLayers.Protocol, {
+
/**
- * Property: version
- * {String} WFS version number.
+ * Property: url
+ * {String} Service URL, read-only, set through the options
+ * passed to constructor.
*/
- version: "1.0.0",
-
+ url: null,
+
/**
- * Constructor: OpenLayers.Protocol.WFS.v1_0_0
- * A class for giving layers WFS v1.0.0 protocol.
- *
- * Parameters:
- * options - {Object} Optional object whose properties will be set on the
- * instance.
- *
- * Valid options properties:
- * featureType - {String} Local (without prefix) feature typeName (required).
- * featureNS - {String} Feature namespace (optional).
- * featurePrefix - {String} Feature namespace alias (optional - only used
- * if featureNS is provided). Default is 'feature'.
- * geometryName - {String} Name of geometry attribute. Default is 'the_geom'.
+ * Property: headers
+ * {Object} HTTP request headers, read-only, set through the options
+ * passed to the constructor,
+ * Example: {'Content-Type': 'plain/text'}
*/
-
- CLASS_NAME: "OpenLayers.Protocol.WFS.v1_0_0"
-});
-/* ======================================================================
- OpenLayers/Control/WMTSGetFeatureInfo.js
- ====================================================================== */
+ headers: 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. */
-
-
-/**
- * @requires OpenLayers/Control.js
- * @requires OpenLayers/Handler/Click.js
- * @requires OpenLayers/Handler/Hover.js
- * @requires OpenLayers/Request.js
- * @requires OpenLayers/Format/WMSGetFeatureInfo.js
- */
-
-/**
- * Class: OpenLayers.Control.WMTSGetFeatureInfo
- * The WMTSGetFeatureInfo control uses a WMTS query to get information about a
- * point on the map. The information may be in a display-friendly format
- * such as HTML, or a machine-friendly format such as GML, depending on the
- * server's capabilities and the client's configuration. This control
- * handles click or hover events, attempts to parse the results using an
- * OpenLayers.Format, and fires a 'getfeatureinfo' event for each layer
- * queried.
- *
- * Inherits from:
- * - <OpenLayers.Control>
- */
-OpenLayers.Control.WMTSGetFeatureInfo = OpenLayers.Class(OpenLayers.Control, {
-
- /**
- * APIProperty: hover
- * {Boolean} Send GetFeatureInfo requests when mouse stops moving.
- * Default is false.
+ /**
+ * Property: params
+ * {Object} Parameters of GET requests, read-only, set through the options
+ * passed to the constructor,
+ * Example: {'bbox': '5,5,5,5'}
*/
- hover: false,
+ params: null,
/**
- * Property: requestEncoding
- * {String} One of "KVP" or "REST". Only KVP encoding is supported at this
- * time.
+ * Property: callback
+ * {Object} Function to be called when the <read>, <create>,
+ * <update>, <delete> or <commit> operation completes, read-only,
+ * set through the options passed to the constructor.
*/
- requestEncoding: "KVP",
+ callback: null,
/**
- * APIProperty: drillDown
- * {Boolean} Drill down over all WMTS layers in the map. When
- * using drillDown mode, hover is not possible. A getfeatureinfo event
- * will be fired for each layer queried.
+ * Property: scope
+ * {Object} Callback execution scope, read-only, set through the
+ * options passed to the constructor.
*/
- drillDown: false,
+ scope: null,
/**
- * APIProperty: maxFeatures
- * {Integer} Maximum number of features to return from a WMTS query. This
- * sets the feature_count parameter on WMTS GetFeatureInfo
- * requests.
+ * APIProperty: readWithPOST
+ * {Boolean} true if read operations are done with POST requests
+ * instead of GET, defaults to false.
*/
- maxFeatures: 10,
+ readWithPOST: false,
- /** APIProperty: clickCallback
- * {String} The click callback to register in the
- * {<OpenLayers.Handler.Click>} object created when the hover
- * option is set to false. Default is "click".
+ /**
+ * APIProperty: updateWithPOST
+ * {Boolean} true if update operations are done with POST requests
+ * defaults to false.
*/
- clickCallback: "click",
+ updateWithPOST: false,
/**
- * Property: layers
- * {Array(<OpenLayers.Layer.WMTS>)} The layers to query for feature info.
- * If omitted, all map WMTS layers will be considered.
+ * APIProperty: deleteWithPOST
+ * {Boolean} true if delete operations are done with POST requests
+ * defaults to false.
+ * if true, POST data is set to output of format.write().
*/
- layers: null,
+ deleteWithPOST: false,
/**
- * APIProperty: queryVisible
- * {Boolean} Filter out hidden layers when searching the map for layers to
- * query. Default is true.
+ * Property: wildcarded.
+ * {Boolean} If true percent signs are added around values
+ * read from LIKE filters, for example if the protocol
+ * read method is passed a LIKE filter whose property
+ * is "foo" and whose value is "bar" the string
+ * "foo__ilike=%bar%" will be sent in the query string;
+ * defaults to false.
*/
- queryVisible: true,
+ wildcarded: false,
/**
- * Property: infoFormat
- * {String} The mimetype to request from the server
+ * APIProperty: srsInBBOX
+ * {Boolean} Include the SRS identifier in BBOX query string parameter.
+ * Default is false. If true and the layer has a projection object set,
+ * any BBOX filter will be serialized with a fifth item identifying the
+ * projection. E.g. bbox=-1000,-1000,1000,1000,EPSG:900913
*/
- infoFormat: 'text/html',
-
+ srsInBBOX: false,
+
/**
- * Property: vendorParams
- * {Object} Additional parameters that will be added to the request, for
- * WMTS implementations that support them. This could e.g. look like
- * (start code)
- * {
- * radius: 5
- * }
- * (end)
+ * Constructor: OpenLayers.Protocol.HTTP
+ * A class for giving layers generic HTTP protocol.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will be set on the
+ * instance.
+ *
+ * Valid options include:
+ * url - {String}
+ * headers - {Object}
+ * params - {Object} URL parameters for GET requests
+ * format - {<OpenLayers.Format>}
+ * callback - {Function}
+ * scope - {Object}
*/
- vendorParams: {},
+ initialize: function(options) {
+ options = options || {};
+ this.params = {};
+ this.headers = {};
+ OpenLayers.Protocol.prototype.initialize.apply(this, arguments);
+
+ if (!this.filterToParams && OpenLayers.Format.QueryStringFilter) {
+ var format = new OpenLayers.Format.QueryStringFilter({
+ wildcarded: this.wildcarded,
+ srsInBBOX: this.srsInBBOX
+ });
+ this.filterToParams = function(filter, params) {
+ return format.write(filter, params);
+ };
+ }
+ },
/**
- * Property: format
- * {<OpenLayers.Format>} A format for parsing GetFeatureInfo responses.
- * Default is <OpenLayers.Format.WMSGetFeatureInfo>.
+ * APIMethod: destroy
+ * Clean up the protocol.
*/
- format: null,
-
- /**
- * Property: formatOptions
- * {Object} Optional properties to set on the format (if one is not provided
- * in the <format> property.
- */
- formatOptions: null,
+ destroy: function() {
+ this.params = null;
+ this.headers = null;
+ OpenLayers.Protocol.prototype.destroy.apply(this);
+ },
/**
- * APIProperty: handlerOptions
- * {Object} Additional options for the handlers used by this control, e.g.
- * (start code)
- * {
- * "click": {delay: 100},
- * "hover": {delay: 300}
- * }
- * (end)
+ * APIMethod: filterToParams
+ * Optional method to translate an <OpenLayers.Filter> object into an object
+ * that can be serialized as request query string provided. If a custom
+ * method is not provided, the filter will be serialized using the
+ * <OpenLayers.Format.QueryStringFilter> class.
+ *
+ * Parameters:
+ * filter - {<OpenLayers.Filter>} filter to convert.
+ * params - {Object} The parameters object.
+ *
+ * Returns:
+ * {Object} The resulting parameters object.
*/
/**
- * Property: handler
- * {Object} Reference to the <OpenLayers.Handler> for this control
+ * APIMethod: read
+ * Construct a request for reading new features.
+ *
+ * Parameters:
+ * options - {Object} Optional object for configuring the request.
+ * This object is modified and should not be reused.
+ *
+ * Valid options:
+ * url - {String} Url for the request.
+ * params - {Object} Parameters to get serialized as a query string.
+ * headers - {Object} Headers to be set on the request.
+ * filter - {<OpenLayers.Filter>} Filter to get serialized as a
+ * query string.
+ * readWithPOST - {Boolean} If the request should be done with POST.
+ *
+ * Returns:
+ * {<OpenLayers.Protocol.Response>} A response object, whose "priv" property
+ * references the HTTP request, this object is also passed to the
+ * callback function when the request completes, its "features" property
+ * is then populated with the features received from the server.
*/
- handler: null,
-
+ read: function(options) {
+ OpenLayers.Protocol.prototype.read.apply(this, arguments);
+ options = options || {};
+ options.params = OpenLayers.Util.applyDefaults(
+ options.params, this.options.params);
+ options = OpenLayers.Util.applyDefaults(options, this.options);
+ if (options.filter && this.filterToParams) {
+ options.params = this.filterToParams(
+ options.filter, options.params
+ );
+ }
+ var readWithPOST = (options.readWithPOST !== undefined) ?
+ options.readWithPOST : this.readWithPOST;
+ var resp = new OpenLayers.Protocol.Response({requestType: "read"});
+ if(readWithPOST) {
+ var headers = options.headers || {};
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
+ resp.priv = OpenLayers.Request.POST({
+ url: options.url,
+ callback: this.createCallback(this.handleRead, resp, options),
+ data: OpenLayers.Util.getParameterString(options.params),
+ headers: headers
+ });
+ } else {
+ resp.priv = OpenLayers.Request.GET({
+ url: options.url,
+ callback: this.createCallback(this.handleRead, resp, options),
+ params: options.params,
+ headers: options.headers
+ });
+ }
+ return resp;
+ },
+
/**
- * Property: hoverRequest
- * {<OpenLayers.Request>} contains the currently running hover request
- * (if any).
+ * Method: handleRead
+ * Individual callbacks are created for read, create and update, should
+ * a subclass need to override each one separately.
+ *
+ * Parameters:
+ * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
+ * the user callback.
+ * options - {Object} The user options passed to the read call.
*/
- hoverRequest: null,
-
- /**
- * APIProperty: events
- * {<OpenLayers.Events>} Events instance for listeners and triggering
- * control specific events.
+ handleRead: function(resp, options) {
+ this.handleResponse(resp, options);
+ },
+
+ /**
+ * APIMethod: create
+ * Construct a request for writing newly created features.
*
- * Register a listener for a particular event with the following syntax:
- * (code)
- * control.events.register(type, obj, listener);
- * (end)
+ * Parameters:
+ * features - {Array({<OpenLayers.Feature.Vector>})} or
+ * {<OpenLayers.Feature.Vector>}
+ * options - {Object} Optional object for configuring the request.
+ * This object is modified and should not be reused.
*
- * Supported event types (in addition to those from <OpenLayers.Control.events>):
- * beforegetfeatureinfo - Triggered before each request is sent.
- * The event object has an *xy* property with the position of the
- * mouse click or hover event that triggers the request and a *layer*
- * property referencing the layer about to be queried. If a listener
- * returns false, the request will not be issued.
- * getfeatureinfo - Triggered when a GetFeatureInfo response is received.
- * The event object has a *text* property with the body of the
- * response (String), a *features* property with an array of the
- * parsed features, an *xy* property with the position of the mouse
- * click or hover event that triggered the request, a *layer* property
- * referencing the layer queried and a *request* property with the
- * request itself. If drillDown is set to true, one event will be fired
- * for each layer queried.
- * exception - Triggered when a GetFeatureInfo request fails (with a
- * status other than 200) or whenparsing fails. Listeners will receive
- * an event with *request*, *xy*, and *layer* properties. In the case
- * of a parsing error, the event will also contain an *error* property.
+ * Returns:
+ * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+ * object, whose "priv" property references the HTTP request, this
+ * object is also passed to the callback function when the request
+ * completes, its "features" property is then populated with the
+ * the features received from the server.
*/
-
- /**
- * Property: pending
- * {Number} The number of pending requests.
+ create: function(features, options) {
+ options = OpenLayers.Util.applyDefaults(options, this.options);
+
+ var resp = new OpenLayers.Protocol.Response({
+ reqFeatures: features,
+ requestType: "create"
+ });
+
+ resp.priv = OpenLayers.Request.POST({
+ url: options.url,
+ callback: this.createCallback(this.handleCreate, resp, options),
+ headers: options.headers,
+ data: this.format.write(features)
+ });
+
+ return resp;
+ },
+
+ /**
+ * Method: handleCreate
+ * Called the the request issued by <create> is complete. May be overridden
+ * by subclasses.
+ *
+ * Parameters:
+ * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
+ * any user callback.
+ * options - {Object} The user options passed to the create call.
*/
- pending: 0,
+ handleCreate: function(resp, options) {
+ this.handleResponse(resp, options);
+ },
/**
- * Constructor: <OpenLayers.Control.WMTSGetFeatureInfo>
+ * APIMethod: update
+ * Construct a request updating modified feature.
*
* Parameters:
- * options - {Object}
+ * feature - {<OpenLayers.Feature.Vector>}
+ * options - {Object} Optional object for configuring the request.
+ * This object is modified and should not be reused.
+ *
+ * Returns:
+ * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+ * object, whose "priv" property references the HTTP request, this
+ * object is also passed to the callback function when the request
+ * completes, its "features" property is then populated with the
+ * the feature received from the server.
*/
- initialize: function(options) {
+ update: function(feature, options) {
options = options || {};
- options.handlerOptions = options.handlerOptions || {};
+ var url = options.url ||
+ feature.url ||
+ this.options.url + "/" + feature.fid;
+ options = OpenLayers.Util.applyDefaults(options, this.options);
- OpenLayers.Control.prototype.initialize.apply(this, [options]);
-
- if (!this.format) {
- this.format = new OpenLayers.Format.WMSGetFeatureInfo(
- options.formatOptions
- );
- }
-
- if (this.drillDown === true) {
- this.hover = false;
- }
+ var resp = new OpenLayers.Protocol.Response({
+ reqFeatures: feature,
+ requestType: "update"
+ });
- if (this.hover) {
- this.handler = new OpenLayers.Handler.Hover(
- this, {
- move: this.cancelHover,
- pause: this.getInfoForHover
- },
- OpenLayers.Util.extend(
- this.handlerOptions.hover || {}, {delay: 250}
- )
- );
- } else {
- var callbacks = {};
- callbacks[this.clickCallback] = this.getInfoForClick;
- this.handler = new OpenLayers.Handler.Click(
- this, callbacks, this.handlerOptions.click || {}
- );
- }
+ var method = this.updateWithPOST ? "POST" : "PUT";
+ resp.priv = OpenLayers.Request[method]({
+ url: url,
+ callback: this.createCallback(this.handleUpdate, resp, options),
+ headers: options.headers,
+ data: this.format.write(feature)
+ });
+
+ return resp;
},
/**
- * Method: getInfoForClick
- * Called on click
+ * Method: handleUpdate
+ * Called the the request issued by <update> is complete. May be overridden
+ * by subclasses.
*
* Parameters:
- * evt - {<OpenLayers.Event>}
+ * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
+ * any user callback.
+ * options - {Object} The user options passed to the update call.
*/
- getInfoForClick: function(evt) {
- this.request(evt.xy, {});
+ handleUpdate: function(resp, options) {
+ this.handleResponse(resp, options);
},
-
+
/**
- * Method: getInfoForHover
- * Pause callback for the hover handler
+ * APIMethod: delete
+ * Construct a request deleting a removed feature.
*
* Parameters:
- * evt - {Object}
+ * feature - {<OpenLayers.Feature.Vector>}
+ * options - {Object} Optional object for configuring the request.
+ * This object is modified and should not be reused.
+ *
+ * Returns:
+ * {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
+ * object, whose "priv" property references the HTTP request, this
+ * object is also passed to the callback function when the request
+ * completes.
*/
- getInfoForHover: function(evt) {
- this.request(evt.xy, {hover: true});
+ "delete": function(feature, options) {
+ options = options || {};
+ var url = options.url ||
+ feature.url ||
+ this.options.url + "/" + feature.fid;
+ options = OpenLayers.Util.applyDefaults(options, this.options);
+
+ var resp = new OpenLayers.Protocol.Response({
+ reqFeatures: feature,
+ requestType: "delete"
+ });
+
+ var method = this.deleteWithPOST ? "POST" : "DELETE";
+ var requestOptions = {
+ url: url,
+ callback: this.createCallback(this.handleDelete, resp, options),
+ headers: options.headers
+ };
+ if (this.deleteWithPOST) {
+ requestOptions.data = this.format.write(feature);
+ }
+ resp.priv = OpenLayers.Request[method](requestOptions);
+
+ return resp;
},
/**
- * Method: cancelHover
- * Cancel callback for the hover handler
+ * Method: handleDelete
+ * Called the the request issued by <delete> is complete. May be overridden
+ * by subclasses.
+ *
+ * Parameters:
+ * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
+ * any user callback.
+ * options - {Object} The user options passed to the delete call.
*/
- cancelHover: function() {
- if (this.hoverRequest) {
- --this.pending;
- if (this.pending <= 0) {
- OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
- this.pending = 0;
- }
- this.hoverRequest.abort();
- this.hoverRequest = null;
- }
+ handleDelete: function(resp, options) {
+ this.handleResponse(resp, options);
},
/**
- * Method: findLayers
- * Internal method to get the layers, independent of whether we are
- * inspecting the map or using a client-provided array
+ * Method: handleResponse
+ * Called by CRUD specific handlers.
+ *
+ * Parameters:
+ * resp - {<OpenLayers.Protocol.Response>} The response object to pass to
+ * any user callback.
+ * options - {Object} The user options passed to the create, read, update,
+ * or delete call.
*/
- findLayers: function() {
- var candidates = this.layers || this.map.layers;
- var layers = [];
- var layer;
- for (var i=candidates.length-1; i>=0; --i) {
- layer = candidates[i];
- if (layer instanceof OpenLayers.Layer.WMTS &&
- layer.requestEncoding === this.requestEncoding &&
- (!this.queryVisible || layer.getVisibility())) {
- layers.push(layer);
- if (!this.drillDown || this.hover) {
- break;
+ handleResponse: function(resp, options) {
+ var request = resp.priv;
+ if(options.callback) {
+ if(request.status >= 200 && request.status < 300) {
+ // success
+ if(resp.requestType != "delete") {
+ resp.features = this.parseFeatures(request);
}
+ resp.code = OpenLayers.Protocol.Response.SUCCESS;
+ } else {
+ // failure
+ resp.code = OpenLayers.Protocol.Response.FAILURE;
}
+ options.callback.call(options.scope, resp);
}
- return layers;
},
-
+
/**
- * Method: buildRequestOptions
- * Build an object with the relevant options for the GetFeatureInfo request.
+ * Method: parseFeatures
+ * Read HTTP response body and return features.
*
* Parameters:
- * layer - {<OpenLayers.Layer.WMTS>} A WMTS layer.
- * xy - {<OpenLayers.Pixel>} The position on the map where the
- * mouse event occurred.
+ * request - {XMLHttpRequest} The request object
+ *
+ * Returns:
+ * {Array({<OpenLayers.Feature.Vector>})} or
+ * {<OpenLayers.Feature.Vector>} Array of features or a single feature.
*/
- buildRequestOptions: function(layer, xy) {
- var loc = this.map.getLonLatFromPixel(xy);
- var getTileUrl = layer.getURL(
- new OpenLayers.Bounds(loc.lon, loc.lat, loc.lon, loc.lat)
- );
- var params = OpenLayers.Util.getParameters(getTileUrl);
- var tileInfo = layer.getTileInfo(loc);
- OpenLayers.Util.extend(params, {
- service: "WMTS",
- version: layer.version,
- request: "GetFeatureInfo",
- infoFormat: this.infoFormat,
- i: tileInfo.i,
- j: tileInfo.j
- });
- OpenLayers.Util.applyDefaults(params, this.vendorParams);
- return {
- url: OpenLayers.Util.isArray(layer.url) ? layer.url[0] : layer.url,
- params: OpenLayers.Util.upperCaseObject(params),
- callback: function(request) {
- this.handleResponse(xy, request, layer);
- },
- scope: this
- };
+ parseFeatures: function(request) {
+ var doc = request.responseXML;
+ if (!doc || !doc.documentElement) {
+ doc = request.responseText;
+ }
+ if (!doc || doc.length <= 0) {
+ return null;
+ }
+ return this.format.read(doc);
},
/**
- * Method: request
- * Sends a GetFeatureInfo request to the WMTS
- *
+ * APIMethod: commit
+ * Iterate over each feature and take action based on the feature state.
+ * Possible actions are create, update and delete.
+ *
* Parameters:
- * xy - {<OpenLayers.Pixel>} The position on the map where the mouse event
- * occurred.
- * options - {Object} additional options for this method.
- *
+ * features - {Array({<OpenLayers.Feature.Vector>})}
+ * options - {Object} Optional object for setting up intermediate commit
+ * callbacks.
+ *
* Valid options:
- * - *hover* {Boolean} true if we do the request for the hover handler
+ * create - {Object} Optional object to be passed to the <create> method.
+ * update - {Object} Optional object to be passed to the <update> method.
+ * delete - {Object} Optional object to be passed to the <delete> method.
+ * callback - {Function} Optional function to be called when the commit
+ * is complete.
+ * scope - {Object} Optional object to be set as the scope of the callback.
+ *
+ * Returns:
+ * {Array(<OpenLayers.Protocol.Response>)} An array of response objects,
+ * one per request made to the server, each object's "priv" property
+ * references the corresponding HTTP request.
*/
- request: function(xy, options) {
- options = options || {};
- var layers = this.findLayers();
- if (layers.length > 0) {
- var issue, layer;
- for (var i=0, len=layers.length; i<len; i++) {
- layer = layers[i];
- issue = this.events.triggerEvent("beforegetfeatureinfo", {
- xy: xy,
- layer: layer
- });
- if (issue !== false) {
- ++this.pending;
- var requestOptions = this.buildRequestOptions(layer, xy);
- var request = OpenLayers.Request.GET(requestOptions);
- if (options.hover === true) {
- this.hoverRequest = request;
- }
- }
+ commit: function(features, options) {
+ options = OpenLayers.Util.applyDefaults(options, this.options);
+ var resp = [], nResponses = 0;
+
+ // Divide up features before issuing any requests. This properly
+ // counts requests in the event that any responses come in before
+ // all requests have been issued.
+ var types = {};
+ types[OpenLayers.State.INSERT] = [];
+ types[OpenLayers.State.UPDATE] = [];
+ types[OpenLayers.State.DELETE] = [];
+ var feature, list, requestFeatures = [];
+ for(var i=0, len=features.length; i<len; ++i) {
+ feature = features[i];
+ list = types[feature.state];
+ if(list) {
+ list.push(feature);
+ requestFeatures.push(feature);
}
- if (this.pending > 0) {
- OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
+ }
+ // tally up number of requests
+ var nRequests = (types[OpenLayers.State.INSERT].length > 0 ? 1 : 0) +
+ types[OpenLayers.State.UPDATE].length +
+ types[OpenLayers.State.DELETE].length;
+
+ // This response will be sent to the final callback after all the others
+ // have been fired.
+ var success = true;
+ var finalResponse = new OpenLayers.Protocol.Response({
+ reqFeatures: requestFeatures
+ });
+
+ function insertCallback(response) {
+ var len = response.features ? response.features.length : 0;
+ var fids = new Array(len);
+ for(var i=0; i<len; ++i) {
+ fids[i] = response.features[i].fid;
+ }
+ finalResponse.insertIds = fids;
+ callback.apply(this, [response]);
+ }
+
+ function callback(response) {
+ this.callUserCallback(response, options);
+ success = success && response.success();
+ nResponses++;
+ if (nResponses >= nRequests) {
+ if (options.callback) {
+ finalResponse.code = success ?
+ OpenLayers.Protocol.Response.SUCCESS :
+ OpenLayers.Protocol.Response.FAILURE;
+ options.callback.apply(options.scope, [finalResponse]);
+ }
}
}
+
+ // start issuing requests
+ var queue = types[OpenLayers.State.INSERT];
+ if(queue.length > 0) {
+ resp.push(this.create(
+ queue, OpenLayers.Util.applyDefaults(
+ {callback: insertCallback, scope: this}, options.create
+ )
+ ));
+ }
+ queue = types[OpenLayers.State.UPDATE];
+ for(var i=queue.length-1; i>=0; --i) {
+ resp.push(this.update(
+ queue[i], OpenLayers.Util.applyDefaults(
+ {callback: callback, scope: this}, options.update
+ ))
+ );
+ }
+ queue = types[OpenLayers.State.DELETE];
+ for(var i=queue.length-1; i>=0; --i) {
+ resp.push(this["delete"](
+ queue[i], OpenLayers.Util.applyDefaults(
+ {callback: callback, scope: this}, options["delete"]
+ ))
+ );
+ }
+ return resp;
},
/**
- * Method: handleResponse
- * Handler for the GetFeatureInfo response.
- *
+ * APIMethod: abort
+ * Abort an ongoing request, the response object passed to
+ * this method must come from this HTTP protocol (as a result
+ * of a create, read, update, delete or commit operation).
+ *
* Parameters:
- * xy - {<OpenLayers.Pixel>} The position on the map where the mouse event
- * occurred.
- * request - {XMLHttpRequest} The request object.
- * layer - {<OpenLayers.Layer.WMTS>} The queried layer.
+ * response - {<OpenLayers.Protocol.Response>}
*/
- handleResponse: function(xy, request, layer) {
- --this.pending;
- if (this.pending <= 0) {
- OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
- this.pending = 0;
+ abort: function(response) {
+ if (response) {
+ response.priv.abort();
}
- if (request.status && (request.status < 200 || request.status >= 300)) {
- this.events.triggerEvent("exception", {
- xy: xy,
- request: request,
- layer: layer
- });
- } else {
- var doc = request.responseXML;
- if (!doc || !doc.documentElement) {
- doc = request.responseText;
- }
- var features, except;
- try {
- features = this.format.read(doc);
- } catch (error) {
- except = true;
- this.events.triggerEvent("exception", {
- xy: xy,
- request: request,
- error: error,
- layer: layer
+ },
+
+ /**
+ * Method: callUserCallback
+ * This method is used from within the commit method each time an
+ * an HTTP response is received from the server, it is responsible
+ * for calling the user-supplied callbacks.
+ *
+ * Parameters:
+ * resp - {<OpenLayers.Protocol.Response>}
+ * options - {Object} The map of options passed to the commit call.
+ */
+ callUserCallback: function(resp, options) {
+ var opt = options[resp.requestType];
+ if(opt && opt.callback) {
+ opt.callback.call(opt.scope, resp);
+ }
+ },
+
+ CLASS_NAME: "OpenLayers.Protocol.HTTP"
+});
+/* ======================================================================
+ OpenLayers/Protocol/WFS/v2_0_0.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/Protocol/WFS/v1.js
+ * @requires OpenLayers/Format/WFST/v2_0_0.js
+ */
+
+/**
+ * Class: OpenLayers.Protocol.WFS.v2_0_0
+ * A WFS v2.0.0 protocol for vector layers. Create a new instance with the
+ * <OpenLayers.Protocol.WFS.v2_0_0> constructor.
+ *
+ * Differences from the v1.0.0 protocol:
+ * - uses Filter Encoding 1.1.0 instead of 1.0.0
+ * - uses GML 3 instead of 2 if no format is provided
+ *
+ * Inherits from:
+ * - <OpenLayers.Protocol.WFS.v1>
+ */
+OpenLayers.Protocol.WFS.v2_0_0 = OpenLayers.Class(OpenLayers.Protocol.WFS.v1, {
+
+ /**
+ * Property: version
+ * {String} WFS version number.
+ */
+ version: "2.0.0",
+
+ /**
+ * Constructor: OpenLayers.Protocol.WFS.v2_0_0
+ * A class for giving layers WFS v2.0.0 protocol.
+ *
+ * Parameters:
+ * options - {Object} Optional object whose properties will be set on the
+ * instance.
+ *
+ * Valid options properties:
+ * featureType - {String} Local (without prefix) feature typeName (required).
+ * featureNS - {String} Feature namespace (optional).
+ * featurePrefix - {String} Feature namespace alias (optional - only used
+ * if featureNS is provided). Default is 'feature'.
+ * geometryName - {String} Name of geometry attribute. Default is 'the_geom'.
+ * outputFormat - {String} Optional output format to use for WFS GetFeature
+ * requests. This can be any format advertized by the WFS's
+ * GetCapabilities response. If set, an appropriate readFormat also
+ * has to be provided, unless outputFormat is GML3, GML2 or JSON.
+ * readFormat - {<OpenLayers.Format>} An appropriate format parser if
+ * outputFormat is none of GML3, GML2 or JSON.
+ */
+ initialize: function(options) {
+ OpenLayers.Protocol.WFS.v1.prototype.initialize.apply(this, arguments);
+ if (this.outputFormat && !this.readFormat) {
+ if (this.outputFormat.toLowerCase() == "gml3") {
+ this.readFormat = new OpenLayers.Format.GML.v3({
+ featureType: this.featureType,
+ featureNS: this.featureNS,
+ geometryName: this.geometryName
});
+ } else if (this.outputFormat.toLowerCase() == "json") {
+ this.readFormat = new OpenLayers.Format.GeoJSON();
}
- if (!except) {
- this.events.triggerEvent("getfeatureinfo", {
- text: request.responseText,
- features: features,
- request: request,
- xy: xy,
- layer: layer
- });
- }
}
},
-
- CLASS_NAME: "OpenLayers.Control.WMTSGetFeatureInfo"
+
+ CLASS_NAME: "OpenLayers.Protocol.WFS.v2_0_0"
});
/* ======================================================================
OpenLayers/Protocol/CSW/v2_0_2.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -76931,11 +79809,11 @@
});
/* ======================================================================
OpenLayers/Control/SLDSelect.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -77502,11 +80380,11 @@
});
/* ======================================================================
OpenLayers/Control/Graticule.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -77880,14 +80758,727 @@
CLASS_NAME: "OpenLayers.Control.Graticule"
});
/* ======================================================================
+ OpenLayers/Control/DragFeature.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/Control.js
+ * @requires OpenLayers/Handler/Drag.js
+ * @requires OpenLayers/Handler/Feature.js
+ */
+
+/**
+ * Class: OpenLayers.Control.DragFeature
+ * The DragFeature control moves a feature with a drag of the mouse. Create a
+ * new control with the <OpenLayers.Control.DragFeature> constructor.
+ *
+ * Inherits From:
+ * - <OpenLayers.Control>
+ */
+OpenLayers.Control.DragFeature = OpenLayers.Class(OpenLayers.Control, {
+
+ /**
+ * APIProperty: geometryTypes
+ * {Array(String)} To restrict dragging to a limited set of geometry types,
+ * send a list of strings corresponding to the geometry class names.
+ */
+ geometryTypes: null,
+
+ /**
+ * APIProperty: onStart
+ * {Function} Define this function if you want to know when a drag starts.
+ * The function should expect to receive two arguments: the feature
+ * that is about to be dragged and the pixel location of the mouse.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>} The feature that is about to be
+ * dragged.
+ * pixel - {<OpenLayers.Pixel>} The pixel location of the mouse.
+ */
+ onStart: function(feature, pixel) {},
+
+ /**
+ * APIProperty: onDrag
+ * {Function} Define this function if you want to know about each move of a
+ * feature. The function should expect to receive two arguments: the
+ * feature that is being dragged and the pixel location of the mouse.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>} The feature that was dragged.
+ * pixel - {<OpenLayers.Pixel>} The pixel location of the mouse.
+ */
+ onDrag: function(feature, pixel) {},
+
+ /**
+ * APIProperty: onComplete
+ * {Function} Define this function if you want to know when a feature is
+ * done dragging. The function should expect to receive two arguments:
+ * the feature that is being dragged and the pixel location of the
+ * mouse.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>} The feature that was dragged.
+ * pixel - {<OpenLayers.Pixel>} The pixel location of the mouse.
+ */
+ onComplete: function(feature, pixel) {},
+
+ /**
+ * APIProperty: onEnter
+ * {Function} Define this function if you want to know when the mouse
+ * goes over a feature and thereby makes this feature a candidate
+ * for dragging.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>} The feature that is ready
+ * to be dragged.
+ */
+ onEnter: function(feature) {},
+
+ /**
+ * APIProperty: onLeave
+ * {Function} Define this function if you want to know when the mouse
+ * goes out of the feature that was dragged.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>} The feature that was dragged.
+ */
+ onLeave: function(feature) {},
+
+ /**
+ * APIProperty: documentDrag
+ * {Boolean} If set to true, mouse dragging will continue even if the
+ * mouse cursor leaves the map viewport. Default is false.
+ */
+ documentDrag: false,
+
+ /**
+ * Property: layer
+ * {<OpenLayers.Layer.Vector>}
+ */
+ layer: null,
+
+ /**
+ * Property: feature
+ * {<OpenLayers.Feature.Vector>}
+ */
+ feature: null,
+
+ /**
+ * Property: dragCallbacks
+ * {Object} The functions that are sent to the drag handler for callback.
+ */
+ dragCallbacks: {},
+
+ /**
+ * Property: featureCallbacks
+ * {Object} The functions that are sent to the feature handler for callback.
+ */
+ featureCallbacks: {},
+
+ /**
+ * Property: lastPixel
+ * {<OpenLayers.Pixel>}
+ */
+ lastPixel: null,
+
+ /**
+ * Constructor: OpenLayers.Control.DragFeature
+ * Create a new control to drag features.
+ *
+ * Parameters:
+ * layer - {<OpenLayers.Layer.Vector>} The layer containing features to be
+ * dragged.
+ * options - {Object} Optional object whose properties will be set on the
+ * control.
+ */
+ initialize: function(layer, options) {
+ OpenLayers.Control.prototype.initialize.apply(this, [options]);
+ this.layer = layer;
+ this.handlers = {
+ drag: new OpenLayers.Handler.Drag(
+ this, OpenLayers.Util.extend({
+ down: this.downFeature,
+ move: this.moveFeature,
+ up: this.upFeature,
+ out: this.cancel,
+ done: this.doneDragging
+ }, this.dragCallbacks), {
+ documentDrag: this.documentDrag
+ }
+ ),
+ feature: new OpenLayers.Handler.Feature(
+ this, this.layer, OpenLayers.Util.extend({
+ // 'click' and 'clickout' callback are for the mobile
+ // support: no 'over' or 'out' in touch based browsers.
+ click: this.clickFeature,
+ clickout: this.clickoutFeature,
+ over: this.overFeature,
+ out: this.outFeature
+ }, this.featureCallbacks),
+ {geometryTypes: this.geometryTypes}
+ )
+ };
+ },
+
+ /**
+ * Method: clickFeature
+ * Called when the feature handler detects a click-in on a feature.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ clickFeature: function(feature) {
+ if (this.handlers.feature.touch && !this.over && this.overFeature(feature)) {
+ this.handlers.drag.dragstart(this.handlers.feature.evt);
+ // to let the events propagate to the feature handler (click callback)
+ this.handlers.drag.stopDown = false;
+ }
+ },
+
+ /**
+ * Method: clickoutFeature
+ * Called when the feature handler detects a click-out on a feature.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>}
+ */
+ clickoutFeature: function(feature) {
+ if (this.handlers.feature.touch && this.over) {
+ this.outFeature(feature);
+ this.handlers.drag.stopDown = true;
+ }
+ },
+
+ /**
+ * APIMethod: destroy
+ * Take care of things that are not handled in superclass
+ */
+ destroy: function() {
+ this.layer = null;
+ OpenLayers.Control.prototype.destroy.apply(this, []);
+ },
+
+ /**
+ * APIMethod: activate
+ * Activate the control and the feature handler.
+ *
+ * Returns:
+ * {Boolean} Successfully activated the control and feature handler.
+ */
+ activate: function() {
+ return (this.handlers.feature.activate() &&
+ OpenLayers.Control.prototype.activate.apply(this, arguments));
+ },
+
+ /**
+ * APIMethod: deactivate
+ * Deactivate the control and all handlers.
+ *
+ * Returns:
+ * {Boolean} Successfully deactivated the control.
+ */
+ deactivate: function() {
+ // the return from the handlers is unimportant in this case
+ this.handlers.drag.deactivate();
+ this.handlers.feature.deactivate();
+ this.feature = null;
+ this.dragging = false;
+ this.lastPixel = null;
+ OpenLayers.Element.removeClass(
+ this.map.viewPortDiv, this.displayClass + "Over"
+ );
+ return OpenLayers.Control.prototype.deactivate.apply(this, arguments);
+ },
+
+ /**
+ * Method: overFeature
+ * Called when the feature handler detects a mouse-over on a feature.
+ * This activates the drag handler.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>} The selected feature.
+ *
+ * Returns:
+ * {Boolean} Successfully activated the drag handler.
+ */
+ overFeature: function(feature) {
+ var activated = false;
+ if(!this.handlers.drag.dragging) {
+ this.feature = feature;
+ this.handlers.drag.activate();
+ activated = true;
+ this.over = true;
+ OpenLayers.Element.addClass(this.map.viewPortDiv, this.displayClass + "Over");
+ this.onEnter(feature);
+ } else {
+ if(this.feature.id == feature.id) {
+ this.over = true;
+ } else {
+ this.over = false;
+ }
+ }
+ return activated;
+ },
+
+ /**
+ * Method: downFeature
+ * Called when the drag handler detects a mouse-down.
+ *
+ * Parameters:
+ * pixel - {<OpenLayers.Pixel>} Location of the mouse event.
+ */
+ downFeature: function(pixel) {
+ this.lastPixel = pixel;
+ this.onStart(this.feature, pixel);
+ },
+
+ /**
+ * Method: moveFeature
+ * Called when the drag handler detects a mouse-move. Also calls the
+ * optional onDrag method.
+ *
+ * Parameters:
+ * pixel - {<OpenLayers.Pixel>} Location of the mouse event.
+ */
+ moveFeature: function(pixel) {
+ var res = this.map.getResolution();
+ this.feature.geometry.move(res * (pixel.x - this.lastPixel.x),
+ res * (this.lastPixel.y - pixel.y));
+ this.layer.drawFeature(this.feature);
+ this.lastPixel = pixel;
+ this.onDrag(this.feature, pixel);
+ },
+
+ /**
+ * Method: upFeature
+ * Called when the drag handler detects a mouse-up.
+ *
+ * Parameters:
+ * pixel - {<OpenLayers.Pixel>} Location of the mouse event.
+ */
+ upFeature: function(pixel) {
+ if(!this.over) {
+ this.handlers.drag.deactivate();
+ }
+ },
+
+ /**
+ * Method: doneDragging
+ * Called when the drag handler is done dragging.
+ *
+ * Parameters:
+ * pixel - {<OpenLayers.Pixel>} The last event pixel location. If this event
+ * came from a mouseout, this may not be in the map viewport.
+ */
+ doneDragging: function(pixel) {
+ this.onComplete(this.feature, pixel);
+ },
+
+ /**
+ * Method: outFeature
+ * Called when the feature handler detects a mouse-out on a feature.
+ *
+ * Parameters:
+ * feature - {<OpenLayers.Feature.Vector>} The feature that the mouse left.
+ */
+ outFeature: function(feature) {
+ if(!this.handlers.drag.dragging) {
+ this.over = false;
+ this.handlers.drag.deactivate();
+ OpenLayers.Element.removeClass(
+ this.map.viewPortDiv, this.displayClass + "Over"
+ );
+ this.onLeave(feature);
+ this.feature = null;
+ } else {
+ if(this.feature.id == feature.id) {
+ this.over = false;
+ }
+ }
+ },
+
+ /**
+ * Method: cancel
+ * Called when the drag handler detects a mouse-out (from the map viewport).
+ */
+ cancel: function() {
+ this.handlers.drag.deactivate();
+ this.over = false;
+ },
+
+ /**
+ * Method: setMap
+ * Set the map property for the control and all handlers.
+ *
+ * Parameters:
+ * map - {<OpenLayers.Map>} The control's map.
+ */
+ setMap: function(map) {
+ this.handlers.drag.setMap(map);
+ this.handlers.feature.setMap(map);
+ OpenLayers.Control.prototype.setMap.apply(this, arguments);
+ },
+
+ CLASS_NAME: "OpenLayers.Control.DragFeature"
+});
+/* ======================================================================
+ Rico/Corner.js
+ ====================================================================== */
+
+/**
+ * @requires OpenLayers/Console.js
+ * @requires Rico/Color.js
+ */
+
+
+/*
+ * This file has been edited substantially from the Rico-released
+ * version by the OpenLayers development team.
+ *
+ * Copyright 2005 Sabre Airline Solutions
+ *
+ * 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.
+ *
+ */
+
+OpenLayers.Console.warn("OpenLayers.Rico is deprecated");
+
+OpenLayers.Rico = OpenLayers.Rico || {};
+OpenLayers.Rico.Corner = {
+
+ round: function(e, options) {
+ e = OpenLayers.Util.getElement(e);
+ this._setOptions(options);
+
+ var color = this.options.color;
+ if ( this.options.color == "fromElement" ) {
+ color = this._background(e);
+ }
+ var bgColor = this.options.bgColor;
+ if ( this.options.bgColor == "fromParent" ) {
+ bgColor = this._background(e.offsetParent);
+ }
+ this._roundCornersImpl(e, color, bgColor);
+ },
+
+ /** This is a helper function to change the background
+ * color of <div> that has had Rico rounded corners added.
+ *
+ * It seems we cannot just set the background color for the
+ * outer <div> so each <span> element used to create the
+ * corners must have its background color set individually.
+ *
+ * @param {DOM} theDiv - A child of the outer <div> that was
+ * supplied to the `round` method.
+ *
+ * @param {String} newColor - The new background color to use.
+ */
+ changeColor: function(theDiv, newColor) {
+
+ theDiv.style.backgroundColor = newColor;
+
+ var spanElements = theDiv.parentNode.getElementsByTagName("span");
+
+ for (var currIdx = 0; currIdx < spanElements.length; currIdx++) {
+ spanElements[currIdx].style.backgroundColor = newColor;
+ }
+ },
+
+
+ /** This is a helper function to change the background
+ * opacity of <div> that has had Rico rounded corners added.
+ *
+ * See changeColor (above) for algorithm explanation
+ *
+ * @param {DOM} theDiv A child of the outer <div> that was
+ * supplied to the `round` method.
+ *
+ * @param {int} newOpacity The new opacity to use (0-1).
+ */
+ changeOpacity: function(theDiv, newOpacity) {
+
+ 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 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 <div> that was
+ * supplied to the `round` method.
+ *
+ * @param {Object} options - list of options
+ */
+ reRound: function(theDiv, options) {
+
+ 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);
+ }
+ },
+
+ _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 = "<div " + style + ">" + el.innerHTML + "</div>";
+ },
+
+ _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"));
+ }
+ el.style.paddingTop = 0;
+ el.insertBefore(corner,el.firstChild);
+ },
+
+ _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);
+ },
+
+ _createCorner: function(bgColor) {
+ var corner = document.createElement("div");
+ corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor);
+ return corner;
+ },
+
+ _createCornerSlice: function(color,bgColor, n, position) {
+ var slice = document.createElement("span");
+
+ var inStyle = slice.style;
+ inStyle.backgroundColor = color;
+ inStyle.display = "block";
+ inStyle.height = "1px";
+ inStyle.overflow = "hidden";
+ inStyle.fontSize = "1px";
+
+ 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";
+ }
+
+ if ( !this.options.compact && (n == (this.options.numSlices-1)) ) {
+ inStyle.height = "2px";
+ }
+ this._setMargin(slice, n, position);
+ this._setBorder(slice, n, position);
+ return slice;
+ },
+
+ _setOptions: function(options) {
+ this.options = {
+ corners : "all",
+ color : "fromElement",
+ bgColor : "fromParent",
+ blend : true,
+ border : false,
+ compact : false
+ };
+ OpenLayers.Util.extend(this.options, options || {});
+
+ this.options.numSlices = this.options.compact ? 2 : 4;
+ if ( this._isTransparent() ) {
+ this.options.blend = false;
+ }
+ },
+
+ _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 "";
+ },
+
+ _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 "";
+ }
+
+ if(this.options.corners.indexOf("bl") >=0) {
+ return "left";
+ } else if(this.options.corners.indexOf("br")>=0) {
+ return "right";
+ }
+ return "";
+ },
+
+ _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 "";
+ }
+ },
+
+
+ _setMargin: function(el, n, corners) {
+ var marginSize = this._marginSize(n);
+ var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
+
+ 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";
+ }
+ },
+
+ _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";
+ }
+ },
+
+ _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];
+ }
+ },
+
+ _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;
+ },
+
+ _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/Layer/UTFGrid.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -77927,11 +81518,11 @@
*/
OpenLayers.Layer.UTFGrid = OpenLayers.Class(OpenLayers.Layer.XYZ, {
/**
* APIProperty: isBaseLayer
- * Default is true, as this is designed to be a base tile source.
+ * Default is false, as UTFGrids are designed to be a transparent overlay layer.
*/
isBaseLayer: false,
/**
* APIProperty: projection
@@ -77994,10 +81585,16 @@
);
this.tileOptions = OpenLayers.Util.extend({
utfgridResolution: this.utfgridResolution
}, this.tileOptions);
},
+
+ /**
+ * Method: createBackBuffer
+ * The UTFGrid cannot create a back buffer, so this method is overriden.
+ */
+ createBackBuffer: function() {},
/**
* APIMethod: clone
* Create a clone of this layer
*
@@ -78065,21 +81662,22 @@
});
/* ======================================================================
OpenLayers/TileManager.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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/Layer/Grid.js
* @requires OpenLayers/Util.js
* @requires OpenLayers/BaseTypes.js
* @requires OpenLayers/BaseTypes/Element.js
+ * @requires OpenLayers/Layer/Grid.js
+ * @requires OpenLayers/Tile/Image.js
*/
/**
* Class: OpenLayers.TileManager
* Provides queueing of image requests and caching of image elements.
@@ -78101,10 +81699,24 @@
* cache for fast reuse. Default is 256.
*/
cacheSize: 256,
/**
+ * APIProperty: tilesPerFrame
+ * {Number} Number of queued tiles to load per frame (see <frameDelay>).
+ * Default is 2.
+ */
+ tilesPerFrame: 2,
+
+ /**
+ * APIProperty: frameDelay
+ * {Number} Delay between tile loading frames (see <tilesPerFrame>) in
+ * milliseconds. Default is 16.
+ */
+ frameDelay: 16,
+
+ /**
* APIProperty: moveDelay
* {Number} Delay in milliseconds after a map's move event before loading
* tiles. Default is 100.
*/
moveDelay: 100,
@@ -78170,11 +81782,11 @@
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
addMap: function(map) {
- if (this._destroyed) {
+ if (this._destroyed || !OpenLayers.Layer.Grid) {
return;
}
this.maps.push(map);
this.tileQueue[map.id] = [];
for (var i=0, ii=map.layers.length; i<ii; ++i) {
@@ -78196,11 +81808,11 @@
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
removeMap: function(map) {
- if (this._destroyed) {
+ if (this._destroyed || !OpenLayers.Layer.Grid) {
return;
}
window.clearTimeout(this.tileQueueId[map.id]);
if (map.layers) {
for (var i=0, ii=map.layers.length; i<ii; ++i) {
@@ -78228,11 +81840,11 @@
*
* Parameters:
* evt - {Object} Listener argument
*/
move: function(evt) {
- this.updateTimeout(evt.object, this.moveDelay);
+ this.updateTimeout(evt.object, this.moveDelay, true);
},
/**
* Method: zoomEnd
* Handles the map's zoomEnd event
@@ -78250,11 +81862,11 @@
*
* Parameters:
* evt - {Object} Listener argument
*/
changeLayer: function(evt) {
- if (evt.property === 'params') {
+ if (evt.property === 'visibility' || evt.property === 'params') {
this.updateTimeout(evt.object, 0);
}
},
/**
@@ -78267,19 +81879,20 @@
addLayer: function(evt) {
var layer = evt.layer;
if (layer instanceof OpenLayers.Layer.Grid) {
layer.events.on({
addtile: this.addTile,
+ refresh: this.handleLayerRefresh,
retile: this.clearTileQueue,
scope: this
});
var i, j, tile;
for (i=layer.grid.length-1; i>=0; --i) {
for (j=layer.grid[i].length-1; j>=0; --j) {
tile = layer.grid[i][j];
this.addTile({tile: tile});
- if (tile.url) {
+ if (tile.url && !tile.imgDiv) {
this.manageTileCache({object: tile});
}
}
}
}
@@ -78297,43 +81910,73 @@
if (layer instanceof OpenLayers.Layer.Grid) {
this.clearTileQueue({object: layer});
if (layer.events) {
layer.events.un({
addtile: this.addTile,
+ refresh: this.handleLayerRefresh,
retile: this.clearTileQueue,
scope: this
});
}
if (layer.grid) {
var i, j, tile;
for (i=layer.grid.length-1; i>=0; --i) {
for (j=layer.grid[i].length-1; j>=0; --j) {
tile = layer.grid[i][j];
this.unloadTile({object: tile});
- if (tile.url) {
- this.manageTileCache({object: tile});
- }
}
}
}
}
},
+
+ /**
+ * Method: handleLayerRefresh
+ * Clears the cache when a redraw is forced on a layer
+ *
+ * Parameters:
+ * evt - {Object} The listener argument
+ */
+ handleLayerRefresh: function(evt) {
+ var layer = evt.object;
+ if (layer.grid) {
+ var i, j, tile;
+ for (i=layer.grid.length-1; i>=0; --i) {
+ for (j=layer.grid[i].length-1; j>=0; --j) {
+ tile = layer.grid[i][j];
+ OpenLayers.Util.removeItem(this.tileCacheIndex, tile.url);
+ delete this.tileCache[tile.url];
+ }
+ }
+ }
+ },
/**
* Method: updateTimeout
- * Applies the <moveDelay> or <zoomDelay> to the <drawTilesFromQueue> loop.
+ * Applies the <moveDelay> or <zoomDelay> to the <drawTilesFromQueue> loop,
+ * and schedules more queue processing after <frameDelay> if there are still
+ * tiles in the queue.
*
* Parameters:
* map - {<OpenLayers.Map>} The map to update the timeout for
* delay - {Number} The delay to apply
+ * nice - {Boolean} If true, the timeout function will only be created if
+ * the tilequeue is not empty. This is used by the move handler to
+ * avoid impacts on dragging performance. For other events, the tile
+ * queue may not be populated yet, so we need to set the timer
+ * regardless of the queue size.
*/
- updateTimeout: function(map, delay) {
+ updateTimeout: function(map, delay, nice) {
window.clearTimeout(this.tileQueueId[map.id]);
- if (this.tileQueue[map.id].length) {
+ var tileQueue = this.tileQueue[map.id];
+ if (!nice || tileQueue.length) {
this.tileQueueId[map.id] = window.setTimeout(
OpenLayers.Function.bind(function() {
this.drawTilesFromQueue(map);
+ if (tileQueue.length) {
+ this.updateTimeout(map, this.frameDelay);
+ }
}, this), delay
);
}
},
@@ -78343,17 +81986,22 @@
*
* Parameters:
* evt - {Object} The listener argument
*/
addTile: function(evt) {
- evt.tile.events.on({
- beforedraw: this.queueTileDraw,
- beforeload: this.manageTileCache,
- loadend: this.addToCache,
- unload: this.unloadTile,
- scope: this
- });
+ if (evt.tile instanceof OpenLayers.Tile.Image) {
+ evt.tile.events.on({
+ beforedraw: this.queueTileDraw,
+ beforeload: this.manageTileCache,
+ loadend: this.addToCache,
+ unload: this.unloadTile,
+ scope: this
+ });
+ } else {
+ // Layer has the wrong tile type, so don't handle it any longer
+ this.removeLayer({layer: evt.tile.layer});
+ }
},
/**
* Method: unloadTile
* Listener for the tile's unload event
@@ -78382,13 +82030,20 @@
*/
queueTileDraw: function(evt) {
var tile = evt.object;
var queued = false;
var layer = tile.layer;
+ var url = layer.getURL(tile.bounds);
+ var img = this.tileCache[url];
+ if (img && img.className !== 'olTileImage') {
+ // cached image no longer valid, e.g. because we're olTileReplacing
+ delete this.tileCache[url];
+ OpenLayers.Util.removeItem(this.tileCacheIndex, url);
+ img = null;
+ }
// queue only if image with same url not cached already
- if (layer.url && (layer.async ||
- !this.tileCache[layer.getURL(tile.bounds)])) {
+ if (layer.url && (layer.async || !img)) {
// add to queue only if not in queue already
var tileQueue = this.tileQueue[layer.map.id];
if (!~OpenLayers.Util.indexOf(tileQueue, tile)) {
tileQueue.push(tile);
}
@@ -78401,12 +82056,15 @@
* Method: drawTilesFromQueue
* Draws tiles from the tileQueue, and unqueues the tiles
*/
drawTilesFromQueue: function(map) {
var tileQueue = this.tileQueue[map.id];
- while (tileQueue.length) {
+ var limit = this.tilesPerFrame;
+ var animating = map.zoomTween && map.zoomTween.playing;
+ while (!animating && tileQueue.length && limit) {
tileQueue.shift().draw(true);
+ --limit;
}
},
/**
* Method: manageTileCache
@@ -78416,22 +82074,27 @@
* evt - {Object} Listener argument of the tile's beforeload event
*/
manageTileCache: function(evt) {
var tile = evt.object;
var img = this.tileCache[tile.url];
- // only use image from cache if it is not on a layer already
- if (img && (!img.parentNode ||
- OpenLayers.Element.hasClass(img.parentNode, 'olBackBuffer'))) {
- if (tile.layer.backBuffer) {
- img.style.opacity = 0;
- img.style.visibility = 'hidden';
- }
- tile.setImage(img);
- // LRU - move tile to the end of the array to mark it as the most
- // recently used
- OpenLayers.Util.removeItem(this.tileCacheIndex, tile.url);
- this.tileCacheIndex.push(tile.url);
+ if (img) {
+ // if image is on its layer's backbuffer, remove it from backbuffer
+ if (img.parentNode &&
+ OpenLayers.Element.hasClass(img.parentNode, 'olBackBuffer')) {
+ img.parentNode.removeChild(img);
+ img.id = null;
+ }
+ // only use image from cache if it is not on a layer already
+ if (!img.parentNode) {
+ img.style.visibility = 'hidden';
+ img.style.opacity = 0;
+ tile.setImage(img);
+ // LRU - move tile to the end of the array to mark it as the most
+ // recently used
+ OpenLayers.Util.removeItem(this.tileCacheIndex, tile.url);
+ this.tileCacheIndex.push(tile.url);
+ }
}
},
/**
* Method: addToCache
@@ -78488,11 +82151,11 @@
});
/* ======================================================================
OpenLayers/Protocol/Script.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -78869,11 +82532,11 @@
})();
/* ======================================================================
OpenLayers/Control/TransformFeature.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -79497,10 +83160,15 @@
});
/* ======================================================================
OpenLayers/Layer/ArcGISCache.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/Layer/XYZ.js
*/
/**
@@ -79976,11 +83644,11 @@
});
/* ======================================================================
OpenLayers/Control/WMSGetFeatureInfo.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -79993,14 +83661,14 @@
*/
/**
* Class: OpenLayers.Control.WMSGetFeatureInfo
* The WMSGetFeatureInfo control uses a WMS query to get information about a point on the map. The
- * information may be in a display-friendly format such as HTML, or a machine-friendly format such
- * as GML, depending on the server's capabilities and the client's configuration. This control
- * handles click or hover events, attempts to parse the results using an OpenLayers.Format, and
- * fires a 'getfeatureinfo' event with the click position, the raw body of the response, and an
+ * information may be in a display-friendly format such as HTML, or a machine-friendly format such
+ * as GML, depending on the server's capabilities and the client's configuration. This control
+ * handles click or hover events, attempts to parse the results using an OpenLayers.Format, and
+ * fires a 'getfeatureinfo' event with the click position, the raw body of the response, and an
* array of features if it successfully read the response.
*
* Inherits from:
* - <OpenLayers.Control>
*/
@@ -80027,86 +83695,88 @@
* sets the feature_count parameter on WMS GetFeatureInfo
* requests.
*/
maxFeatures: 10,
- /** APIProperty: clickCallback
- * {String} The click callback to register in the
- * {<OpenLayers.Handler.Click>} object created when the hover
- * option is set to false. Default is "click".
+ /**
+ * APIProperty: clickCallback
+ * {String} The click callback to register in the
+ * {<OpenLayers.Handler.Click>} object created when the hover
+ * option is set to false. Default is "click".
*/
clickCallback: "click",
-
- /** APIProperty: output
- * {String} Either "features" or "object". When triggering a
- * getfeatureinfo request should we pass on an array of features
- * or an object with with a "features" property and other properties
- * (such as the url of the WMS). Default is "features".
+
+ /**
+ * APIProperty: output
+ * {String} Either "features" or "object". When triggering a getfeatureinfo
+ * request should we pass on an array of features or an object with with
+ * a "features" property and other properties (such as the url of the
+ * WMS). Default is "features".
*/
output: "features",
-
+
/**
- * Property: layers
+ * APIProperty: layers
* {Array(<OpenLayers.Layer.WMS>)} The layers to query for feature info.
* If omitted, all map WMS layers with a url that matches this <url> or
* <layerUrls> will be considered.
*/
layers: null,
/**
- * Property: queryVisible
+ * APIProperty: queryVisible
* {Boolean} If true, filter out hidden layers when searching the map for
* layers to query. Default is false.
*/
queryVisible: false,
/**
- * Property: url
+ * APIProperty: url
* {String} The URL of the WMS service to use. If not provided, the url
* of the first eligible layer will be used.
*/
url: null,
-
+
/**
- * Property: layerUrls
+ * APIProperty: layerUrls
* {Array(String)} Optional list of urls for layers that should be queried.
* This can be used when the layer url differs from the url used for
* making GetFeatureInfo requests (in the case of a layer using cached
* tiles).
*/
layerUrls: null,
/**
- * Property: infoFormat
- * {String} The mimetype to request from the server. If you are using
- * drillDown mode and have multiple servers that do not share a common
- * infoFormat, you can override the control's infoFormat by providing an
- * INFO_FORMAT parameter in your <OpenLayers.Layer.WMS> instance(s).
+ * APIProperty: infoFormat
+ * {String} The mimetype to request from the server. If you are using
+ * drillDown mode and have multiple servers that do not share a common
+ * infoFormat, you can override the control's infoFormat by providing an
+ * INFO_FORMAT parameter in your <OpenLayers.Layer.WMS> instance(s).
*/
infoFormat: 'text/html',
-
+
/**
- * Property: vendorParams
+ * APIProperty: vendorParams
* {Object} Additional parameters that will be added to the request, for
- * WMS implementations that support them. This could e.g. look like
+ * WMS implementations that support them. This could e.g. look like
* (start code)
* {
* radius: 5
* }
* (end)
*/
vendorParams: {},
-
+
/**
- * Property: format
+ * APIProperty: format
* {<OpenLayers.Format>} A format for parsing GetFeatureInfo responses.
* Default is <OpenLayers.Format.WMSGetFeatureInfo>.
*/
format: null,
-
+
/**
- * Property: formatOptions
+ * APIProperty: formatOptions
* {Object} Optional properties to set on the format (if one is not provided
* in the <format> property.
*/
formatOptions: null,
@@ -80118,25 +83788,25 @@
* "click": {delay: 100},
* "hover": {delay: 300}
* }
* (end)
*/
-
+
/**
* Property: handler
* {Object} Reference to the <OpenLayers.Handler> for this control
*/
handler: null,
-
+
/**
* Property: hoverRequest
* {<OpenLayers.Request>} contains the currently running hover request
* (if any).
*/
hoverRequest: null,
-
- /**
+
+ /**
* APIProperty: events
* {<OpenLayers.Events>} Events instance for listeners and triggering
* control specific events.
*
* Register a listener for a particular event with the following syntax:
@@ -80144,11 +83814,11 @@
* control.events.register(type, obj, listener);
* (end)
*
* Supported event types (in addition to those from <OpenLayers.Control.events>):
* beforegetfeatureinfo - Triggered before the request is sent.
- * The event object has an *xy* property with the position of the
+ * The event object has an *xy* property with the position of the
* mouse click or hover event that triggers the request.
* nogetfeatureinfo - no queryable layers were found.
* getfeatureinfo - Triggered when a GetFeatureInfo response is received.
* The event object has a *text* property with the body of the
* response (String), a *features* property with an array of the
@@ -80162,24 +83832,24 @@
/**
* Constructor: <OpenLayers.Control.WMSGetFeatureInfo>
*
* Parameters:
- * options - {Object}
+ * options - {Object}
*/
initialize: function(options) {
options = options || {};
options.handlerOptions = options.handlerOptions || {};
OpenLayers.Control.prototype.initialize.apply(this, [options]);
-
+
if(!this.format) {
this.format = new OpenLayers.Format.WMSGetFeatureInfo(
options.formatOptions
);
}
-
+
if(this.drillDown === true) {
this.hover = false;
}
if(this.hover) {
@@ -80198,24 +83868,24 @@
this, callbacks, this.handlerOptions.click || {});
}
},
/**
- * Method: getInfoForClick
+ * Method: getInfoForClick
* Called on click
*
* Parameters:
- * evt - {<OpenLayers.Event>}
+ * evt - {<OpenLayers.Event>}
*/
getInfoForClick: function(evt) {
this.events.triggerEvent("beforegetfeatureinfo", {xy: evt.xy});
// Set the cursor to "wait" to tell the user we're working on their
// click.
OpenLayers.Element.addClass(this.map.viewPortDiv, "olCursorWait");
this.request(evt.xy, {});
},
-
+
/**
* Method: getInfoForHover
* Pause callback for the hover handler
*
* Parameters:
@@ -80262,11 +83932,11 @@
}
}
}
return layers;
},
-
+
/**
* Method: urlMatches
* Test to see if the provided url matches either the control <url> or one
* of the <layerUrls>.
*
@@ -80361,11 +84031,11 @@
/**
* Method: getStyleNames
* Gets the STYLES parameter for the layer. Make sure the STYLES parameter
* matches the LAYERS parameter
- *
+ *
* Parameters:
* layer - {<OpenLayers.Layer.WMS>}
*
* Returns:
* {Array(String)} The STYLES parameter
@@ -80379,26 +84049,26 @@
if (layer.params.STYLES) {
styleNames = layer.params.STYLES;
} else {
if (OpenLayers.Util.isArray(layer.params.LAYERS)) {
styleNames = new Array(layer.params.LAYERS.length);
- } else { // Assume it's a String
- styleNames = layer.params.LAYERS.replace(/[^,]/g, "");
+ } else {
+ styleNames = layer.params.LAYERS.toString().replace(/[^,]/g, "");
}
}
return styleNames;
},
/**
* Method: request
* Sends a GetFeatureInfo request to the WMS
- *
+ *
* Parameters:
* clickPosition - {<OpenLayers.Pixel>} The position on the map where the
* mouse event occurred.
* options - {Object} additional options for this method.
- *
+ *
* Valid options:
* - *hover* {Boolean} true if we do the request for the hover handler
*/
request: function(clickPosition, options) {
var layers = this.findLayers();
@@ -80406,17 +84076,17 @@
this.events.triggerEvent("nogetfeatureinfo");
// Reset the cursor.
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
return;
}
-
+
options = options || {};
if(this.drillDown === false) {
var wmsOptions = this.buildWMSOptions(this.url, layers,
- clickPosition, layers[0].params.FORMAT);
+ clickPosition, layers[0].params.FORMAT);
var request = OpenLayers.Request.GET(wmsOptions);
-
+
if (options.hover === true) {
this.hoverRequest = request;
}
} else {
this._requestCount = 0;
@@ -80436,13 +84106,13 @@
}
}
var layers;
for (var url in services) {
layers = services[url];
- var wmsOptions = this.buildWMSOptions(url, layers,
+ var wmsOptions = this.buildWMSOptions(url, layers,
clickPosition, layers[0].params.FORMAT);
- OpenLayers.Request.GET(wmsOptions);
+ OpenLayers.Request.GET(wmsOptions);
}
}
},
/**
@@ -80466,23 +84136,23 @@
});
// Reset the cursor.
OpenLayers.Element.removeClass(this.map.viewPortDiv, "olCursorWait");
},
-
+
/**
* Method: handleResponse
* Handler for the GetFeatureInfo response.
- *
+ *
* Parameters:
* xy - {<OpenLayers.Pixel>} The position on the map where the
* mouse event occurred.
* request - {XMLHttpRequest} The request object.
* url - {String} The url which was used for this request.
*/
handleResponse: function(xy, request, url) {
-
+
var doc = request.responseXML;
if(!doc || !doc.documentElement) {
doc = request.responseText;
}
var features = this.format.read(doc);
@@ -80496,11 +84166,11 @@
);
} else {
this._features = (this._features || []).concat(features);
}
if (this._requestCount === this._numRequests) {
- this.triggerGetFeatureInfo(request, xy, this._features.concat());
+ this.triggerGetFeatureInfo(request, xy, this._features.concat());
delete this._features;
delete this._requestCount;
delete this._numRequests;
}
}
@@ -80510,11 +84180,11 @@
});
/* ======================================================================
OpenLayers/Format/WMSCapabilities/v1_3_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -80544,11 +84214,11 @@
});
/* ======================================================================
OpenLayers/Format/WFS.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -80771,11 +84441,11 @@
});
/* ======================================================================
OpenLayers/Control/UTFGrid.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -81015,11 +84685,11 @@
});
/* ======================================================================
OpenLayers/Format/CQL.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -81471,11 +85141,11 @@
/* ======================================================================
OpenLayers/Control/Split.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -81969,11 +85639,11 @@
});
/* ======================================================================
OpenLayers/Layer/WMTS.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -82235,11 +85905,10 @@
/**
* Method: setMap
*/
setMap: function() {
OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
- this.updateMatrixProperties();
},
/**
* Method: updateMatrixProperties
* Called when map resolution changes to update matrix related properties.
@@ -82484,11 +86153,11 @@
});
/* ======================================================================
OpenLayers/Protocol/SOS/v1_0_0.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -82621,11 +86290,11 @@
});
/* ======================================================================
OpenLayers/Layer/KaMapCache.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -82768,11 +86437,11 @@
});
/* ======================================================================
OpenLayers/Layer/TileCache.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
@@ -82912,11 +86581,11 @@
});
/* ======================================================================
OpenLayers/Format/WMSCapabilities/v1_1_1.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -82976,11 +86645,11 @@
});
/* ======================================================================
OpenLayers/Format/WMSCapabilities/v1_1_1_WMSC.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -83062,803 +86731,14 @@
CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_1_WMSC"
});
/* ======================================================================
- OpenLayers/Control/LayerSwitcher.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/Control.js
- * @requires OpenLayers/Lang.js
- * @requires OpenLayers/Console.js
- * @requires OpenLayers/Events/buttonclick.js
- */
-
-/**
- * Class: OpenLayers.Control.LayerSwitcher
- * The LayerSwitcher control displays a table of contents for the map. This
- * allows the user interface to switch between BaseLasyers and to show or hide
- * Overlays. By default the switcher is shown minimized on the right edge of
- * the map, the user may expand it by clicking on the handle.
- *
- * To create the LayerSwitcher outside of the map, pass the Id of a html div
- * as the first argument to the constructor.
- *
- * Inherits from:
- * - <OpenLayers.Control>
- */
-OpenLayers.Control.LayerSwitcher =
- OpenLayers.Class(OpenLayers.Control, {
-
- /**
- * APIProperty: roundedCorner
- * {Boolean} If true the Rico library is used for rounding the corners
- * of the layer switcher div, defaults to false. *Deprecated*. Use
- * CSS3's border-radius instead. If this option is set to true the
- * Rico/Corner.js script must be loaded in the page, and therefore
- * listed in the build profile.
- *
- */
- roundedCorner: false,
-
- /**
- * APIProperty: roundedCornerColor
- * {String} The color of the rounded corners, only applies if roundedCorner
- * is true, defaults to "darkblue".
- */
- roundedCornerColor: "darkblue",
-
- /**
- * Property: layerStates
- * {Array(Object)} Basically a copy of the "state" of the map's layers
- * the last time the control was drawn. We have this in order to avoid
- * unnecessarily redrawing the control.
- */
- layerStates: null,
-
-
- // DOM Elements
-
- /**
- * Property: layersDiv
- * {DOMElement}
- */
- layersDiv: null,
-
- /**
- * Property: baseLayersDiv
- * {DOMElement}
- */
- baseLayersDiv: null,
-
- /**
- * Property: baseLayers
- * {Array(Object)}
- */
- baseLayers: null,
-
-
- /**
- * Property: dataLbl
- * {DOMElement}
- */
- dataLbl: null,
-
- /**
- * Property: dataLayersDiv
- * {DOMElement}
- */
- dataLayersDiv: null,
-
- /**
- * Property: dataLayers
- * {Array(Object)}
- */
- dataLayers: null,
-
-
- /**
- * Property: minimizeDiv
- * {DOMElement}
- */
- minimizeDiv: null,
-
- /**
- * Property: maximizeDiv
- * {DOMElement}
- */
- maximizeDiv: null,
-
- /**
- * APIProperty: ascending
- * {Boolean}
- */
- ascending: true,
-
- /**
- * Constructor: OpenLayers.Control.LayerSwitcher
- *
- * Parameters:
- * options - {Object}
- */
- initialize: function(options) {
- OpenLayers.Control.prototype.initialize.apply(this, arguments);
- this.layerStates = [];
-
- if(this.roundedCorner) {
- OpenLayers.Console.warn('roundedCorner option is deprecated');
- }
- },
-
- /**
- * APIMethod: destroy
- */
- destroy: function() {
-
- //clear out layers info and unregister their events
- this.clearLayersArray("base");
- this.clearLayersArray("data");
-
- this.map.events.un({
- buttonclick: this.onButtonClick,
- addlayer: this.redraw,
- changelayer: this.redraw,
- removelayer: this.redraw,
- changebaselayer: this.redraw,
- scope: this
- });
- this.events.unregister("buttonclick", this, this.onButtonClick);
-
- OpenLayers.Control.prototype.destroy.apply(this, arguments);
- },
-
- /**
- * Method: setMap
- *
- * Properties:
- * map - {<OpenLayers.Map>}
- */
- setMap: function(map) {
- OpenLayers.Control.prototype.setMap.apply(this, arguments);
-
- this.map.events.on({
- addlayer: this.redraw,
- changelayer: this.redraw,
- removelayer: this.redraw,
- changebaselayer: this.redraw,
- scope: this
- });
- if (this.outsideViewport) {
- this.events.attachToElement(this.div);
- this.events.register("buttonclick", this, this.onButtonClick);
- } else {
- this.map.events.register("buttonclick", this, this.onButtonClick);
- }
- },
-
- /**
- * Method: draw
- *
- * Returns:
- * {DOMElement} A reference to the DIV DOMElement containing the
- * switcher tabs.
- */
- draw: function() {
- OpenLayers.Control.prototype.draw.apply(this);
-
- // create layout divs
- this.loadContents();
-
- // set mode to minimize
- if(!this.outsideViewport) {
- this.minimizeControl();
- }
-
- // populate div with current info
- this.redraw();
-
- return this.div;
- },
-
- /**
- * Method: onButtonClick
- *
- * Parameters:
- * evt - {Event}
- */
- onButtonClick: function(evt) {
- var button = evt.buttonElement;
- if (button === this.minimizeDiv) {
- this.minimizeControl();
- } else if (button === this.maximizeDiv) {
- this.maximizeControl();
- } else if (button._layerSwitcher === this.id) {
- if (button["for"]) {
- button = document.getElementById(button["for"]);
- }
- if (!button.disabled) {
- if (button.type == "radio") {
- button.checked = true;
- this.map.setBaseLayer(this.map.getLayer(button._layer));
- } else {
- button.checked = !button.checked;
- this.updateMap();
- }
- }
- }
- },
-
- /**
- * Method: clearLayersArray
- * User specifies either "base" or "data". we then clear all the
- * corresponding listeners, the div, and reinitialize a new array.
- *
- * Parameters:
- * layersType - {String}
- */
- clearLayersArray: function(layersType) {
- this[layersType + "LayersDiv"].innerHTML = "";
- this[layersType + "Layers"] = [];
- },
-
-
- /**
- * Method: checkRedraw
- * Checks if the layer state has changed since the last redraw() call.
- *
- * Returns:
- * {Boolean} The layer state changed since the last redraw() call.
- */
- checkRedraw: function() {
- var redraw = false;
- if ( !this.layerStates.length ||
- (this.map.layers.length != this.layerStates.length) ) {
- redraw = true;
- } else {
- for (var i=0, len=this.layerStates.length; i<len; i++) {
- var layerState = this.layerStates[i];
- var layer = this.map.layers[i];
- if ( (layerState.name != layer.name) ||
- (layerState.inRange != layer.inRange) ||
- (layerState.id != layer.id) ||
- (layerState.visibility != layer.visibility) ) {
- redraw = true;
- break;
- }
- }
- }
- return redraw;
- },
-
- /**
- * Method: redraw
- * Goes through and takes the current state of the Map and rebuilds the
- * control to display that state. Groups base layers into a
- * radio-button group and lists each data layer with a checkbox.
- *
- * Returns:
- * {DOMElement} A reference to the DIV DOMElement containing the control
- */
- redraw: function() {
- //if the state hasn't changed since last redraw, no need
- // to do anything. Just return the existing div.
- if (!this.checkRedraw()) {
- return this.div;
- }
-
- //clear out previous layers
- this.clearLayersArray("base");
- this.clearLayersArray("data");
-
- var containsOverlays = false;
- var containsBaseLayers = false;
-
- // Save state -- for checking layer if the map state changed.
- // We save this before redrawing, because in the process of redrawing
- // we will trigger more visibility changes, and we want to not redraw
- // and enter an infinite loop.
- var len = this.map.layers.length;
- this.layerStates = new Array(len);
- for (var i=0; i <len; i++) {
- var layer = this.map.layers[i];
- this.layerStates[i] = {
- 'name': layer.name,
- 'visibility': layer.visibility,
- 'inRange': layer.inRange,
- 'id': layer.id
- };
- }
-
- var layers = this.map.layers.slice();
- if (!this.ascending) { layers.reverse(); }
- for(var i=0, len=layers.length; i<len; i++) {
- var layer = layers[i];
- var baseLayer = layer.isBaseLayer;
-
- if (layer.displayInLayerSwitcher) {
-
- if (baseLayer) {
- containsBaseLayers = true;
- } else {
- containsOverlays = true;
- }
-
- // only check a baselayer if it is *the* baselayer, check data
- // layers if they are visible
- var checked = (baseLayer) ? (layer == this.map.baseLayer)
- : layer.getVisibility();
-
- // create input element
- var inputElem = document.createElement("input");
- inputElem.id = this.id + "_input_" + layer.name;
- inputElem.name = (baseLayer) ? this.id + "_baseLayers" : layer.name;
- inputElem.type = (baseLayer) ? "radio" : "checkbox";
- inputElem.value = layer.name;
- inputElem.checked = checked;
- inputElem.defaultChecked = checked;
- inputElem.className = "olButton";
- inputElem._layer = layer.id;
- inputElem._layerSwitcher = this.id;
-
- if (!baseLayer && !layer.inRange) {
- inputElem.disabled = true;
- }
-
- // create span
- var labelSpan = document.createElement("label");
- labelSpan["for"] = inputElem.id;
- OpenLayers.Element.addClass(labelSpan, "labelSpan olButton");
- labelSpan._layer = layer.id;
- labelSpan._layerSwitcher = this.id;
- if (!baseLayer && !layer.inRange) {
- labelSpan.style.color = "gray";
- }
- labelSpan.innerHTML = layer.name;
- labelSpan.style.verticalAlign = (baseLayer) ? "bottom"
- : "baseline";
- // create line break
- var br = document.createElement("br");
-
-
- var groupArray = (baseLayer) ? this.baseLayers
- : this.dataLayers;
- groupArray.push({
- 'layer': layer,
- 'inputElem': inputElem,
- 'labelSpan': labelSpan
- });
-
-
- var groupDiv = (baseLayer) ? this.baseLayersDiv
- : this.dataLayersDiv;
- groupDiv.appendChild(inputElem);
- groupDiv.appendChild(labelSpan);
- groupDiv.appendChild(br);
- }
- }
-
- // if no overlays, dont display the overlay label
- this.dataLbl.style.display = (containsOverlays) ? "" : "none";
-
- // if no baselayers, dont display the baselayer label
- this.baseLbl.style.display = (containsBaseLayers) ? "" : "none";
-
- return this.div;
- },
-
- /**
- * Method: updateMap
- * Cycles through the loaded data and base layer input arrays and makes
- * the necessary calls to the Map object such that that the map's
- * visual state corresponds to what the user has selected in
- * the control.
- */
- updateMap: function() {
-
- // set the newly selected base layer
- for(var i=0, len=this.baseLayers.length; i<len; i++) {
- var layerEntry = this.baseLayers[i];
- if (layerEntry.inputElem.checked) {
- this.map.setBaseLayer(layerEntry.layer, false);
- }
- }
-
- // set the correct visibilities for the overlays
- for(var i=0, len=this.dataLayers.length; i<len; i++) {
- var layerEntry = this.dataLayers[i];
- layerEntry.layer.setVisibility(layerEntry.inputElem.checked);
- }
-
- },
-
- /**
- * Method: maximizeControl
- * Set up the labels and divs for the control
- *
- * Parameters:
- * e - {Event}
- */
- maximizeControl: function(e) {
-
- // set the div's width and height to empty values, so
- // the div dimensions can be controlled by CSS
- this.div.style.width = "";
- this.div.style.height = "";
-
- this.showControls(false);
-
- if (e != null) {
- OpenLayers.Event.stop(e);
- }
- },
-
- /**
- * Method: minimizeControl
- * Hide all the contents of the control, shrink the size,
- * add the maximize icon
- *
- * Parameters:
- * e - {Event}
- */
- minimizeControl: function(e) {
-
- // to minimize the control we set its div's width
- // and height to 0px, we cannot just set "display"
- // to "none" because it would hide the maximize
- // div
- this.div.style.width = "0px";
- this.div.style.height = "0px";
-
- this.showControls(true);
-
- if (e != null) {
- OpenLayers.Event.stop(e);
- }
- },
-
- /**
- * Method: showControls
- * Hide/Show all LayerSwitcher controls depending on whether we are
- * minimized or not
- *
- * Parameters:
- * minimize - {Boolean}
- */
- showControls: function(minimize) {
-
- this.maximizeDiv.style.display = minimize ? "" : "none";
- this.minimizeDiv.style.display = minimize ? "none" : "";
-
- this.layersDiv.style.display = minimize ? "none" : "";
- },
-
- /**
- * Method: loadContents
- * Set up the labels and divs for the control
- */
- loadContents: function() {
-
- // layers list div
- this.layersDiv = document.createElement("div");
- this.layersDiv.id = this.id + "_layersDiv";
- OpenLayers.Element.addClass(this.layersDiv, "layersDiv");
-
- this.baseLbl = document.createElement("div");
- this.baseLbl.innerHTML = OpenLayers.i18n("Base Layer");
- OpenLayers.Element.addClass(this.baseLbl, "baseLbl");
-
- this.baseLayersDiv = document.createElement("div");
- OpenLayers.Element.addClass(this.baseLayersDiv, "baseLayersDiv");
-
- this.dataLbl = document.createElement("div");
- this.dataLbl.innerHTML = OpenLayers.i18n("Overlays");
- OpenLayers.Element.addClass(this.dataLbl, "dataLbl");
-
- this.dataLayersDiv = document.createElement("div");
- OpenLayers.Element.addClass(this.dataLayersDiv, "dataLayersDiv");
-
- if (this.ascending) {
- this.layersDiv.appendChild(this.baseLbl);
- this.layersDiv.appendChild(this.baseLayersDiv);
- this.layersDiv.appendChild(this.dataLbl);
- this.layersDiv.appendChild(this.dataLayersDiv);
- } else {
- this.layersDiv.appendChild(this.dataLbl);
- this.layersDiv.appendChild(this.dataLayersDiv);
- this.layersDiv.appendChild(this.baseLbl);
- this.layersDiv.appendChild(this.baseLayersDiv);
- }
-
- this.div.appendChild(this.layersDiv);
-
- if(this.roundedCorner) {
- OpenLayers.Rico.Corner.round(this.div, {
- corners: "tl bl",
- bgColor: "transparent",
- color: this.roundedCornerColor,
- blend: false
- });
- OpenLayers.Rico.Corner.changeOpacity(this.layersDiv, 0.75);
- }
-
- // maximize button div
- var img = OpenLayers.Util.getImageLocation('layer-switcher-maximize.png');
- this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv(
- "OpenLayers_Control_MaximizeDiv",
- null,
- null,
- img,
- "absolute");
- OpenLayers.Element.addClass(this.maximizeDiv, "maximizeDiv olButton");
- this.maximizeDiv.style.display = "none";
-
- this.div.appendChild(this.maximizeDiv);
-
- // minimize button div
- var img = OpenLayers.Util.getImageLocation('layer-switcher-minimize.png');
- this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv(
- "OpenLayers_Control_MinimizeDiv",
- null,
- null,
- img,
- "absolute");
- OpenLayers.Element.addClass(this.minimizeDiv, "minimizeDiv olButton");
- this.minimizeDiv.style.display = "none";
-
- this.div.appendChild(this.minimizeDiv);
- },
-
- CLASS_NAME: "OpenLayers.Control.LayerSwitcher"
-});
-/* ======================================================================
- OpenLayers/Tile/Image/IFrame.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/Tile/Image.js
- */
-
-/**
- * Constant: OpenLayers.Tile.Image.IFrame
- * Mixin for tiles that use form-encoded POST requests to get images from
- * remote services. Images will be loaded using HTTP-POST into an IFrame.
- *
- * This mixin will be applied to <OpenLayers.Tile.Image> instances
- * configured with <OpenLayers.Tile.Image.maxGetUrlLength> set.
- */
-OpenLayers.Tile.Image.IFrame = {
-
- /**
- * Property: useIFrame
- * {Boolean} true if we are currently using an IFrame to render POST
- * responses, false if we are using an img element to render GET responses.
- */
- useIFrame: null,
-
- /**
- * Property: blankImageUrl
- * {String} Using a data scheme url is not supported by all browsers, but
- * we don't care because we either set it as css backgroundImage, or the
- * image's display style is set to "none" when we use it.
- */
- blankImageUrl: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAQAIBRAA7",
-
- /**
- * Method: draw
- * Set useIFrame in the instance, and operate the image/iframe switch.
- * Then call Tile.Image.draw.
- *
- * Returns:
- * {Boolean}
- */
- draw: function() {
- var draw = OpenLayers.Tile.Image.prototype.shouldDraw.call(this);
- if(draw) {
-
- // this.url isn't set to the currect value yet, so we call getURL
- // on the layer and store the result in a local variable
- var url = this.layer.getURL(this.bounds);
-
- var usedIFrame = this.useIFrame;
- this.useIFrame = this.maxGetUrlLength !== null &&
- !this.layer.async &&
- url.length > this.maxGetUrlLength;
-
- var fromIFrame = usedIFrame && !this.useIFrame;
- var toIFrame = !usedIFrame && this.useIFrame;
-
- if(fromIFrame || toIFrame) {
-
- // Switching between GET (image) and POST (iframe).
-
- // We remove the imgDiv (really either an image or an iframe)
- // from the frame and set it to null to make sure initImage
- // will call getImage.
-
- if(this.imgDiv && this.imgDiv.parentNode === this.frame) {
- this.frame.removeChild(this.imgDiv);
- }
- this.imgDiv = null;
-
- // And if we had an iframe we also remove the event pane.
-
- if(fromIFrame) {
- this.frame.removeChild(this.frame.firstChild);
- }
- }
- }
- return OpenLayers.Tile.Image.prototype.draw.apply(this, arguments);
- },
-
- /**
- * Method: getImage
- * Creates the content for the frame on the tile.
- */
- getImage: function() {
- if (this.useIFrame === true) {
- if (!this.frame.childNodes.length) {
- var eventPane = document.createElement("div"),
- style = eventPane.style;
- style.position = "absolute";
- style.width = "100%";
- style.height = "100%";
- style.zIndex = 1;
- style.backgroundImage = "url(" + this.blankImageUrl + ")";
- this.frame.appendChild(eventPane);
- }
-
- var id = this.id + '_iFrame', iframe;
- if (parseFloat(navigator.appVersion.split("MSIE")[1]) < 9) {
- // Older IE versions do not set the name attribute of an iFrame
- // properly via DOM manipulation, so we need to do it on our own with
- // this hack.
- iframe = document.createElement('<iframe name="'+id+'">');
-
- // IFrames in older IE versions are not transparent, if you set
- // the backgroundColor transparent. This is a workaround to get
- // transparent iframes.
- iframe.style.backgroundColor = '#FFFFFF';
- iframe.style.filter = 'chroma(color=#FFFFFF)';
- }
- else {
- iframe = document.createElement('iframe');
- iframe.style.backgroundColor = 'transparent';
-
- // iframe.name needs to be an unique id, otherwise it
- // could happen that other iframes are overwritten.
- iframe.name = id;
- }
-
- // some special properties to avoid scaling the images and scrollbars
- // in the iframe
- iframe.scrolling = 'no';
- iframe.marginWidth = '0px';
- iframe.marginHeight = '0px';
- iframe.frameBorder = '0';
-
- iframe.style.position = "absolute";
- iframe.style.width = "100%";
- iframe.style.height = "100%";
-
- if (this.layer.opacity < 1) {
- OpenLayers.Util.modifyDOMElement(iframe, null, null, null,
- null, null, null, this.layer.opacity);
- }
- this.frame.appendChild(iframe);
- this.imgDiv = iframe;
- return iframe;
- } else {
- return OpenLayers.Tile.Image.prototype.getImage.apply(this, arguments);
- }
- },
-
- /**
- * Method: createRequestForm
- * Create the html <form> element with width, height, bbox and all
- * parameters specified in the layer params.
- *
- * Returns:
- * {DOMElement} The form element which sends the HTTP-POST request to the
- * WMS.
- */
- createRequestForm: function() {
- // creation of the form element
- var form = document.createElement('form');
- form.method = 'POST';
- var cacheId = this.layer.params["_OLSALT"];
- cacheId = (cacheId ? cacheId + "_" : "") + this.bounds.toBBOX();
- form.action = OpenLayers.Util.urlAppend(this.layer.url, cacheId);
- form.target = this.id + '_iFrame';
-
- // adding all parameters in layer params as hidden fields to the html
- // form element
- var imageSize = this.layer.getImageSize(),
- params = OpenLayers.Util.getParameters(this.url),
- field;
-
- for(var par in params) {
- field = document.createElement('input');
- field.type = 'hidden';
- field.name = par;
- field.value = params[par];
- form.appendChild(field);
- }
-
- return form;
- },
-
- /**
- * Method: setImgSrc
- * Sets the source for the tile image
- *
- * Parameters:
- * url - {String}
- */
- setImgSrc: function(url) {
- if (this.useIFrame === true) {
- if (url) {
- var form = this.createRequestForm();
- this.frame.appendChild(form);
- form.submit();
- this.frame.removeChild(form);
- } else if (this.imgDiv.parentNode === this.frame) {
- // we don't reuse iframes to avoid caching issues
- this.frame.removeChild(this.imgDiv);
- this.imgDiv = null;
- }
- } else {
- OpenLayers.Tile.Image.prototype.setImgSrc.apply(this, arguments);
- }
- },
-
- /**
- * Method: onImageLoad
- * Handler for the image onload event
- */
- onImageLoad: function() {
- //TODO de-uglify opacity handling
- OpenLayers.Tile.Image.prototype.onImageLoad.apply(this, arguments);
- if (this.useIFrame === true) {
- this.imgDiv.style.opacity = 1;
- this.frame.style.opacity = this.layer.opacity;
- }
- },
-
- /**
- * Method: createBackBuffer
- * Override createBackBuffer to do nothing when we use an iframe. Moving an
- * iframe from one element to another makes it necessary to reload the iframe
- * because its content is lost. So we just give up.
- *
- * Returns:
- * {DOMElement}
- */
- createBackBuffer: function() {
- var backBuffer;
- if(this.useIFrame === false) {
- backBuffer = OpenLayers.Tile.Image.prototype.createBackBuffer.call(this);
- }
- return backBuffer;
- }
-};
-/* ======================================================================
OpenLayers/Format/Atom.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**
@@ -84567,13 +87447,775 @@
},
CLASS_NAME: "OpenLayers.Format.Atom"
});
/* ======================================================================
+ OpenLayers/Control/LayerSwitcher.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/Control.js
+ * @requires OpenLayers/Lang.js
+ * @requires OpenLayers/Util.js
+ * @requires OpenLayers/Events/buttonclick.js
+ */
+
+/**
+ * Class: OpenLayers.Control.LayerSwitcher
+ * The LayerSwitcher control displays a table of contents for the map. This
+ * allows the user interface to switch between BaseLasyers and to show or hide
+ * Overlays. By default the switcher is shown minimized on the right edge of
+ * the map, the user may expand it by clicking on the handle.
+ *
+ * To create the LayerSwitcher outside of the map, pass the Id of a html div
+ * as the first argument to the constructor.
+ *
+ * Inherits from:
+ * - <OpenLayers.Control>
+ */
+OpenLayers.Control.LayerSwitcher = OpenLayers.Class(OpenLayers.Control, {
+
+ /**
+ * Property: layerStates
+ * {Array(Object)} Basically a copy of the "state" of the map's layers
+ * the last time the control was drawn. We have this in order to avoid
+ * unnecessarily redrawing the control.
+ */
+ layerStates: null,
+
+ // DOM Elements
+
+ /**
+ * Property: layersDiv
+ * {DOMElement}
+ */
+ layersDiv: null,
+
+ /**
+ * Property: baseLayersDiv
+ * {DOMElement}
+ */
+ baseLayersDiv: null,
+
+ /**
+ * Property: baseLayers
+ * {Array(Object)}
+ */
+ baseLayers: null,
+
+
+ /**
+ * Property: dataLbl
+ * {DOMElement}
+ */
+ dataLbl: null,
+
+ /**
+ * Property: dataLayersDiv
+ * {DOMElement}
+ */
+ dataLayersDiv: null,
+
+ /**
+ * Property: dataLayers
+ * {Array(Object)}
+ */
+ dataLayers: null,
+
+
+ /**
+ * Property: minimizeDiv
+ * {DOMElement}
+ */
+ minimizeDiv: null,
+
+ /**
+ * Property: maximizeDiv
+ * {DOMElement}
+ */
+ maximizeDiv: null,
+
+ /**
+ * APIProperty: ascending
+ * {Boolean}
+ */
+ ascending: true,
+
+ /**
+ * Constructor: OpenLayers.Control.LayerSwitcher
+ *
+ * Parameters:
+ * options - {Object}
+ */
+ initialize: function(options) {
+ OpenLayers.Control.prototype.initialize.apply(this, arguments);
+ this.layerStates = [];
+ },
+
+ /**
+ * APIMethod: destroy
+ */
+ destroy: function() {
+
+ //clear out layers info and unregister their events
+ this.clearLayersArray("base");
+ this.clearLayersArray("data");
+
+ this.map.events.un({
+ buttonclick: this.onButtonClick,
+ addlayer: this.redraw,
+ changelayer: this.redraw,
+ removelayer: this.redraw,
+ changebaselayer: this.redraw,
+ scope: this
+ });
+ this.events.unregister("buttonclick", this, this.onButtonClick);
+
+ OpenLayers.Control.prototype.destroy.apply(this, arguments);
+ },
+
+ /**
+ * Method: setMap
+ *
+ * Properties:
+ * map - {<OpenLayers.Map>}
+ */
+ setMap: function(map) {
+ OpenLayers.Control.prototype.setMap.apply(this, arguments);
+
+ this.map.events.on({
+ addlayer: this.redraw,
+ changelayer: this.redraw,
+ removelayer: this.redraw,
+ changebaselayer: this.redraw,
+ scope: this
+ });
+ if (this.outsideViewport) {
+ this.events.attachToElement(this.div);
+ this.events.register("buttonclick", this, this.onButtonClick);
+ } else {
+ this.map.events.register("buttonclick", this, this.onButtonClick);
+ }
+ },
+
+ /**
+ * Method: draw
+ *
+ * Returns:
+ * {DOMElement} A reference to the DIV DOMElement containing the
+ * switcher tabs.
+ */
+ draw: function() {
+ OpenLayers.Control.prototype.draw.apply(this);
+
+ // create layout divs
+ this.loadContents();
+
+ // set mode to minimize
+ if(!this.outsideViewport) {
+ this.minimizeControl();
+ }
+
+ // populate div with current info
+ this.redraw();
+
+ return this.div;
+ },
+
+ /**
+ * Method: onButtonClick
+ *
+ * Parameters:
+ * evt - {Event}
+ */
+ onButtonClick: function(evt) {
+ var button = evt.buttonElement;
+ if (button === this.minimizeDiv) {
+ this.minimizeControl();
+ } else if (button === this.maximizeDiv) {
+ this.maximizeControl();
+ } else if (button._layerSwitcher === this.id) {
+ if (button["for"]) {
+ button = document.getElementById(button["for"]);
+ }
+ if (!button.disabled) {
+ if (button.type == "radio") {
+ button.checked = true;
+ this.map.setBaseLayer(this.map.getLayer(button._layer));
+ } else {
+ button.checked = !button.checked;
+ this.updateMap();
+ }
+ }
+ }
+ },
+
+ /**
+ * Method: clearLayersArray
+ * User specifies either "base" or "data". we then clear all the
+ * corresponding listeners, the div, and reinitialize a new array.
+ *
+ * Parameters:
+ * layersType - {String}
+ */
+ clearLayersArray: function(layersType) {
+ this[layersType + "LayersDiv"].innerHTML = "";
+ this[layersType + "Layers"] = [];
+ },
+
+
+ /**
+ * Method: checkRedraw
+ * Checks if the layer state has changed since the last redraw() call.
+ *
+ * Returns:
+ * {Boolean} The layer state changed since the last redraw() call.
+ */
+ checkRedraw: function() {
+ if ( !this.layerStates.length ||
+ (this.map.layers.length != this.layerStates.length) ) {
+ return true;
+ }
+
+ for (var i = 0, len = this.layerStates.length; i < len; i++) {
+ var layerState = this.layerStates[i];
+ var layer = this.map.layers[i];
+ if ( (layerState.name != layer.name) ||
+ (layerState.inRange != layer.inRange) ||
+ (layerState.id != layer.id) ||
+ (layerState.visibility != layer.visibility) ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ /**
+ * Method: redraw
+ * Goes through and takes the current state of the Map and rebuilds the
+ * control to display that state. Groups base layers into a
+ * radio-button group and lists each data layer with a checkbox.
+ *
+ * Returns:
+ * {DOMElement} A reference to the DIV DOMElement containing the control
+ */
+ redraw: function() {
+ //if the state hasn't changed since last redraw, no need
+ // to do anything. Just return the existing div.
+ if (!this.checkRedraw()) {
+ return this.div;
+ }
+
+ //clear out previous layers
+ this.clearLayersArray("base");
+ this.clearLayersArray("data");
+
+ var containsOverlays = false;
+ var containsBaseLayers = false;
+
+ // Save state -- for checking layer if the map state changed.
+ // We save this before redrawing, because in the process of redrawing
+ // we will trigger more visibility changes, and we want to not redraw
+ // and enter an infinite loop.
+ var len = this.map.layers.length;
+ this.layerStates = new Array(len);
+ for (var i=0; i <len; i++) {
+ var layer = this.map.layers[i];
+ this.layerStates[i] = {
+ 'name': layer.name,
+ 'visibility': layer.visibility,
+ 'inRange': layer.inRange,
+ 'id': layer.id
+ };
+ }
+
+ var layers = this.map.layers.slice();
+ if (!this.ascending) { layers.reverse(); }
+ for(var i=0, len=layers.length; i<len; i++) {
+ var layer = layers[i];
+ var baseLayer = layer.isBaseLayer;
+
+ if (layer.displayInLayerSwitcher) {
+
+ if (baseLayer) {
+ containsBaseLayers = true;
+ } else {
+ containsOverlays = true;
+ }
+
+ // only check a baselayer if it is *the* baselayer, check data
+ // layers if they are visible
+ var checked = (baseLayer) ? (layer == this.map.baseLayer)
+ : layer.getVisibility();
+
+ // create input element
+ var inputElem = document.createElement("input"),
+ // The input shall have an id attribute so we can use
+ // labels to interact with them.
+ inputId = OpenLayers.Util.createUniqueID(
+ this.id + "_input_"
+ );
+
+ inputElem.id = inputId;
+ inputElem.name = (baseLayer) ? this.id + "_baseLayers" : layer.name;
+ inputElem.type = (baseLayer) ? "radio" : "checkbox";
+ inputElem.value = layer.name;
+ inputElem.checked = checked;
+ inputElem.defaultChecked = checked;
+ inputElem.className = "olButton";
+ inputElem._layer = layer.id;
+ inputElem._layerSwitcher = this.id;
+
+ if (!baseLayer && !layer.inRange) {
+ inputElem.disabled = true;
+ }
+
+ // create span
+ var labelSpan = document.createElement("label");
+ // this isn't the DOM attribute 'for', but an arbitrary name we
+ // use to find the appropriate input element in <onButtonClick>
+ labelSpan["for"] = inputElem.id;
+ OpenLayers.Element.addClass(labelSpan, "labelSpan olButton");
+ labelSpan._layer = layer.id;
+ labelSpan._layerSwitcher = this.id;
+ if (!baseLayer && !layer.inRange) {
+ labelSpan.style.color = "gray";
+ }
+ labelSpan.innerHTML = layer.name;
+ labelSpan.style.verticalAlign = (baseLayer) ? "bottom"
+ : "baseline";
+ // create line break
+ var br = document.createElement("br");
+
+
+ var groupArray = (baseLayer) ? this.baseLayers
+ : this.dataLayers;
+ groupArray.push({
+ 'layer': layer,
+ 'inputElem': inputElem,
+ 'labelSpan': labelSpan
+ });
+
+
+ var groupDiv = (baseLayer) ? this.baseLayersDiv
+ : this.dataLayersDiv;
+ groupDiv.appendChild(inputElem);
+ groupDiv.appendChild(labelSpan);
+ groupDiv.appendChild(br);
+ }
+ }
+
+ // if no overlays, dont display the overlay label
+ this.dataLbl.style.display = (containsOverlays) ? "" : "none";
+
+ // if no baselayers, dont display the baselayer label
+ this.baseLbl.style.display = (containsBaseLayers) ? "" : "none";
+
+ return this.div;
+ },
+
+ /**
+ * Method: updateMap
+ * Cycles through the loaded data and base layer input arrays and makes
+ * the necessary calls to the Map object such that that the map's
+ * visual state corresponds to what the user has selected in
+ * the control.
+ */
+ updateMap: function() {
+
+ // set the newly selected base layer
+ for(var i=0, len=this.baseLayers.length; i<len; i++) {
+ var layerEntry = this.baseLayers[i];
+ if (layerEntry.inputElem.checked) {
+ this.map.setBaseLayer(layerEntry.layer, false);
+ }
+ }
+
+ // set the correct visibilities for the overlays
+ for(var i=0, len=this.dataLayers.length; i<len; i++) {
+ var layerEntry = this.dataLayers[i];
+ layerEntry.layer.setVisibility(layerEntry.inputElem.checked);
+ }
+
+ },
+
+ /**
+ * Method: maximizeControl
+ * Set up the labels and divs for the control
+ *
+ * Parameters:
+ * e - {Event}
+ */
+ maximizeControl: function(e) {
+
+ // set the div's width and height to empty values, so
+ // the div dimensions can be controlled by CSS
+ this.div.style.width = "";
+ this.div.style.height = "";
+
+ this.showControls(false);
+
+ if (e != null) {
+ OpenLayers.Event.stop(e);
+ }
+ },
+
+ /**
+ * Method: minimizeControl
+ * Hide all the contents of the control, shrink the size,
+ * add the maximize icon
+ *
+ * Parameters:
+ * e - {Event}
+ */
+ minimizeControl: function(e) {
+
+ // to minimize the control we set its div's width
+ // and height to 0px, we cannot just set "display"
+ // to "none" because it would hide the maximize
+ // div
+ this.div.style.width = "0px";
+ this.div.style.height = "0px";
+
+ this.showControls(true);
+
+ if (e != null) {
+ OpenLayers.Event.stop(e);
+ }
+ },
+
+ /**
+ * Method: showControls
+ * Hide/Show all LayerSwitcher controls depending on whether we are
+ * minimized or not
+ *
+ * Parameters:
+ * minimize - {Boolean}
+ */
+ showControls: function(minimize) {
+
+ this.maximizeDiv.style.display = minimize ? "" : "none";
+ this.minimizeDiv.style.display = minimize ? "none" : "";
+
+ this.layersDiv.style.display = minimize ? "none" : "";
+ },
+
+ /**
+ * Method: loadContents
+ * Set up the labels and divs for the control
+ */
+ loadContents: function() {
+
+ // layers list div
+ this.layersDiv = document.createElement("div");
+ this.layersDiv.id = this.id + "_layersDiv";
+ OpenLayers.Element.addClass(this.layersDiv, "layersDiv");
+
+ this.baseLbl = document.createElement("div");
+ this.baseLbl.innerHTML = OpenLayers.i18n("Base Layer");
+ OpenLayers.Element.addClass(this.baseLbl, "baseLbl");
+
+ this.baseLayersDiv = document.createElement("div");
+ OpenLayers.Element.addClass(this.baseLayersDiv, "baseLayersDiv");
+
+ this.dataLbl = document.createElement("div");
+ this.dataLbl.innerHTML = OpenLayers.i18n("Overlays");
+ OpenLayers.Element.addClass(this.dataLbl, "dataLbl");
+
+ this.dataLayersDiv = document.createElement("div");
+ OpenLayers.Element.addClass(this.dataLayersDiv, "dataLayersDiv");
+
+ if (this.ascending) {
+ this.layersDiv.appendChild(this.baseLbl);
+ this.layersDiv.appendChild(this.baseLayersDiv);
+ this.layersDiv.appendChild(this.dataLbl);
+ this.layersDiv.appendChild(this.dataLayersDiv);
+ } else {
+ this.layersDiv.appendChild(this.dataLbl);
+ this.layersDiv.appendChild(this.dataLayersDiv);
+ this.layersDiv.appendChild(this.baseLbl);
+ this.layersDiv.appendChild(this.baseLayersDiv);
+ }
+
+ this.div.appendChild(this.layersDiv);
+
+ // maximize button div
+ var img = OpenLayers.Util.getImageLocation('layer-switcher-maximize.png');
+ this.maximizeDiv = OpenLayers.Util.createAlphaImageDiv(
+ "OpenLayers_Control_MaximizeDiv",
+ null,
+ null,
+ img,
+ "absolute");
+ OpenLayers.Element.addClass(this.maximizeDiv, "maximizeDiv olButton");
+ this.maximizeDiv.style.display = "none";
+
+ this.div.appendChild(this.maximizeDiv);
+
+ // minimize button div
+ var img = OpenLayers.Util.getImageLocation('layer-switcher-minimize.png');
+ this.minimizeDiv = OpenLayers.Util.createAlphaImageDiv(
+ "OpenLayers_Control_MinimizeDiv",
+ null,
+ null,
+ img,
+ "absolute");
+ OpenLayers.Element.addClass(this.minimizeDiv, "minimizeDiv olButton");
+ this.minimizeDiv.style.display = "none";
+
+ this.div.appendChild(this.minimizeDiv);
+ },
+
+ CLASS_NAME: "OpenLayers.Control.LayerSwitcher"
+});
+/* ======================================================================
+ OpenLayers/Tile/Image/IFrame.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/Tile/Image.js
+ */
+
+/**
+ * Constant: OpenLayers.Tile.Image.IFrame
+ * Mixin for tiles that use form-encoded POST requests to get images from
+ * remote services. Images will be loaded using HTTP-POST into an IFrame.
+ *
+ * This mixin will be applied to <OpenLayers.Tile.Image> instances
+ * configured with <OpenLayers.Tile.Image.maxGetUrlLength> set.
+ */
+OpenLayers.Tile.Image.IFrame = {
+
+ /**
+ * Property: useIFrame
+ * {Boolean} true if we are currently using an IFrame to render POST
+ * responses, false if we are using an img element to render GET responses.
+ */
+ useIFrame: null,
+
+ /**
+ * Property: blankImageUrl
+ * {String} Using a data scheme url is not supported by all browsers, but
+ * we don't care because we either set it as css backgroundImage, or the
+ * image's display style is set to "none" when we use it.
+ */
+ blankImageUrl: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAQAIBRAA7",
+
+ /**
+ * Method: draw
+ * Set useIFrame in the instance, and operate the image/iframe switch.
+ * Then call Tile.Image.draw.
+ *
+ * Returns:
+ * {Boolean}
+ */
+ draw: function() {
+ var draw = OpenLayers.Tile.Image.prototype.shouldDraw.call(this);
+ if(draw) {
+
+ // this.url isn't set to the currect value yet, so we call getURL
+ // on the layer and store the result in a local variable
+ var url = this.layer.getURL(this.bounds);
+
+ var usedIFrame = this.useIFrame;
+ this.useIFrame = this.maxGetUrlLength !== null &&
+ !this.layer.async &&
+ url.length > this.maxGetUrlLength;
+
+ var fromIFrame = usedIFrame && !this.useIFrame;
+ var toIFrame = !usedIFrame && this.useIFrame;
+
+ if(fromIFrame || toIFrame) {
+
+ // Switching between GET (image) and POST (iframe).
+
+ // We remove the imgDiv (really either an image or an iframe)
+ // from the frame and set it to null to make sure initImage
+ // will call getImage.
+
+ if(this.imgDiv && this.imgDiv.parentNode === this.frame) {
+ this.frame.removeChild(this.imgDiv);
+ }
+ this.imgDiv = null;
+
+ // And if we had an iframe we also remove the event pane.
+
+ if(fromIFrame) {
+ this.frame.removeChild(this.frame.firstChild);
+ }
+ }
+ }
+ return OpenLayers.Tile.Image.prototype.draw.apply(this, arguments);
+ },
+
+ /**
+ * Method: getImage
+ * Creates the content for the frame on the tile.
+ */
+ getImage: function() {
+ if (this.useIFrame === true) {
+ if (!this.frame.childNodes.length) {
+ var eventPane = document.createElement("div"),
+ style = eventPane.style;
+ style.position = "absolute";
+ style.width = "100%";
+ style.height = "100%";
+ style.zIndex = 1;
+ style.backgroundImage = "url(" + this.blankImageUrl + ")";
+ this.frame.appendChild(eventPane);
+ }
+
+ var id = this.id + '_iFrame', iframe;
+ if (parseFloat(navigator.appVersion.split("MSIE")[1]) < 9) {
+ // Older IE versions do not set the name attribute of an iFrame
+ // properly via DOM manipulation, so we need to do it on our own with
+ // this hack.
+ iframe = document.createElement('<iframe name="'+id+'">');
+
+ // IFrames in older IE versions are not transparent, if you set
+ // the backgroundColor transparent. This is a workaround to get
+ // transparent iframes.
+ iframe.style.backgroundColor = '#FFFFFF';
+ iframe.style.filter = 'chroma(color=#FFFFFF)';
+ }
+ else {
+ iframe = document.createElement('iframe');
+ iframe.style.backgroundColor = 'transparent';
+
+ // iframe.name needs to be an unique id, otherwise it
+ // could happen that other iframes are overwritten.
+ iframe.name = id;
+ }
+
+ // some special properties to avoid scaling the images and scrollbars
+ // in the iframe
+ iframe.scrolling = 'no';
+ iframe.marginWidth = '0px';
+ iframe.marginHeight = '0px';
+ iframe.frameBorder = '0';
+
+ iframe.style.position = "absolute";
+ iframe.style.width = "100%";
+ iframe.style.height = "100%";
+
+ if (this.layer.opacity < 1) {
+ OpenLayers.Util.modifyDOMElement(iframe, null, null, null,
+ null, null, null, this.layer.opacity);
+ }
+ this.frame.appendChild(iframe);
+ this.imgDiv = iframe;
+ return iframe;
+ } else {
+ return OpenLayers.Tile.Image.prototype.getImage.apply(this, arguments);
+ }
+ },
+
+ /**
+ * Method: createRequestForm
+ * Create the html <form> element with width, height, bbox and all
+ * parameters specified in the layer params.
+ *
+ * Returns:
+ * {DOMElement} The form element which sends the HTTP-POST request to the
+ * WMS.
+ */
+ createRequestForm: function() {
+ // creation of the form element
+ var form = document.createElement('form');
+ form.method = 'POST';
+ var cacheId = this.layer.params["_OLSALT"];
+ cacheId = (cacheId ? cacheId + "_" : "") + this.bounds.toBBOX();
+ form.action = OpenLayers.Util.urlAppend(this.layer.url, cacheId);
+ form.target = this.id + '_iFrame';
+
+ // adding all parameters in layer params as hidden fields to the html
+ // form element
+ var imageSize = this.layer.getImageSize(),
+ params = OpenLayers.Util.getParameters(this.url),
+ field;
+
+ for(var par in params) {
+ field = document.createElement('input');
+ field.type = 'hidden';
+ field.name = par;
+ field.value = params[par];
+ form.appendChild(field);
+ }
+
+ return form;
+ },
+
+ /**
+ * Method: setImgSrc
+ * Sets the source for the tile image
+ *
+ * Parameters:
+ * url - {String}
+ */
+ setImgSrc: function(url) {
+ if (this.useIFrame === true) {
+ if (url) {
+ var form = this.createRequestForm();
+ this.frame.appendChild(form);
+ form.submit();
+ this.frame.removeChild(form);
+ } else if (this.imgDiv.parentNode === this.frame) {
+ // we don't reuse iframes to avoid caching issues
+ this.frame.removeChild(this.imgDiv);
+ this.imgDiv = null;
+ }
+ } else {
+ OpenLayers.Tile.Image.prototype.setImgSrc.apply(this, arguments);
+ }
+ },
+
+ /**
+ * Method: onImageLoad
+ * Handler for the image onload event
+ */
+ onImageLoad: function() {
+ //TODO de-uglify opacity handling
+ OpenLayers.Tile.Image.prototype.onImageLoad.apply(this, arguments);
+ if (this.useIFrame === true) {
+ this.imgDiv.style.opacity = 1;
+ this.frame.style.opacity = this.layer.opacity;
+ }
+ },
+
+ /**
+ * Method: createBackBuffer
+ * Override createBackBuffer to do nothing when we use an iframe. Moving an
+ * iframe from one element to another makes it necessary to reload the iframe
+ * because its content is lost. So we just give up.
+ *
+ * Returns:
+ * {DOMElement}
+ */
+ createBackBuffer: function() {
+ var backBuffer;
+ if(this.useIFrame === false) {
+ backBuffer = OpenLayers.Tile.Image.prototype.createBackBuffer.call(this);
+ }
+ return backBuffer;
+ }
+};
+/* ======================================================================
OpenLayers/Control/KeyboardDefaults.js
====================================================================== */
-/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
+/* 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. */
/**