ordering <exclamation point/>. you can now gracefully z-order your vectors... and you can even 'yOrder' them and add background images, making for a nice 3dish look. be sure to check out the two new example html's: marker-shadow.html and ordering.html. Big thanks to tcoulter (funkyc) for a prolonged effort with this patch. It has come a long way and now what a beautiful finish. (Closes #1357)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@7652 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
141
examples/marker-shadow.html
Normal file
141
examples/marker-shadow.html
Normal file
@@ -0,0 +1,141 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
|
||||
<link rel="stylesheet" href="style.css" type="text/css" />
|
||||
<style type="text/css">
|
||||
.smallmap {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.docs {
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script src="../lib/OpenLayers.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var SHADOW_Z_INDEX = 10;
|
||||
var MARKER_Z_INDEX = 11;
|
||||
|
||||
var DIAMETER = 200;
|
||||
var NUMBER_OF_FEATURES = 15;
|
||||
|
||||
var map, layer;
|
||||
|
||||
function init() {
|
||||
map = new OpenLayers.Map("map");
|
||||
|
||||
layer = new OpenLayers.Layer.Vector(
|
||||
"Marker Drop Shadows",
|
||||
{
|
||||
styleMap: new OpenLayers.StyleMap({
|
||||
// Set the external graphic and background graphic images.
|
||||
externalGraphic: "../img/marker-gold.png",
|
||||
backgroundGraphic: "./marker_shadow.png",
|
||||
|
||||
// Makes sure the background graphic is placed correctly relative
|
||||
// to the external graphic.
|
||||
backgroundXOffset: 0,
|
||||
backgroundYOffset: -7,
|
||||
|
||||
// Set the z-indexes of both graphics to make sure the background
|
||||
// graphics stay in the background (shadows on top of markers looks
|
||||
// odd; let's not do that).
|
||||
graphicZIndex: MARKER_Z_INDEX,
|
||||
backgroundGraphicZIndex: SHADOW_Z_INDEX,
|
||||
|
||||
pointRadius: 10
|
||||
}),
|
||||
isBaseLayer: true,
|
||||
yOrdering: true
|
||||
}
|
||||
);
|
||||
|
||||
map.addLayers([layer]);
|
||||
|
||||
// Add a drag feature control to move features around.
|
||||
var dragFeature = new OpenLayers.Control.DragFeature(layer);
|
||||
|
||||
map.addControl(dragFeature);
|
||||
|
||||
dragFeature.activate();
|
||||
|
||||
map.zoomToMaxExtent();
|
||||
|
||||
drawFeatures();
|
||||
}
|
||||
|
||||
function drawFeatures() {
|
||||
|
||||
layer.removeFeatures(layer.features);
|
||||
|
||||
// Create features at random around the center.
|
||||
var center = map.getViewPortPxFromLonLat(map.getCenter());
|
||||
|
||||
// Add the ordering features. These are the gold ones that all have the same z-index
|
||||
// and succomb to y-ordering.
|
||||
var features = [];
|
||||
|
||||
for (var index = 0; index < NUMBER_OF_FEATURES; index++) {
|
||||
// Calculate a random x/y. Subtract half the diameter to make some
|
||||
// features negative.
|
||||
var x = (parseInt(Math.random() * DIAMETER)) - (DIAMETER / 2);
|
||||
var y = (parseInt(Math.random() * DIAMETER)) - (DIAMETER / 2);
|
||||
|
||||
var pixel = new OpenLayers.Pixel(center.x + x, center.y + y);
|
||||
|
||||
var lonLat = map.getLonLatFromViewPortPx(pixel);
|
||||
features.push(
|
||||
new OpenLayers.Feature.Vector(
|
||||
new OpenLayers.Geometry.Point(lonLat.lon, lonLat.lat)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
layer.addFeatures(features);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init()">
|
||||
<h1 id="title">Marker Shadows using Background Graphics/Z-Indexes</h1>
|
||||
|
||||
<div id="tags">
|
||||
</div>
|
||||
|
||||
<p id="shortdesc">
|
||||
This example shows off marker shadows using background graphics and z-indexes. Move the features around to show the shadows' interaction.
|
||||
</p>
|
||||
|
||||
<br>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="map" class="smallmap"></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="docs">
|
||||
The features in this map were generated at random. Each of these features have a <i>backgroundGraphic</i> property set in the style map to add a shadow image. Note that the background graphics are not duplicated features with a different style.
|
||||
<br><br>
|
||||
The shadows were set to have a different z-index than the markers themselves, using the <i>backgroundGraphicZIndex</i> property. This makes sure all shadows stay behind the markers, keeping a clean look. The shadows were also placed nicely relative to the external graphic using the <i>backgroundXOffset</i> and <i>backgroundYOffset</i> property.
|
||||
<br><br>
|
||||
Y-ordering on the layer is enabled. See the <a href="./ordering.html">ordering example</a>.
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button onclick="drawFeatures()">Redraw Features</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
BIN
examples/marker_shadow.png
Executable file
BIN
examples/marker_shadow.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 374 B |
203
examples/ordering.html
Normal file
203
examples/ordering.html
Normal file
@@ -0,0 +1,203 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<link rel="stylesheet" href="../theme/default/style.css" type="text/css" />
|
||||
<link rel="stylesheet" href="style.css" type="text/css" />
|
||||
<style type="text/css">
|
||||
.smallmap {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.docs {
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script src="../lib/OpenLayers.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var GOLD_Z_INDEX = 15;
|
||||
var FIRST_RED_Z_INDEX = 10;
|
||||
var SECOND_RED_Z_INDEX = 11;
|
||||
|
||||
var RADIUS_FROM_CENTER = 40;
|
||||
var POINT_DISTANCE = 10;
|
||||
|
||||
function initYOrderMap() {
|
||||
var map = new OpenLayers.Map("yorder");
|
||||
|
||||
var layer = new OpenLayers.Layer.Vector(
|
||||
"Y-Order",
|
||||
{
|
||||
styleMap: new OpenLayers.StyleMap({
|
||||
externalGraphic: "../img/marker-gold.png",
|
||||
pointRadius: 10,
|
||||
graphicZIndex: GOLD_Z_INDEX
|
||||
}),
|
||||
isBaseLayer: true,
|
||||
yOrdering: true
|
||||
}
|
||||
);
|
||||
|
||||
map.addLayers([layer]);
|
||||
map.zoomToMaxExtent();
|
||||
|
||||
// Add features to the layers to show off z-index/y-ordering.
|
||||
// We do this after adding the layer so we can work in pixels.
|
||||
var center = map.getViewPortPxFromLonLat(map.getCenter());
|
||||
|
||||
var top = new OpenLayers.Pixel(center.x, center.y - RADIUS_FROM_CENTER);
|
||||
var bottom = new OpenLayers.Pixel(center.x, center.y + RADIUS_FROM_CENTER);
|
||||
var left = new OpenLayers.Pixel(center.x - RADIUS_FROM_CENTER, center.y - POINT_DISTANCE / 2);
|
||||
var right = new OpenLayers.Pixel(center.x + RADIUS_FROM_CENTER, center.y - POINT_DISTANCE / 2);
|
||||
|
||||
// Add the ordering features. These are the gold ones that all have the same z-index
|
||||
// and succomb to y-ordering.
|
||||
var orderingFeatures = [];
|
||||
// Note: We use > here on purpose (instead of >= ), as well as subtracting the
|
||||
// the POINT_DISTANCE in the beginning of the loop (as opposed to the end).
|
||||
// This is purely for symmetry. Also note that the gold features are drawn
|
||||
// from bottom to top so as to quickly signal whether or not y-ordering is working.
|
||||
while (bottom.y > top.y) {
|
||||
bottom.y -= POINT_DISTANCE;
|
||||
var lonLat = map.getLonLatFromViewPortPx(bottom);
|
||||
orderingFeatures.push(
|
||||
new OpenLayers.Feature.Vector(
|
||||
new OpenLayers.Geometry.Point(lonLat.lon, lonLat.lat)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
layer.addFeatures(orderingFeatures);
|
||||
|
||||
// Add the z-index features. Technically, these features succomb to y-ordering
|
||||
// as well; however, since they have different z-indexes, the z-indexes take
|
||||
// precedence.
|
||||
var indexFeatures = [];
|
||||
var useFirst = true;
|
||||
while (left.x <= right.x) {
|
||||
var lonLat = map.getLonLatFromViewPortPx(left);
|
||||
var point = new OpenLayers.Feature.Vector(
|
||||
new OpenLayers.Geometry.Point(lonLat.lon, lonLat.lat)
|
||||
);
|
||||
|
||||
// This is where the magic happens. We override the style on the layer
|
||||
// to give our own style with alternativing z-indexes.
|
||||
point.style = {
|
||||
graphicZIndex: useFirst ? FIRST_RED_Z_INDEX : SECOND_RED_Z_INDEX,
|
||||
externalGraphic: "../img/marker.png",
|
||||
pointRadius: 10
|
||||
}
|
||||
|
||||
indexFeatures.push(
|
||||
point
|
||||
);
|
||||
|
||||
left.x += POINT_DISTANCE;
|
||||
useFirst = !useFirst;
|
||||
}
|
||||
|
||||
layer.addFeatures(indexFeatures);
|
||||
}
|
||||
|
||||
function initDrawingOrderMap() {
|
||||
var map = new OpenLayers.Map("drawingorder");
|
||||
|
||||
var layer = new OpenLayers.Layer.Vector(
|
||||
"Drawing Order",
|
||||
{
|
||||
// Note there's no z-index set, and yOrdering is left
|
||||
// to its default.
|
||||
styleMap: new OpenLayers.StyleMap({
|
||||
externalGraphic: "../img/marker-green.png",
|
||||
pointRadius: 10
|
||||
}),
|
||||
isBaseLayer: true
|
||||
}
|
||||
);
|
||||
|
||||
map.addLayers([layer]);
|
||||
map.zoomToMaxExtent();
|
||||
|
||||
// Add features to the layers to show off z-index/y-ordering.
|
||||
// We do this after adding the layer so we can work in pixels.
|
||||
var center = map.getViewPortPxFromLonLat(map.getCenter());
|
||||
|
||||
var top = new OpenLayers.Pixel(center.x, center.y - RADIUS_FROM_CENTER);
|
||||
var bottom = new OpenLayers.Pixel(center.x, center.y + RADIUS_FROM_CENTER);
|
||||
var left = new OpenLayers.Pixel(center.x - RADIUS_FROM_CENTER, center.y);
|
||||
var right = new OpenLayers.Pixel(center.x + RADIUS_FROM_CENTER, center.y);
|
||||
|
||||
// Add the ordering features. These are the gold ones that all have the same z-index
|
||||
// and succomb to y-ordering.
|
||||
var orderingFeatures = [];
|
||||
while (bottom.y > top.y && left.x < right.x) {
|
||||
var bottomLonLat = map.getLonLatFromViewPortPx(bottom);
|
||||
var leftLonLat = map.getLonLatFromViewPortPx(left);
|
||||
orderingFeatures.push(
|
||||
new OpenLayers.Feature.Vector(
|
||||
new OpenLayers.Geometry.Point(leftLonLat.lon, bottomLonLat.lat)
|
||||
)
|
||||
);
|
||||
bottom.y -= POINT_DISTANCE / 2; // Divide by 2 for better visual.
|
||||
left.x += POINT_DISTANCE / 2;
|
||||
}
|
||||
|
||||
layer.addFeatures(orderingFeatures);
|
||||
}
|
||||
|
||||
function init(){
|
||||
initYOrderMap();
|
||||
initDrawingOrderMap();
|
||||
};
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init()">
|
||||
<h1 id="title">Z-Index/Y-Order Example</h1>
|
||||
|
||||
<div id="tags">
|
||||
</div>
|
||||
|
||||
<p id="shortdesc">
|
||||
This example shows the use of z-indexing and y-ordering of external graphics. Zoom in and out to see this behavior.
|
||||
</p>
|
||||
|
||||
<h3>Z-Index (with Y-Ordering enabled)</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="yorder" class="smallmap"></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="docs">
|
||||
In this map, the gold features all have the same z-index, and the red features have alternating z-indeces. The gold features' z-index is greater than the red features' z-indeces, which is why gold features look to be drawn on top of the red features. Since each gold feature has the same z-index, gold features succomb to y-ordering: this is where features that seem closest to the viewer (lower lattitude) show up above those that seem farther away (higher lattitude).
|
||||
<br><br>
|
||||
All vector layers have z-indexing enabled by default, but are not enabled with y-ordering. You can enable y-ordering by passing the parameter <i>yOrdering: true</i> in the vector layer's options hash. For all configurations, if features have the same z-index -- and if y-ordering is enabled: the same lattitude -- those features will succomb to drawing order, where the last feature to be drawn will appear above the rest.
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<h3>Drawing Order (no Z-Indexes set, and Y-Ordering disabled)</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="drawingorder" class="smallmap"></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="docs">
|
||||
In this map, features are not given z-indexes, and the layer's <i>yOrdering</i> parameter is set to the default (false). This configuration makes features succomb to drawing order instead of z-index order or y-order.
|
||||
<br><br>
|
||||
The features in this map were drawn from left to right and bottom to top, diagonally, to show that y-ordering is not enabled.
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -152,6 +152,13 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
* {<OpenLayers.Renderer>}
|
||||
*/
|
||||
renderer: null,
|
||||
|
||||
/**
|
||||
* APIProperty: yOrdering
|
||||
* {String} Whether or not externalGraphic y-ordering is enabled on this
|
||||
* layer. Default is false.
|
||||
*/
|
||||
yOrdering: false,
|
||||
|
||||
/**
|
||||
* APIProperty: geometryType
|
||||
@@ -252,8 +259,8 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
for (var i=0, len=this.renderers.length; i<this.renderers.length; i++) {
|
||||
var rendererClass = OpenLayers.Renderer[this.renderers[i]];
|
||||
if (rendererClass && rendererClass.prototype.supported()) {
|
||||
this.renderer = new rendererClass(this.div);
|
||||
break;
|
||||
this.renderer = new rendererClass(this.div, this.yOrdering);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -332,7 +339,7 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
this.renderer.setExtent(extent);
|
||||
|
||||
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.
|
||||
|
||||
@@ -6,6 +6,292 @@
|
||||
* @requires OpenLayers/Renderer.js
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class: OpenLayers.ElementsIndexer
|
||||
* This class takes care of figuring out which order elements should be
|
||||
* placed in the DOM based on given indexing methods.
|
||||
*/
|
||||
OpenLayers.ElementsIndexer = OpenLayers.Class({
|
||||
|
||||
/**
|
||||
* Property: maxZIndex
|
||||
* {Integer} This is the largest-most z-index value for a node
|
||||
* contained within the indexer.
|
||||
*/
|
||||
maxZIndex: null,
|
||||
|
||||
/**
|
||||
* Property: order
|
||||
* {Array<String>} This is an array of node id's stored in the
|
||||
* order that they should show up on screen. Id's higher up in the
|
||||
* array (higher array index) represent nodes with higher z-indeces.
|
||||
*/
|
||||
order: null,
|
||||
|
||||
/**
|
||||
* Property: indices
|
||||
* {Object} This is a hash that maps node ids to their z-index value
|
||||
* stored in the indexer. This is done to make finding a nodes z-index
|
||||
* value O(1).
|
||||
*/
|
||||
indices: null,
|
||||
|
||||
/**
|
||||
* Property: compare
|
||||
* {Function} This is the function used to determine placement of
|
||||
* of a new node within the indexer. If null, this defaults to to
|
||||
* the Z_ORDER_DRAWING_ORDER comparison method.
|
||||
*/
|
||||
compare: null,
|
||||
|
||||
/**
|
||||
* APIMethod: initialize
|
||||
* Create a new indexer with
|
||||
*
|
||||
* Parameters:
|
||||
* yOrdering - {Boolean} Whether to use y-ordering.
|
||||
*/
|
||||
initialize: function(yOrdering) {
|
||||
|
||||
this.compare = yOrdering ?
|
||||
OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER :
|
||||
OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER;
|
||||
|
||||
this.order = [];
|
||||
this.indices = {};
|
||||
this.maxZIndex = 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* APIMethod: insert
|
||||
* Insert a new node into the indexer. In order to find the correct
|
||||
* positioning for the node to be inserted, this method uses a binary
|
||||
* search. This makes inserting O(log(n)).
|
||||
*
|
||||
* Parameters:
|
||||
* newNode - {DOMElement} The new node to be inserted.
|
||||
* root - {DOMElement} The root node from which to insert the new node.
|
||||
*/
|
||||
insert: function(newNode, root) {
|
||||
var nodeId = newNode.id;
|
||||
|
||||
this.determineZIndex(newNode);
|
||||
|
||||
var leftIndex = -1;
|
||||
var rightIndex = this.order.length;
|
||||
var middle;
|
||||
|
||||
while (rightIndex - leftIndex > 1) {
|
||||
middle = parseInt((leftIndex + rightIndex) / 2);
|
||||
|
||||
var nextId = this.order[middle];
|
||||
var nextNode = OpenLayers.Util.getElement(nextId);
|
||||
|
||||
var placement = this.compare(this, newNode, nextNode);
|
||||
|
||||
if (placement > 0) {
|
||||
leftIndex = middle;
|
||||
} else {
|
||||
rightIndex = middle;
|
||||
}
|
||||
}
|
||||
|
||||
this.order.splice(rightIndex, 0, nodeId);
|
||||
this.indices[nodeId] = this.getZIndex(newNode);
|
||||
|
||||
// If the new node should be before another in the index
|
||||
// order, insert the new node before the next; else, lets just
|
||||
// append the new one on the end, making it the highest in the index order.
|
||||
var nextIndex = rightIndex + 1;
|
||||
if (nextIndex < this.order.length) {
|
||||
var nextNode = OpenLayers.Util.getElement(this.order[nextIndex]);
|
||||
root.insertBefore(newNode, nextNode);
|
||||
} else {
|
||||
root.appendChild(newNode);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* APIMethod: remove
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement} The node to be removed.
|
||||
*/
|
||||
remove: function(node) {
|
||||
var nodeId = node.id;
|
||||
var arrayIndex = OpenLayers.Util.indexOf(this.order, nodeId);
|
||||
if (arrayIndex >= 0) {
|
||||
// Remove it from the order array, as well as deleting the node
|
||||
// from the indeces hash.
|
||||
this.order.splice(arrayIndex, 1);
|
||||
delete this.indices[nodeId];
|
||||
|
||||
// Reset the maxium z-index based on the last item in the
|
||||
// order array.
|
||||
var lastId = this.order[this.order.length - 1];
|
||||
this.maxZIndex = this.indices[lastId];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* APIMethod: exists
|
||||
*
|
||||
* Parameters:
|
||||
* node- {DOMElement} The node to test for existence.
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} Whether or not the node exists in the indexer?
|
||||
*/
|
||||
exists: function(node) {
|
||||
return (this.indices[node.id] != null);
|
||||
},
|
||||
|
||||
/**
|
||||
* APIMethod: getZIndex
|
||||
* Get the z-index value for the current node from the node data itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement} The node whose z-index to get.
|
||||
*
|
||||
* Returns:
|
||||
* {Integer} The z-index value for the specified node (from the node
|
||||
* data itself).
|
||||
*/
|
||||
getZIndex: function(node) {
|
||||
return node._style.graphicZIndex;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: determineZIndex
|
||||
* Determine the z-index for the current node if there isn't one,
|
||||
* and set the maximum value if we've found a new maximum.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
*/
|
||||
determineZIndex: function(node) {
|
||||
var zIndex = node._style.graphicZIndex;
|
||||
|
||||
// Everything must have a zIndex. If none is specified,
|
||||
// this means the user *must* (hint: assumption) want this
|
||||
// node to succomb to drawing order. To enforce drawing order
|
||||
// over all indexing methods, we'll create a new z-index that's
|
||||
// greater than any currently in the indexer.
|
||||
if (zIndex == null) {
|
||||
zIndex = this.maxZIndex;
|
||||
node._style.graphicZIndex = zIndex;
|
||||
} else if (zIndex > this.maxZIndex) {
|
||||
this.maxZIndex = zIndex;
|
||||
}
|
||||
},
|
||||
|
||||
CLASS_NAME: "OpenLayers.ElementsIndexer"
|
||||
});
|
||||
|
||||
/**
|
||||
* Namespace: OpenLayers.ElementsIndexer.IndexingMethods
|
||||
* These are the compare methods for figuring out where a new node should be
|
||||
* placed within the indexer. These methods are very similar to general
|
||||
* sorting methods in that they return -1, 0, and 1 to specify the
|
||||
* direction in which new nodes fall in the ordering.
|
||||
*/
|
||||
OpenLayers.ElementsIndexer.IndexingMethods = {
|
||||
|
||||
/**
|
||||
* Method: Z_ORDER
|
||||
* This compare method is used by other comparison methods.
|
||||
* It can be used individually for ordering, but is not recommended,
|
||||
* because it doesn't subscribe to drawing order.
|
||||
*
|
||||
* Parameters:
|
||||
* indexer - {<OpenLayers.ElementsIndexer>}
|
||||
* newNode - {DOMElement}
|
||||
* nextNode - {DOMElement}
|
||||
*
|
||||
* Returns:
|
||||
* {Integer}
|
||||
*/
|
||||
Z_ORDER: function(indexer, newNode, nextNode) {
|
||||
var newZIndex = indexer.getZIndex(newNode);
|
||||
|
||||
var returnVal = 0;
|
||||
if (nextNode) {
|
||||
var nextZIndex = indexer.getZIndex(nextNode);
|
||||
returnVal = newZIndex - nextZIndex;
|
||||
}
|
||||
|
||||
return returnVal;
|
||||
},
|
||||
|
||||
/**
|
||||
* APIMethod: Z_ORDER_DRAWING_ORDER
|
||||
* This method orders nodes by their z-index, but does so in a way
|
||||
* that, if there are other nodes with the same z-index, the newest
|
||||
* drawn will be the front most within that z-index. This is the
|
||||
* default indexing method.
|
||||
*
|
||||
* Parameters:
|
||||
* indexer - {<OpenLayers.ElementsIndexer>}
|
||||
* newNode - {DOMElement}
|
||||
* nextNode - {DOMElement}
|
||||
*
|
||||
* Returns:
|
||||
* {Integer}
|
||||
*/
|
||||
Z_ORDER_DRAWING_ORDER: function(indexer, newNode, nextNode) {
|
||||
var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(
|
||||
indexer,
|
||||
newNode,
|
||||
nextNode
|
||||
);
|
||||
|
||||
// Make Z_ORDER subscribe to drawing order by pushing it above
|
||||
// all of the other nodes with the same z-index.
|
||||
if (nextNode && returnVal == 0) {
|
||||
returnVal = 1;
|
||||
}
|
||||
|
||||
return returnVal;
|
||||
},
|
||||
|
||||
/**
|
||||
* APIMethod: Z_ORDER_Y_ORDER
|
||||
* This one should really be called Z_ORDER_Y_ORDER_DRAWING_ORDER, as it
|
||||
* best describes which ordering methods have precedence (though, the
|
||||
* name would be too long). This method orders nodes by their z-index,
|
||||
* but does so in a way that, if there are other nodes with the same
|
||||
* z-index, the nodes with the lower y position will be "closer" than
|
||||
* those with a higher y position. If two nodes have the exact same y
|
||||
* position, however, then this method will revert to using drawing
|
||||
* order to decide placement.
|
||||
*
|
||||
* Parameters:
|
||||
* indexer - {<OpenLayers.ElementsIndexer>}
|
||||
* newNode - {DOMElement}
|
||||
* nextNode - {DOMElement}
|
||||
*
|
||||
* Returns:
|
||||
* {Integer}
|
||||
*/
|
||||
Z_ORDER_Y_ORDER: function(indexer, newNode, nextNode) {
|
||||
var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(
|
||||
indexer,
|
||||
newNode,
|
||||
nextNode
|
||||
);
|
||||
|
||||
if (nextNode && returnVal == 0) {
|
||||
var newLat = newNode._geometry.getBounds().bottom;
|
||||
var nextLat = nextNode._geometry.getBounds().bottom;
|
||||
|
||||
var result = nextLat - newLat;
|
||||
returnVal = (result ==0) ? 1 : result;
|
||||
}
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Class: OpenLayers.Renderer.Elements
|
||||
* This is another virtual class in that it should never be instantiated by
|
||||
@@ -41,6 +327,19 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
*/
|
||||
xmlns: null,
|
||||
|
||||
/**
|
||||
* Property: Indexer
|
||||
* {<OpenLayers.ElementIndexer>} An instance of OpenLayers.ElementsIndexer
|
||||
* created upon initialization.
|
||||
*/
|
||||
indexer: null,
|
||||
|
||||
/**
|
||||
* Constant: BACKGROUND_ID_SUFFIX
|
||||
* {String}
|
||||
*/
|
||||
BACKGROUND_ID_SUFFIX: "_background",
|
||||
|
||||
/**
|
||||
* Property: minimumSymbolizer
|
||||
* {Object}
|
||||
@@ -57,8 +356,9 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
*
|
||||
* Parameters:
|
||||
* containerID - {String}
|
||||
* yOrdering - {Boolean} Whether or not y-ordering is enabled.
|
||||
*/
|
||||
initialize: function(containerID) {
|
||||
initialize: function(containerID, yOrdering) {
|
||||
OpenLayers.Renderer.prototype.initialize.apply(this, arguments);
|
||||
|
||||
this.rendererRoot = this.createRenderRoot();
|
||||
@@ -66,6 +366,8 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
|
||||
this.rendererRoot.appendChild(this.root);
|
||||
this.container.appendChild(this.rendererRoot);
|
||||
|
||||
this.indexer = new OpenLayers.ElementsIndexer(yOrdering);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -135,22 +437,13 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
return;
|
||||
};
|
||||
|
||||
//
|
||||
if (style.backgroundGraphic) {
|
||||
this.redrawBackgroundNode(geometry.id, geometry, style, featureId);
|
||||
}
|
||||
|
||||
if (style.display != "none") {
|
||||
//first we create the basic node and add it to the root
|
||||
var nodeType = this.getNodeType(geometry, style);
|
||||
var node = this.nodeFactory(geometry.id, nodeType);
|
||||
node._featureId = featureId;
|
||||
node._geometryClass = geometry.CLASS_NAME;
|
||||
node._style = style;
|
||||
|
||||
//now actually draw the node, and style it
|
||||
node = this.drawGeometryNode(node, geometry);
|
||||
|
||||
// append the node to root (but only if it's new)
|
||||
if (node.parentNode != this.root) {
|
||||
this.root.appendChild(node);
|
||||
}
|
||||
this.postDraw(node);
|
||||
this.redrawNode(geometry.id, geometry, style, featureId);
|
||||
} else {
|
||||
node = OpenLayers.Util.getElement(geometry.id);
|
||||
if (node) {
|
||||
@@ -158,6 +451,90 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: redrawNode
|
||||
*
|
||||
* Parameters:
|
||||
* id - {String}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* style - {Object}
|
||||
* featureId - {String}
|
||||
*/
|
||||
redrawNode: function(id, geometry, style, featureId) {
|
||||
// Get the node if it's already on the map.
|
||||
var currentNode = OpenLayers.Util.getElement(id);
|
||||
|
||||
// Create a new node, or use the current one if it's
|
||||
// already there.
|
||||
var newNode;
|
||||
if (!currentNode) {
|
||||
var nodeType = this.getNodeType(geometry, style);
|
||||
newNode = this.createNode(nodeType, id);
|
||||
} else {
|
||||
newNode = currentNode;
|
||||
}
|
||||
|
||||
// Set the data for the node, then draw it.
|
||||
newNode._featureId = featureId;
|
||||
newNode._geometry = geometry;
|
||||
newNode._geometryClass = geometry.CLASS_NAME;
|
||||
newNode._style = style;
|
||||
newNode = this.drawGeometryNode(newNode, geometry, style);
|
||||
|
||||
// If the node is known to the indexer, remove it so we can
|
||||
// recalculate where it should go.
|
||||
if (this.indexer.exists(newNode)) {
|
||||
this.indexer.remove(newNode);
|
||||
}
|
||||
|
||||
// Insert the node into the indexer so it can show us where to place it.
|
||||
// Note that this operation is O(log(n)). If there's a performance
|
||||
// problem (when dragging, for instance) this is likely where it
|
||||
// would be.
|
||||
this.indexer.insert(newNode, this.root);
|
||||
|
||||
this.postDraw(newNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: redrawBackgroundNode
|
||||
* Redraws the node using special 'background' style properties. Basically
|
||||
* just calls redrawNode(), but instead of directly using the
|
||||
* 'externalGraphic', 'graphicXOffset', 'graphicYOffset', and
|
||||
* 'graphicZIndex' properties directly from the specified 'style'
|
||||
* parameter, we create a new style object and set those properties
|
||||
* from the corresponding 'background'-prefixed properties from
|
||||
* specified 'style' parameter.
|
||||
*
|
||||
* Parameters:
|
||||
* id - {String}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* style - {Object}
|
||||
* featureId - {String}
|
||||
*/
|
||||
redrawBackgroundNode: function(id, geometry, style, featureId) {
|
||||
var backgroundStyle = OpenLayers.Util.extend({}, style);
|
||||
|
||||
// Set regular style attributes to apply to the background styles.
|
||||
backgroundStyle.externalGraphic = backgroundStyle.backgroundGraphic;
|
||||
backgroundStyle.graphicXOffset = backgroundStyle.backgroundXOffset;
|
||||
backgroundStyle.graphicYOffset = backgroundStyle.backgroundYOffset;
|
||||
backgroundStyle.graphicZIndex = backgroundStyle.backgroundGraphicZIndex;
|
||||
|
||||
// Erase background styles.
|
||||
backgroundStyle.backgroundGraphic = null;
|
||||
backgroundStyle.backgroundXOffset = null;
|
||||
backgroundStyle.backgroundYOffset = null;
|
||||
backgroundStyle.backgroundGraphicZIndex = null;
|
||||
|
||||
this.redrawNode(
|
||||
id + this.BACKGROUND_ID_SUFFIX,
|
||||
geometry,
|
||||
backgroundStyle,
|
||||
null
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawGeometryNode
|
||||
@@ -213,7 +590,7 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
/**
|
||||
* Method: postDraw
|
||||
* Things that have do be done after the geometry node is appended
|
||||
* to its parent node. To be overridden by subclasses.
|
||||
* to its parent node. To be overridden by subclasses.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
@@ -223,8 +600,8 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
/**
|
||||
* Method: drawPoint
|
||||
* Virtual function for drawing Point Geometry.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
@@ -235,8 +612,8 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
/**
|
||||
* Method: drawLineString
|
||||
* Virtual function for drawing LineString Geometry.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
@@ -247,8 +624,8 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
/**
|
||||
* Method: drawLinearRing
|
||||
* Virtual function for drawing LinearRing Geometry.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
@@ -259,8 +636,8 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
/**
|
||||
* Method: drawPolygon
|
||||
* Virtual function for drawing Polygon Geometry.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
@@ -271,8 +648,8 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
/**
|
||||
* Method: drawRectangle
|
||||
* Virtual function for drawing Rectangle Geometry.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
@@ -283,8 +660,8 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
/**
|
||||
* Method: drawCircle
|
||||
* Virtual function for drawing Circle Geometry.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
@@ -295,8 +672,8 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
/**
|
||||
* Method: drawSurface
|
||||
* Virtual function for drawing Surface Geometry.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
* Should be implemented by subclasses.
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
@@ -312,7 +689,7 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
*
|
||||
* Returns:
|
||||
* {<OpenLayers.Geometry>} A geometry from an event that
|
||||
* happened on a layer
|
||||
* happened on a layer.
|
||||
*/
|
||||
getFeatureIdFromEvent: function(evt) {
|
||||
var node = evt.target || evt.srcElement;
|
||||
@@ -340,10 +717,24 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
} else {
|
||||
var element = OpenLayers.Util.getElement(geometry.id);
|
||||
if (element && element.parentNode) {
|
||||
if (element.geometry) {
|
||||
element.geometry.destroy();
|
||||
element.geometry = null;
|
||||
}
|
||||
element.parentNode.removeChild(element);
|
||||
|
||||
this.indexer.remove(element);
|
||||
|
||||
var backgroundId = geometry.id + this.BACKGROUND_ID_SUFFIX;
|
||||
var bElem = OpenLayers.Util.getElement(backgroundId);
|
||||
if (bElem && bElem.parentNode) {
|
||||
// No need to destroy the geometry since the element and the background
|
||||
// node share the same geometry.
|
||||
bElem.parentNode.removeChild(bElem);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: nodeFactory
|
||||
@@ -354,10 +745,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
*
|
||||
* Parameters:
|
||||
* id - {String}
|
||||
* type - {String} type Kind of node to draw
|
||||
* type - {String} type Kind of node to draw.
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} A new node of the given type and id
|
||||
* {DOMElement} A new node of the given type and id.
|
||||
*/
|
||||
nodeFactory: function(id, type) {
|
||||
var node = OpenLayers.Util.getElement(id);
|
||||
@@ -372,6 +763,19 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: createNode
|
||||
*
|
||||
* Parameters:
|
||||
* type - {String} Kind of node to draw.
|
||||
* id - {String} Id for node.
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} A new node of the given type and id.
|
||||
* This function must be overridden by subclasses.
|
||||
*/
|
||||
createNode: function(type, id) {},
|
||||
|
||||
/**
|
||||
* Method: isComplexSymbol
|
||||
* Determines if a symbol cannot be rendered using drawCircle
|
||||
@@ -385,7 +789,7 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
isComplexSymbol: function(graphicName) {
|
||||
return (graphicName != "circle") && !!graphicName;
|
||||
},
|
||||
|
||||
|
||||
CLASS_NAME: "OpenLayers.Renderer.Elements"
|
||||
});
|
||||
|
||||
|
||||
@@ -3,12 +3,9 @@
|
||||
<script src="../../lib/OpenLayers.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
function test_Elements_constructor(t) {
|
||||
t.plan(5);
|
||||
var el = document.createElement('div');
|
||||
document.body.appendChild(el);
|
||||
el.id = "foo";
|
||||
|
||||
function setUp() {
|
||||
// Stub out functions that are meant to be overridden by
|
||||
// subclasses.
|
||||
OpenLayers.Renderer.Elements.prototype._createRenderRoot =
|
||||
OpenLayers.Renderer.Elements.prototype.createRenderRoot;
|
||||
|
||||
@@ -25,69 +22,97 @@
|
||||
return root;
|
||||
};
|
||||
|
||||
var r = new OpenLayers.Renderer.Elements("foo");
|
||||
OpenLayers.Renderer.Elements.prototype._createNode =
|
||||
OpenLayers.Renderer.Elements.prototype.createNode;
|
||||
|
||||
t.ok(r instanceof OpenLayers.Renderer.Elements, "new OpenLayers.Renderer.Elements returns Elements object" );
|
||||
t.ok(r.rendererRoot != null, "elements rendererRoot is not null");
|
||||
t.ok(r.root != null, "elements root is not null");
|
||||
OpenLayers.Renderer.Elements.prototype.createNode = function() {
|
||||
return document.createElement("div");
|
||||
};
|
||||
}
|
||||
|
||||
// Create a new Elements renderer based on an id and an ordering
|
||||
// type. For these tests, both of these parameters are optional.
|
||||
function create_renderer(id, ordering) {
|
||||
|
||||
t.ok(r.root.parentNode == rendererRoot, "elements root is correctly appended to rendererRoot");
|
||||
t.ok(r.rendererRoot.parentNode == el, "elements rendererRoot is correctly appended to container");
|
||||
rendererRoot = null;
|
||||
|
||||
if (id == null) {
|
||||
var el = document.createElement('div');
|
||||
document.body.appendChild(el);
|
||||
el.id = OpenLayers.Util.createUniqueID();
|
||||
id = el.id;
|
||||
}
|
||||
|
||||
return new OpenLayers.Renderer.Elements(id, ordering);
|
||||
}
|
||||
|
||||
// Cleanup stubs made in the function above.
|
||||
function tearDown() {
|
||||
OpenLayers.Renderer.Elements.prototype.createRenderRoot =
|
||||
OpenLayers.Renderer.Elements.prototype._createRenderRoot;
|
||||
OpenLayers.Renderer.Elements.prototype.createRoot =
|
||||
OpenLayers.Renderer.Elements.prototype._createRoot;
|
||||
OpenLayers.Renderer.Elements.prototype.createNode =
|
||||
OpenLayers.Renderer.Elements.prototype._createNode;
|
||||
}
|
||||
|
||||
function test_Elements_constructor(t) {
|
||||
t.plan(6);
|
||||
|
||||
setUp();
|
||||
|
||||
var r = create_renderer();
|
||||
|
||||
t.ok(r instanceof OpenLayers.Renderer.Elements, "new OpenLayers.Renderer.Elements returns Elements object" );
|
||||
t.ok(r.rendererRoot != null, "elements rendererRoot is not null");
|
||||
t.ok(r.root != null, "elements root is not null");
|
||||
t.ok(r.indexer != null, "indexer is not null.");
|
||||
|
||||
t.ok(r.root.parentNode == r.rendererRoot, "elements root is correctly appended to rendererRoot");
|
||||
t.ok(r.rendererRoot.parentNode == r.container, "elements rendererRoot is correctly appended to container");
|
||||
|
||||
tearDown();
|
||||
}
|
||||
|
||||
function test_Elements_destroy(t) {
|
||||
t.plan(5);
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype._initialize =
|
||||
OpenLayers.Renderer.Elements.prototype.initialize;
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.initialize = function() {}
|
||||
|
||||
var g_Clear = false, g_Destroy = false;
|
||||
|
||||
var elems = {
|
||||
'clear': function() {
|
||||
t.ok(true, "clear called");
|
||||
},
|
||||
'rendererRoot': {},
|
||||
'root': {},
|
||||
'xmlns': {}
|
||||
};
|
||||
|
||||
OpenLayers.Renderer.prototype._destroy =
|
||||
OpenLayers.Renderer.prototype.destroy;
|
||||
|
||||
|
||||
var args = [{}, {}, {}];
|
||||
OpenLayers.Renderer.prototype.destroy = function() {
|
||||
g_Destroy = true;
|
||||
t.ok((arguments[0] == args[0]) &&
|
||||
(arguments[1] == args[1]) &&
|
||||
(arguments[2] == args[2]), "correct arguments passed to OpenLayers.Renderer.destroy()");
|
||||
};
|
||||
|
||||
var r = new OpenLayers.Renderer.SVG(document.body);
|
||||
r.clear = function() {
|
||||
g_Clear = true;
|
||||
};
|
||||
r.rendererRoot = 'foo';
|
||||
r.root = 'bar';
|
||||
r.xmlns = 'dude';
|
||||
|
||||
r.destroy();
|
||||
|
||||
t.eq(g_Clear, true, "OpenLayers.Renderer.Elements.clear() called");
|
||||
t.eq(r.rendererRoot, null, "rendererRoot nullified");
|
||||
t.eq(r.root, null, "root nullified");
|
||||
t.eq(r.xmlns, null, "xmlns nullified");
|
||||
t.eq(g_Destroy, true, "OpenLayers.Renderer.destroy() called");
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.initialize =
|
||||
OpenLayers.Renderer.Elements.prototype._initialize;
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.destroy.apply(elems, args);
|
||||
|
||||
t.ok(elems.rendererRoot == null, "rendererRoot nullified");
|
||||
t.ok(elems.root == null, "root nullified");
|
||||
t.ok(elems.xmlns == null, "xmlns nullified");
|
||||
|
||||
OpenLayers.Renderer.prototype.destroy =
|
||||
OpenLayers.Renderer.prototype._destroy;
|
||||
|
||||
}
|
||||
|
||||
function test_Elements_clear(t) {
|
||||
t.plan(1);
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype._initialize =
|
||||
OpenLayers.Renderer.Elements.prototype.initialize;
|
||||
setUp();
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.initialize = function() {}
|
||||
|
||||
var r = new OpenLayers.Renderer.Elements();
|
||||
var r = create_renderer();
|
||||
var element = document.createElement("div");
|
||||
r.root = element;
|
||||
|
||||
@@ -98,19 +123,15 @@
|
||||
|
||||
t.ok(r.root.childNodes.length == 0, "root is correctly cleared");
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.initialize =
|
||||
OpenLayers.Renderer.Elements.prototype._initialize;
|
||||
tearDown();
|
||||
}
|
||||
|
||||
function test_Elements_drawGeometry(t) {
|
||||
t.plan(5);
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype._initialize =
|
||||
OpenLayers.Renderer.Elements.prototype.initialize;
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.initialize = function() {};
|
||||
|
||||
var r = new OpenLayers.Renderer.Elements();
|
||||
|
||||
setUp();
|
||||
|
||||
var r = create_renderer();
|
||||
|
||||
var element = document.createElement("div");
|
||||
r.root = element;
|
||||
@@ -147,21 +168,16 @@
|
||||
var style = {'display':'none'};
|
||||
r.drawGeometry(geometry, style, featureId);
|
||||
t.ok(g_Node.parentNode != r.root, "node is correctly removed");
|
||||
|
||||
OpenLayers.Util.getElement = _getElement;
|
||||
OpenLayers.Renderer.Elements.prototype.initialize =
|
||||
OpenLayers.Renderer.Elements.prototype._initialize;
|
||||
|
||||
tearDown();
|
||||
}
|
||||
|
||||
function test_Elements_drawGeometry_2(t) {
|
||||
t.plan(9);
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype._initialize =
|
||||
OpenLayers.Renderer.Elements.prototype.initialize;
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.initialize = function() {};
|
||||
|
||||
var r = new OpenLayers.Renderer.Elements();
|
||||
setUp();
|
||||
|
||||
var r = create_renderer();
|
||||
|
||||
var element = document.createElement("div");
|
||||
r.root = element;
|
||||
@@ -281,9 +297,8 @@
|
||||
style = true;
|
||||
r.drawGeometry(geometry, style);
|
||||
t.ok(properDraw, "drawGeometry called drawPolygon when passed a multi-polygon");
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.initialize =
|
||||
OpenLayers.Renderer.Elements.prototype._initialize;
|
||||
|
||||
tearDown();
|
||||
}
|
||||
|
||||
function test_Elements_getfeatureidfromevent(t) {
|
||||
@@ -308,70 +323,134 @@
|
||||
}
|
||||
|
||||
function test_Elements_erasegeometry(t) {
|
||||
t.plan(5);
|
||||
|
||||
var el = document.createElement('div');
|
||||
document.body.appendChild(el);
|
||||
el.id = 'bar';
|
||||
var geometry = {
|
||||
id: 'bar'
|
||||
t.plan(15);
|
||||
|
||||
var elements = {
|
||||
'eraseGeometry': function(geometry) {
|
||||
gErased.push(geometry);
|
||||
}
|
||||
};
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry);
|
||||
t.ok(el.parentNode != document.body, "element correctly removed");
|
||||
|
||||
var el = document.createElement('div');
|
||||
document.body.appendChild(el);
|
||||
el.id = 'bar';
|
||||
var geometry = {
|
||||
CLASS_NAME: "OpenLayers.Geometry.MultiPoint",
|
||||
components: [{
|
||||
id: 'bar'
|
||||
}]
|
||||
'components': [{}, {}, {}]
|
||||
};
|
||||
|
||||
//multipoint
|
||||
geometry.CLASS_NAME = "OpenLayers.Geometry.MultiPoint";
|
||||
gErased = [];
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry.apply(elements, [geometry]);
|
||||
t.ok( (gErased[0] == geometry.components[0]) &&
|
||||
(gErased[1] == geometry.components[1]) &&
|
||||
(gErased[2] == geometry.components[2]), "multipoint all components of geometry correctly erased.");
|
||||
|
||||
//multilinestring
|
||||
geometry.CLASS_NAME = "OpenLayers.Geometry.MultiLineString";
|
||||
gErased = [];
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry.apply(elements, [geometry]);
|
||||
t.ok( (gErased[0] == geometry.components[0]) &&
|
||||
(gErased[1] == geometry.components[1]) &&
|
||||
(gErased[2] == geometry.components[2]), "multilinestring all components of geometry correctly erased.");
|
||||
|
||||
//multipolygon
|
||||
geometry.CLASS_NAME = "OpenLayers.Geometry.MultiPolygon";
|
||||
gErased = [];
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry.apply(elements, [geometry]);
|
||||
t.ok( (gErased[0] == geometry.components[0]) &&
|
||||
(gErased[1] == geometry.components[1]) &&
|
||||
(gErased[2] == geometry.components[2]), "multipolygon all components of geometry correctly erased.");
|
||||
|
||||
//collection
|
||||
geometry.CLASS_NAME = "OpenLayers.Geometry.Collection";
|
||||
gErased = [];
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry.apply(elements, [geometry]);
|
||||
t.ok( (gErased[0] == geometry.components[0]) &&
|
||||
(gErased[1] == geometry.components[1]) &&
|
||||
(gErased[2] == geometry.components[2]), "collection all components of geometry correctly erased.");
|
||||
|
||||
|
||||
// OTHERS
|
||||
//
|
||||
geometry.CLASS_NAME = {};
|
||||
|
||||
gElement = null;
|
||||
gBackElement = null;
|
||||
|
||||
OpenLayers.Util._getElement = OpenLayers.Util.getElement;
|
||||
OpenLayers.Util.getElement = function(id) {
|
||||
var retVal = null;
|
||||
if (id != null) {
|
||||
var hasBack = (id.indexOf(elements.BACKGROUND_ID_SUFFIX) != -1);
|
||||
retVal = hasBack ? gBackElement : gElement;
|
||||
}
|
||||
return retVal;
|
||||
};
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry);
|
||||
t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a multipoint");
|
||||
|
||||
var el = document.createElement('div');
|
||||
document.body.appendChild(el);
|
||||
el.id = 'bar';
|
||||
var geometry = {
|
||||
CLASS_NAME: "OpenLayers.Geometry.MultiLineString",
|
||||
components: [{
|
||||
id: 'bar'
|
||||
}]
|
||||
//element null
|
||||
geometry.id = null;
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry.apply(elements, [geometry]);
|
||||
// (no tests here, just make sure it doesn't bomb)
|
||||
|
||||
//element.parentNode null
|
||||
elements.BACKGROUND_ID_SUFFIX = 'BLAHBLAHBLAH';
|
||||
geometry.id = "foo";
|
||||
gElement = {};
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry.apply(elements, [geometry]);
|
||||
// (no tests here, just make sure it doesn't bomb)
|
||||
|
||||
//valid element.parentNode, element.geometry
|
||||
elements.indexer = {
|
||||
'remove': function(elem) {
|
||||
gIndexerRemoved = elem;
|
||||
}
|
||||
};
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry);
|
||||
t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a multilinestring");
|
||||
|
||||
var el = document.createElement('div');
|
||||
document.body.appendChild(el);
|
||||
el.id = 'bar';
|
||||
var geometry = {
|
||||
CLASS_NAME: "OpenLayers.Geometry.MultiPolygon",
|
||||
components: [{
|
||||
id: 'bar'
|
||||
}]
|
||||
|
||||
gElement = {
|
||||
'geometry': {
|
||||
'destroy': function() {
|
||||
t.ok(true, "geometry destroyed");
|
||||
}
|
||||
},
|
||||
'parentNode': {
|
||||
'removeChild': function(elem) {
|
||||
gElemRemoved = elem;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry);
|
||||
t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a multipolygon");
|
||||
|
||||
var el = document.createElement('div');
|
||||
document.body.appendChild(el);
|
||||
el.id = 'bar';
|
||||
var geometry = {
|
||||
CLASS_NAME: "OpenLayers.Geometry.Collection",
|
||||
components: [{
|
||||
id: 'bar'
|
||||
}]
|
||||
gBackElement = {
|
||||
'parentNode': {
|
||||
'removeChild': function(elem) {
|
||||
gBackRemoved = elem;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry);
|
||||
t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a collection");
|
||||
}
|
||||
|
||||
gElemRemoved = gBackRemoved = gIndexerRemoved = null;
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry.apply(elements, [geometry]);
|
||||
t.ok( (gElement.geometry == null), "all normal: element's 'geometry' property nullified");
|
||||
t.ok( (gElemRemoved == gElement), "all normal: main element properly removed from parent node");
|
||||
t.ok( (gBackRemoved == gBackElement), "all normal: back element properly removed from parent node");
|
||||
t.ok( (gIndexerRemoved == gElement), "all normal: main element properly removed from the indexer");
|
||||
|
||||
//valid element.parentNode, no element.geometry, no bElem
|
||||
gBackElement = null;
|
||||
gElement.geometry = null;
|
||||
gElemRemoved = gBackRemoved = gIndexerRemoved = null;
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry.apply(elements, [geometry]);
|
||||
t.ok( (gElemRemoved == gElement), "no bElem: main element properly removed from parent node");
|
||||
t.ok( (gBackRemoved == null), "no bElem: back element not tried to remove from parent node when it doesn't exist");
|
||||
t.ok( (gIndexerRemoved == gElement), "no bElem: main element properly removed from the indexer");
|
||||
|
||||
//valid element.parentNode, no element.geometry, valid bElem, no bElem.parentNode
|
||||
gBackElement = {};
|
||||
gElemRemoved = gBackRemoved = gIndexerRemoved = null;
|
||||
OpenLayers.Renderer.Elements.prototype.eraseGeometry.apply(elements, [geometry]);
|
||||
t.ok( (gElemRemoved == gElement), "no bElem.parentNode: main element properly removed from parent node");
|
||||
t.ok( (gBackRemoved == null), "no bElem.parentNode: back element not tried to remove from parent node when it has no parent node");
|
||||
t.ok( (gIndexerRemoved == gElement), "no bElem.parentNode: main element properly removed from the indexer");
|
||||
|
||||
|
||||
OpenLayers.Util.getElement = OpenLayers.Util._getElement;
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user