Files
openlayers/tests/Layer/Vector.html
ahocevar cc2e19d789 added support for text labels. This also adds getCentroid methods to all
geometries. Thanks crschmidt for the great help with this patch, and 
thanks to camptocamp for the initial work on this and rcoup for creating 
the first patches. r=crschmidt (closes #1895)


git-svn-id: http://svn.openlayers.org/trunk/openlayers@9262 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
2009-04-10 16:05:26 +00:00

555 lines
24 KiB
HTML

<html>
<head>
<script src="../../lib/OpenLayers.js"></script>
<script type="text/javascript">
var name = "Vector Layer";
function test_Layer_Vector_constructor(t) {
t.plan(4);
var options = {protocol: new OpenLayers.Protocol(),
strategies: [new OpenLayers.Strategy(), new OpenLayers.Strategy()]}
var layer = new OpenLayers.Layer.Vector(name, options);
t.ok(layer instanceof OpenLayers.Layer.Vector, "new OpenLayers.Layer.Vector returns correct object" );
t.eq(layer.name, name, "layer name is correctly set");
t.ok(layer.renderer.CLASS_NAME, "layer has a renderer");
t.ok((layer.name == layer.strategies[0].layer.name) &&
(layer.strategies[0].layer.name == layer.strategies[1].layer.name),
"setLayer was called on strategies");
}
function test_Layer_Vector_refresh(t) {
t.plan(4);
var obj = {"an": "object"};
var log;
var layer = new OpenLayers.Layer.Vector(name, {
eventListeners: {
refresh: function(o) {
log.obj = o;
}
}
});
inRange = false;
layer.calculateInRange = function() {
return inRange;
};
log = {};
inRange = false;
layer.visibility = false;
layer.refresh(obj);
t.eq(log.obj, undefined, "[false, false] refresh not triggered");
log = {};
inRange = true;
layer.visibility = false;
layer.refresh(obj);
t.eq(log.obj, undefined, "[true, false] refresh not triggered");
log = {};
inRange = false;
layer.visibility = true;
layer.refresh(obj);
t.eq(log.obj, undefined, "[false, true] refresh not triggered");
log = {};
inRange = true;
layer.visibility = true;
layer.refresh(obj);
t.ok(log.obj === obj, "[true, true] refresh triggered with correct arg");
}
function test_Layer_Vector_addFeatures(t) {
t.plan(8);
var layer = new OpenLayers.Layer.Vector(name);
var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
var pointFeature = new OpenLayers.Feature.Vector(point);
layer.preFeatureInsert = function(feature) {
t.ok(feature == pointFeature, "OpenLayers.Layer.Vector.addFeatures calls preFeatureInsert with the right arg");
};
layer.onFeatureInsert = function(feature) {
t.ok(feature == pointFeature, "OpenLayers.Layer.Vector.addFeatures calls onFeatureInsert with the right arg");
};
layer.events.register('beforefeatureadded', null, function(obj) {
t.ok(pointFeature == obj.feature, "OpenLayers.Layer.Vector.addFeatures triggers beforefeatureadded with correct feature passed to callback");
});
layer.events.register('featureadded', null, function(obj) {
t.ok(pointFeature == obj.feature, "OpenLayers.Layer.Vector.addFeatures triggers featureadded with correct feature passed to callback");
});
layer.events.register('featuresadded', null, function(obj) {
t.ok(pointFeature == obj.features[0], "OpenLayers.Layer.Vector.addFeatures triggers featuresadded with correct features passed to callback");
});
layer.addFeatures([pointFeature]);
t.eq(layer.features.length, 1, "OpenLayers.Layer.Vector.addFeatures adds something to the array");
t.ok(layer.features[0] == pointFeature, "OpenLayers.Layer.Vector.addFeatures returns an array of features");
layer.preFeatureInsert = function(feature) {
t.fail("OpenLayers.Layer.Vector.addFeatures calls preFeatureInsert while it must not");
};
layer.onFeatureInsert = function(feature) {
t.fail("OpenLayers.Layer.Vector.addFeatures calls onFeatureInsert while it must not");
};
layer.events.register('beforefeatureadded', null, function(obj) {
t.fail("OpenLayers.Layer.Vector.addFeatures triggers beforefeatureadded while it must not");
});
layer.events.register('featureadded', null, function(obj) {
t.fail("OpenLayers.Layer.Vector.addFeatures triggers featureadded while it must not");
});
layer.events.register('featuresadded', null, function(obj) {
t.fail("OpenLayers.Layer.Vector.addFeatures triggers featuresadded while it must not");
});
layer.addFeatures([pointFeature], {silent: true});
var extent = layer.getDataExtent();
t.eq(extent.toBBOX(), "-111.04,45.68,-111.04,45.68", "extent from getDataExtent is correct");
}
function test_Layer_Vector_getDataExtent(t) {
t.plan(1);
var layer = new OpenLayers.Layer.Vector(name);
var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
var pointFeature = new OpenLayers.Feature.Vector(point);
layer.addFeatures([pointFeature]);
var point = new OpenLayers.Geometry.Point(-111.04, 5.68);
var pointFeature = new OpenLayers.Feature.Vector(point);
layer.addFeatures([pointFeature]);
var extent = layer.getDataExtent();
t.ok(extent.toBBOX() != layer.features[0].geometry.getBounds().toBBOX(), "extent from getDataExtent doesn't clobber first feature");
}
function test_Layer_Vector_removeFeatures(t) {
t.plan(6);
var layer = new OpenLayers.Layer.Vector(name);
var point1 = new OpenLayers.Geometry.Point(-111.04, 45.68);
var pointFeature1 = new OpenLayers.Feature.Vector(layer, point1);
var point2 = new OpenLayers.Geometry.Point(-111.14, 45.78);
var pointFeature2 = new OpenLayers.Feature.Vector(layer, point2);
layer.addFeatures([pointFeature1, pointFeature2]);
var features = layer.removeFeatures([pointFeature1]);
t.ok(layer.features.length == 1, "OpenLayers.Layer.Vector.removeFeatures removes a feature from the features array");
layer.addFeatures([pointFeature1.clone(), pointFeature2.clone()]);
layer.selectedFeatures.push(layer.features[0]);
layer.removeFeatures(layer.features[0]);
t.eq(layer.selectedFeatures, [], "Remove features removes selected features");
var features = layer.removeFeatures(layer.features);
t.ok(layer.features.length == 0,
"OpenLayers.Layer.Vector.removeFeatures(layer.features) removes all feature from the features array");
// 3 tests
layer.events.register('beforefeatureremoved', null, function(obj) {
t.ok(pointFeature1 == obj.feature,
"OpenLayers.Layer.Vector.removeFeatures triggers beforefeatureremoved with correct feature passed to callback");
});
layer.events.register('featureremoved', null, function(obj) {
t.ok(pointFeature1 == obj.feature,
"OpenLayers.Layer.Vector.removeFeatures triggers featureremoved with correct feature passed to callback");
});
layer.events.register('featuresremoved', null, function(obj) {
t.ok(pointFeature1 == obj.features[0],
"OpenLayers.Layer.Vector.removeFeatures triggers featuresremoved with correct features passed to callback");
});
layer.addFeatures([pointFeature1]);
layer.removeFeatures([pointFeature1]);
// 0 test
layer.events.register('beforefeatureremoved', null, function(obj) {
t.fail("OpenLayers.Layer.Vector.removeFeatures triggers beforefeatureremoved while it must not");
});
layer.events.register('featureremoved', null, function(obj) {
t.fail("OpenLayers.Layer.Vector.removeFeatures triggers featureremoved while it must not");
});
layer.events.register('featuresremoved', null, function(obj) {
t.fail("OpenLayers.Layer.Vector.removeFeatures triggers featuresremoved while it must not");
});
layer.addFeatures([pointFeature1]);
layer.removeFeatures([pointFeature1], {silent: true});
}
function test_Layer_Vector_drawFeature(t) {
t.plan(7);
var layer = new OpenLayers.Layer.Vector("Test Layer", {isBaseLayer: true});
var map = new OpenLayers.Map('map', {
maxExtent: new OpenLayers.Bounds(-100, -100, 100, 100)
});
map.addLayer(layer);
var geometry = new OpenLayers.Geometry.Point(10, 10);
var feature = new OpenLayers.Feature.Vector(geometry);
var f, s;
// Bogus layer renderer needs some methods
// for functional tests.
layer.drawn = true;
layer.renderer = {
drawFeature: function(feature, style) {
f = feature;
s = style;
},
root: document.createElement("div"),
destroy: function() { },
eraseFeatures: function() {},
setExtent: function() {}
};
layer.drawFeature(feature);
t.ok(geometry.equals(f.geometry),
"calls layer.renderer.drawFeature() with feature.geometry");
feature.style = {foo: "bar"};
layer.drawFeature(feature);
t.eq(feature.style, s,
"calls layer.renderer.drawFeature() with feature.style");
feature.style = null;
layer.style = {foo: "bar"};
layer.drawFeature(feature);
t.eq(layer.style.foo, s.foo,
"given null feature style, uses layer style");
feature.style = {foo1: "bar1"};
layer.style = {foo2: "bar2"};
var customStyle = {foo: "bar"};
layer.drawFeature(feature, customStyle);
t.eq(customStyle.foo, s.foo,
"given a custom style, renders with that");
// the real renderer's drawFeature method is tested in Renderer.html
layer.renderer.drawFeature = function(feature) {
return(feature.geometry.getBounds().intersectsBounds(map.getExtent()));
}
// reset the drawn to null as if the layer had never been rendered
layer.drawn = null;
layer.drawFeature(feature);
t.ok(true, "Trying to draw a feature on an not drawn layer doesn't throw any error.");
layer.addFeatures([feature]);
map.setCenter(new OpenLayers.Bounds(0, 0, 0, 0), 6);
t.ok(layer.unrenderedFeatures[feature.id], "Did not render feature outside the viewport.");
map.panTo(new OpenLayers.LonLat(10, 10));
t.ok(!layer.unrenderedFeatures[feature.id], "Rendered feature inside the viewport.");
layer.features = [];
}
function test_deleted_state(t) {
t.plan(9);
var map = new OpenLayers.Map("map");
var layer = new OpenLayers.Layer.Vector(null, {
drawn: true
});
map.addLayer(layer);
var feature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(10, 10)
);
var log;
layer.renderer = {
drawFeature: function(f, s) {
log = {
feature: f,
style: s
};
},
destroy: function() {}
};
// draw feature with no state
layer.drawFeature(feature);
t.ok(log.feature === feature, "[no state] drawFeature called with correct feature");
t.ok(log.style.display !== "none", "[no state] drawFeature called with style display not none");
// draw feature with delete style
feature.state = OpenLayers.State.DELETE;
layer.drawFeature(feature);
t.ok(log.feature === feature, "[delete] drawFeature called with correct feature");
t.eq(log.style.display, "none", "[delete] drawFeature called with style display none");
// undelete the feature and redraw
delete feature.state;
delete feature.renderIntent;
layer.drawFeature(feature);
t.ok(log.feature === feature, "[undelete] drawFeature called with correct feature");
t.ok(log.style.display !== "none", "[undelete] drawFeature called with style display not none");
// change deleted style
layer.styleMap.styles["delete"] = new OpenLayers.Style({fillOpacity: 0.1});
// draw feature with delete style
feature.state = OpenLayers.State.DELETE;
layer.drawFeature(feature);
t.ok(log.feature === feature, "[draw deleted] drawFeature called with correct feature");
t.ok(log.style.display !== "none", "[draw deleted] drawFeature called with style display not none");
t.eq(log.style.fillOpacity, 0.1,"[draw deleted] drawFeature called with correct fill opacity");
}
function test_Layer_Vector_eraseFeatures(t) {
t.plan(2);
var layer = new OpenLayers.Layer.Vector("Test Layer");
var map = new OpenLayers.Map('map');
map.addLayer(layer);
var geometry = new OpenLayers.Geometry.Point(10, 10);
var feature = new OpenLayers.Feature.Vector(geometry);
var f;
layer.renderer = {
eraseFeatures: function(features) {
f = features[0];
},
destroy: function() { }
};
layer.eraseFeatures([feature]);
t.ok(f, "calls layer.renderer.eraseFeatures");
t.ok(geometry.equals(f.geometry),
"calls layer.renderer.eraseFeatures() given an array of features");
}
function test_Layer_Vector_destroyFeatures (t) {
t.plan(5);
layer = new OpenLayers.Layer.Vector(name);
var map = new OpenLayers.Map('map');
map.addLayer(layer);
var features = [];
for (var i = 0; i < 5; i++) {
features.push(new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(0,0)));
}
layer.addFeatures(features);
t.eq(layer.features.length, 5, "addFeatures adds 5 features");
layer.selectedFeatures.push(features[0]);
layer.destroyFeatures();
t.eq(layer.features.length, 0, "destroyFeatures triggers removal");
t.eq(layer.selectedFeatures, [], "Destroy features removes selected features");
features = [];
for (var i = 0; i < 5; i++) {
features.push(new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(0,0)));
}
layer.addFeatures(features);
layer.selectedFeatures.push(features[0]);
layer.selectedFeatures.push(features[1]);
layer.destroyFeatures([features[0], features[1]]);
t.eq(layer.features.length, 3, "destroyFeatures removes appropriate features");
t.eq(layer.selectedFeatures, [], "destroyFeatures removes appropriate selected features");
}
function test_Layer_Vector_destroy (t) {
t.plan(5);
var options = {protocol: new OpenLayers.Protocol(),
strategies: [new OpenLayers.Strategy(), new OpenLayers.Strategy()]}
var layer = new OpenLayers.Layer.Vector(name, options);
var map = new OpenLayers.Map('map');
map.addLayer(layer);
layer.destroy();
t.eq(layer.map, null, "layer.map is null after destroy");
t.eq(layer.getFeatureFromEvent({'target':'map'}), null,
"getFeatureIdFromEvent doesn't cause an error when called on layer which has been destroyed.");
t.eq(layer.protocol, null, "layer.protocol is null after destroy");
t.eq(layer.strategies, null, "layer.strategies is null after destroy");
// test that we can call layer.destroy a second time without trouble
try {
layer.destroy();
layer.destroy();
t.ok(true, "layer.destroy called twice without any issues");
} catch(err) {
t.fail("calling layer.destroy twice triggers exception: " + err + " in " + err.fileName + " line " + err.lineNumber);
}
}
function test_Layer_Vector_externalGraphic(t) {
t.plan(11);
var layer = new OpenLayers.Layer.Vector("Test Layer", {isBaseLayer: true});
var renderer = layer.renderer;
var map = new OpenLayers.Map('map');
map.addLayers([layer]);
var geometryX = 10;
var geometryY = 10;
var geometry = new OpenLayers.Geometry.Point(geometryX, geometryY);
var feature = new OpenLayers.Feature.Vector(geometry);
map.zoomToMaxExtent();
var customStyle1 = new Object({
externalGraphic: 'test.png',
pointRadius: 10
});
var customStyle2 = new Object({
externalGraphic: 'test.png',
graphicWidth: 12
});
var customStyle3 = new Object({
externalGraphic: 'test.png',
graphicHeight: 14
});
var customStyle4 = new Object({
externalGraphic: 'test.png',
graphicWidth: 24,
graphicHeight: 16
});
var customStyle5 = new Object({
externalGraphic: 'test.png',
graphicWidth: 24,
graphicOpacity: 1
});
var customStyle6 = new Object({
externalGraphic: 'test.png',
graphicWidth: 24,
graphicHeight: 16,
graphicXOffset: -24,
graphicYOffset: -16
});
var root = renderer.vectorRoot;
if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.SVG') {
feature.style = customStyle1;
layer.drawFeature(feature);
t.eq(root.firstChild.getAttributeNS(null, 'width'),
(2*customStyle1.pointRadius).toString(),
"given a pointRadius, width equals 2*pointRadius");
t.eq(root.firstChild.getAttributeNS(null, 'height'),
(2*customStyle1.pointRadius).toString(),
"given a pointRadius, height equals 2*pointRadius");
feature.style = customStyle2;
layer.drawFeature(feature);
t.eq(root.firstChild.getAttributeNS(null, 'width'),
root.firstChild.getAttributeNS(null, 'height'),
"given a graphicWidth, width equals height");
t.eq(root.firstChild.getAttributeNS(null, 'width'),
customStyle2.graphicWidth.toString(),
"width is set correctly");
feature.style = customStyle3;
layer.drawFeature(feature);
t.eq(root.firstChild.getAttributeNS(null, 'height'),
root.firstChild.getAttributeNS(null, 'width'),
"given a graphicHeight, height equals width");
t.eq(root.firstChild.getAttributeNS(null, 'height'),
customStyle3.graphicHeight.toString(),
"height is set correctly");
feature.style = customStyle4;
layer.drawFeature(feature);
t.eq(root.firstChild.getAttributeNS(null, 'height'),
customStyle4.graphicHeight.toString(),
"given graphicHeight and graphicWidth, both are set: height");
t.eq(root.firstChild.getAttributeNS(null, 'width'),
customStyle4.graphicWidth.toString(),
"given graphicHeight and graphicWidth, both are set: width");
feature.style = customStyle5;
layer.drawFeature(feature);
t.eq(root.firstChild.getAttributeNS(null, 'style'),
'opacity: '+customStyle5.graphicOpacity.toString()+((OpenLayers.Util.getBrowserName() == "opera" || OpenLayers.Util.getBrowserName() == "safari") ? "" : ';'),
"graphicOpacity correctly set");
feature.style = customStyle6;
layer.drawFeature(feature);
var x = geometryX / renderer.getResolution() + renderer.left;
var y = geometryY / renderer.getResolution() - renderer.top;
// SVG setStyle() gets x and y using getAttributeNS(), which returns
// a value with only 3 decimal digits. To mimic this we use toFixed(3) here
x = x.toFixed(3);
y = y.toFixed(3);
// toFixed() returns a string
x = parseFloat(x);
y = parseFloat(y);
t.eq(root.firstChild.getAttributeNS(null, 'x'),
(x + customStyle6.graphicXOffset).toFixed().toString(),
"graphicXOffset correctly set");
t.eq(root.firstChild.getAttributeNS(null, 'y'),
(-y + customStyle6.graphicYOffset).toFixed().toString(),
"graphicYOffset correctly set");
}
if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.VML') {
feature.style = customStyle1;
layer.drawFeature(feature);
t.eq(root.firstChild.style.width,
(2*customStyle1.pointRadius).toString()+'px',
"given a pointRadius, width equals 2*pointRadius");
t.eq(root.firstChild.style.height,
(2*customStyle1.pointRadius).toString()+'px',
"given a pointRadius, height equals 2*pointRadius");
feature.style = customStyle2;
layer.drawFeature(feature);
t.eq(root.firstChild.style.width,
root.firstChild.style.height,
"given a graphicWidth, width equals height");
t.eq(root.firstChild.style.width,
customStyle2.graphicWidth.toString()+'px',
"width is set correctly");
feature.style = customStyle3;
layer.drawFeature(feature);
t.eq(root.firstChild.style.height,
root.firstChild.style.width,
"given a graphicHeight, height equals width");
t.eq(root.firstChild.style.height,
customStyle3.graphicHeight.toString()+'px',
"height is set correctly");
feature.style = customStyle4;
layer.drawFeature(feature);
t.eq(root.firstChild.style.height,
customStyle4.graphicHeight.toString()+'px',
"given graphicHeight and graphicWidth, both are set: height");
t.eq(root.firstChild.style.width,
customStyle4.graphicWidth.toString()+'px',
"given graphicHeight and graphicWidth, both are set: width");
feature.style = customStyle5;
layer.renderer.clear();
layer.drawFeature(feature);
var fill = root.firstChild.getElementsByTagName("v:fill")[0];
var opacity;
if(fill) {
opacity = fill.getAttribute('opacity');
}
if(opacity === undefined) {
fill = root.firstChild.getElementsByTagName("fill")[0];
opacity = fill.getAttribute('opacity');
}
t.eq(opacity,
customStyle5.graphicOpacity,
"graphicOpacity correctly set");
feature.style = customStyle6;
layer.drawFeature(feature);
var x = geometryX / renderer.getResolution();
var y = geometryY / renderer.getResolution();
t.eq(root.firstChild.style.left,
(x + customStyle6.graphicXOffset).toFixed().toString()+'px',
"graphicXOffset correctly set");
t.eq(root.firstChild.style.top,
(y - (customStyle6.graphicYOffset+parseInt(root.firstChild.style.height))).toFixed().toString()+'px',
"graphicYOffset correctly set");
}
}
</script>
</head>
<body>
<div id="map" style="width:500px;height:550px"></div>
</body>
</html>