]> dev.renevier.net Git - syp.git/blob - openlayers/tests/Layer/Vector.html
initial commit
[syp.git] / openlayers / tests / Layer / Vector.html
1 <html>
2 <head>
3 <script src="../../lib/OpenLayers.js"></script>
4   <script type="text/javascript">
5
6     var name = "Vector Layer";
7     
8     function test_Layer_Vector_constructor(t) {
9         t.plan(4);
10
11         var options = {protocol: new OpenLayers.Protocol(), 
12                        strategies: [new OpenLayers.Strategy(), new OpenLayers.Strategy()]}
13         var layer = new OpenLayers.Layer.Vector(name, options);
14
15         t.ok(layer instanceof OpenLayers.Layer.Vector, "new OpenLayers.Layer.Vector returns correct object" );
16         t.eq(layer.name, name, "layer name is correctly set");
17         t.ok(layer.renderer.CLASS_NAME, "layer has a renderer");
18         
19         t.ok((layer.name == layer.strategies[0].layer.name) &&
20              (layer.strategies[0].layer.name == layer.strategies[1].layer.name), 
21              "setLayer was called on strategies");
22     }
23
24     function test_Layer_Vector_refresh(t) {
25         t.plan(4);
26
27         var obj = {"an": "object"};
28
29         var log;
30         var layer = new OpenLayers.Layer.Vector(name, {
31             eventListeners: {
32                 refresh: function(o) {
33                     log.obj = o;
34                 }
35             }
36         });
37         inRange = false;
38         layer.calculateInRange = function() {
39             return inRange;
40         };
41
42         log = {};
43         inRange = false;
44         layer.visibility = false;
45         layer.refresh(obj);
46         t.eq(log.obj, undefined, "[false, false] refresh not triggered");
47
48         log = {};
49         inRange = true;
50         layer.visibility = false;
51         layer.refresh(obj);
52         t.eq(log.obj, undefined, "[true, false] refresh not triggered");
53
54         log = {};
55         inRange = false;
56         layer.visibility = true;
57         layer.refresh(obj);
58         t.eq(log.obj, undefined, "[false, true] refresh not triggered");
59
60         log = {};
61         inRange = true;
62         layer.visibility = true;
63         layer.refresh(obj);
64         t.ok(log.obj === obj, "[true, true] refresh triggered with correct arg");
65     }
66     
67     function test_Layer_Vector_addFeatures(t) {
68         t.plan(8);
69     
70         var layer = new OpenLayers.Layer.Vector(name);
71
72         var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
73         var pointFeature = new OpenLayers.Feature.Vector(point);
74
75         layer.preFeatureInsert = function(feature) {
76             t.ok(feature == pointFeature, "OpenLayers.Layer.Vector.addFeatures calls preFeatureInsert with the right arg");
77         };
78         layer.onFeatureInsert = function(feature) {
79             t.ok(feature == pointFeature, "OpenLayers.Layer.Vector.addFeatures calls onFeatureInsert with the right arg");
80         };
81         layer.events.register('beforefeatureadded', null, function(obj) {
82             t.ok(pointFeature == obj.feature, "OpenLayers.Layer.Vector.addFeatures triggers beforefeatureadded with correct feature passed to callback");
83         });
84         layer.events.register('featureadded', null, function(obj) {
85             t.ok(pointFeature == obj.feature, "OpenLayers.Layer.Vector.addFeatures triggers featureadded with correct feature passed to callback");
86         });
87         layer.events.register('featuresadded', null, function(obj) {
88             t.ok(pointFeature == obj.features[0], "OpenLayers.Layer.Vector.addFeatures triggers featuresadded with correct features passed to callback");
89         });
90
91         layer.addFeatures([pointFeature]);
92         
93         t.eq(layer.features.length, 1, "OpenLayers.Layer.Vector.addFeatures adds something to the array");
94         t.ok(layer.features[0] == pointFeature, "OpenLayers.Layer.Vector.addFeatures returns an array of features");
95
96         layer.preFeatureInsert = function(feature) {
97             t.fail("OpenLayers.Layer.Vector.addFeatures calls preFeatureInsert while it must not");
98         };
99         layer.onFeatureInsert = function(feature) {
100             t.fail("OpenLayers.Layer.Vector.addFeatures calls onFeatureInsert while it must not");
101         };
102         layer.events.register('beforefeatureadded', null, function(obj) {
103             t.fail("OpenLayers.Layer.Vector.addFeatures triggers beforefeatureadded while it must not");
104         });
105         layer.events.register('featureadded', null, function(obj) {
106             t.fail("OpenLayers.Layer.Vector.addFeatures triggers featureadded while it must not");
107         });
108         layer.events.register('featuresadded', null, function(obj) {
109             t.fail("OpenLayers.Layer.Vector.addFeatures triggers featuresadded while it must not");
110         });
111
112         layer.addFeatures([pointFeature], {silent: true});
113
114         var extent = layer.getDataExtent();
115         t.eq(extent.toBBOX(), "-111.04,45.68,-111.04,45.68", "extent from getDataExtent is correct");
116     }
117
118     function test_Layer_Vector_getDataExtent(t) {
119         t.plan(1);
120         var layer = new OpenLayers.Layer.Vector(name);
121
122         var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
123         var pointFeature = new OpenLayers.Feature.Vector(point);
124         layer.addFeatures([pointFeature]);
125         var point = new OpenLayers.Geometry.Point(-111.04, 5.68);
126         var pointFeature = new OpenLayers.Feature.Vector(point);
127         layer.addFeatures([pointFeature]);
128         var extent = layer.getDataExtent();
129         t.ok(extent.toBBOX() != layer.features[0].geometry.getBounds().toBBOX(), "extent from getDataExtent doesn't clobber first feature");
130     }
131
132     function test_Layer_Vector_removeFeatures(t) {
133         t.plan(9);
134     
135         var layer = new OpenLayers.Layer.Vector(name);
136
137         var point1 = new OpenLayers.Geometry.Point(-111.04, 45.68);
138         var pointFeature1 = new OpenLayers.Feature.Vector(layer, point1);
139         var point2 = new OpenLayers.Geometry.Point(-111.14, 45.78);
140         var pointFeature2 = new OpenLayers.Feature.Vector(layer, point2);
141       
142         layer.addFeatures([pointFeature1, pointFeature2]);
143         var features = layer.removeFeatures([pointFeature1]);
144         
145         t.ok(layer.features.length == 1, "OpenLayers.Layer.Vector.removeFeatures removes a feature from the features array");
146         layer.addFeatures([pointFeature1.clone(), pointFeature2.clone()]);
147         layer.selectedFeatures.push(layer.features[0]); 
148         layer.removeFeatures(layer.features[0]);
149         t.eq(layer.selectedFeatures, [], "Remove features removes selected features");
150         var features = layer.removeFeatures(layer.features);
151         
152         t.ok(layer.features.length == 0,
153              "OpenLayers.Layer.Vector.removeFeatures(layer.features) removes all feature from the features array");
154
155         // 6 tests
156         layer.events.register('beforefeatureremoved', null, function(obj) {
157             t.ok(pointFeature1 == obj.feature,
158                  "OpenLayers.Layer.Vector.removeFeatures triggers beforefeatureremoved with correct feature passed to callback");
159         });
160         layer.events.register('featureremoved', null, function(obj) {
161             t.ok(pointFeature1 == obj.feature,
162                  "OpenLayers.Layer.Vector.removeFeatures triggers featureremoved with correct feature passed to callback");
163         });
164         layer.events.register('featuresremoved', null, function(obj) {
165             t.ok(pointFeature1 == obj.features[0],
166                  "OpenLayers.Layer.Vector.removeFeatures triggers featuresremoved with correct features passed to callback");
167         });
168         layer.addFeatures([pointFeature1]);
169         layer.removeFeatures([pointFeature1]);
170         layer.addFeatures([pointFeature1]);
171         layer.removeFeatures(layer.features);
172
173         // 0 test
174         layer.events.register('beforefeatureremoved', null, function(obj) {
175             t.fail("OpenLayers.Layer.Vector.removeFeatures triggers beforefeatureremoved while it must not");
176         });
177         layer.events.register('featureremoved', null, function(obj) {
178             t.fail("OpenLayers.Layer.Vector.removeFeatures triggers featureremoved while it must not");
179         });
180         layer.events.register('featuresremoved', null, function(obj) {
181             t.fail("OpenLayers.Layer.Vector.removeFeatures triggers featuresremoved while it must not");
182         });
183         layer.addFeatures([pointFeature1]);
184         layer.removeFeatures([pointFeature1], {silent: true});
185      }
186     
187     function test_Layer_Vector_drawFeature(t) {
188         t.plan(7);
189         var layer = new OpenLayers.Layer.Vector("Test Layer", {isBaseLayer: true});
190         var map = new OpenLayers.Map('map', {
191             maxExtent: new OpenLayers.Bounds(-100, -100, 100, 100)
192         });
193         map.addLayer(layer);
194         var geometry = new OpenLayers.Geometry.Point(10, 10);
195         var feature = new OpenLayers.Feature.Vector(geometry);
196         
197         var f, s;
198         
199         // Bogus layer renderer needs some methods
200         // for functional tests.
201         layer.drawn = true;
202         layer.renderer = {
203             drawFeature: function(feature, style) {
204                 f = feature;
205                 s = style;
206             },
207             root: document.createElement("div"),
208             destroy: function() { },
209             eraseFeatures: function() {},
210             setExtent: function() {}
211         };
212         
213
214         layer.drawFeature(feature);
215         t.ok(geometry.equals(f.geometry),
216              "calls layer.renderer.drawFeature() with feature.geometry");
217         
218         feature.style = {foo: "bar"};
219         layer.drawFeature(feature);
220         t.eq(feature.style, s,
221              "calls layer.renderer.drawFeature() with feature.style");
222         
223         feature.style = null;
224         layer.style = {foo: "bar"};
225         layer.drawFeature(feature);
226         t.eq(layer.style.foo, s.foo,
227              "given null feature style, uses layer style");
228
229         feature.style = {foo1: "bar1"};
230         layer.style = {foo2: "bar2"};
231         var customStyle = {foo: "bar"};
232         layer.drawFeature(feature, customStyle);
233         t.eq(customStyle.foo, s.foo,
234              "given a custom style, renders with that");
235         
236         // the real renderer's drawFeature method is tested in Renderer.html
237         layer.renderer.drawFeature = function(feature) {
238             return(feature.geometry.getBounds().intersectsBounds(map.getExtent()));
239         }
240         // reset the drawn to null as if the layer had never been rendered
241         layer.drawn = null;
242         
243         layer.drawFeature(feature);
244         t.ok(true, "Trying to draw a feature on an not drawn layer doesn't throw any error.");
245         
246         layer.addFeatures([feature]);
247         
248         map.setCenter(new OpenLayers.Bounds(0, 0, 0, 0), 6);
249         t.ok(layer.unrenderedFeatures[feature.id], "Did not render feature outside the viewport.");
250         map.panTo(new OpenLayers.LonLat(10, 10));
251         t.ok(!layer.unrenderedFeatures[feature.id], "Rendered feature inside the viewport.");
252         
253         layer.features = [];
254     }
255     
256     function test_deleted_state(t) {
257         t.plan(9);
258         
259         var map = new OpenLayers.Map("map");
260         var layer = new OpenLayers.Layer.Vector(null, {
261             drawn: true
262         });
263         map.addLayer(layer);
264         var feature = new OpenLayers.Feature.Vector(
265             new OpenLayers.Geometry.Point(10, 10)
266         );
267         var log;
268         layer.renderer = {
269             drawFeature: function(f, s) {
270                 log = {
271                     feature: f,
272                     style: s
273                 };
274             },
275             destroy: function() {}
276         };
277         
278         // draw feature with no state
279         layer.drawFeature(feature);
280         t.ok(log.feature === feature, "[no state] drawFeature called with correct feature");
281         t.ok(log.style.display !== "none", "[no state] drawFeature called with style display not none");
282
283         // draw feature with delete style
284         feature.state = OpenLayers.State.DELETE;
285         layer.drawFeature(feature);
286         t.ok(log.feature === feature, "[delete] drawFeature called with correct feature");
287         t.eq(log.style.display, "none", "[delete] drawFeature called with style display none");
288
289         // undelete the feature and redraw
290         delete feature.state;
291         delete feature.renderIntent;
292         layer.drawFeature(feature);
293         t.ok(log.feature === feature, "[undelete] drawFeature called with correct feature");
294         t.ok(log.style.display !== "none", "[undelete] drawFeature called with style display not none");
295         
296         // change deleted style
297         layer.styleMap.styles["delete"] = new OpenLayers.Style({fillOpacity: 0.1});
298
299         // draw feature with delete style
300         feature.state = OpenLayers.State.DELETE;
301         layer.drawFeature(feature);
302         t.ok(log.feature === feature, "[draw deleted] drawFeature called with correct feature");
303         t.ok(log.style.display !== "none", "[draw deleted] drawFeature called with style display not none");
304         t.eq(log.style.fillOpacity, 0.1,"[draw deleted] drawFeature called with correct fill opacity");
305
306         
307     }
308     
309     function test_Layer_Vector_eraseFeatures(t) {
310         t.plan(2);
311         var layer = new OpenLayers.Layer.Vector("Test Layer");
312         var map = new OpenLayers.Map('map');
313         map.addLayer(layer);
314         var geometry = new OpenLayers.Geometry.Point(10, 10);
315         var feature = new OpenLayers.Feature.Vector(geometry);
316         
317         var f;
318         layer.renderer = {
319             eraseFeatures: function(features) {
320                 f = features[0];
321             },
322             destroy: function() { }
323         };
324
325         layer.eraseFeatures([feature]);
326         t.ok(f, "calls layer.renderer.eraseFeatures");
327         t.ok(geometry.equals(f.geometry),
328              "calls layer.renderer.eraseFeatures() given an array of features");
329     }
330
331     function test_Layer_Vector_destroyFeatures (t) {
332         t.plan(5); 
333         layer = new OpenLayers.Layer.Vector(name);
334         var map = new OpenLayers.Map('map');
335         map.addLayer(layer);
336         var features = [];
337         for (var i = 0; i < 5; i++) {
338             features.push(new OpenLayers.Feature.Vector(
339                           new OpenLayers.Geometry.Point(0,0)));
340         }
341         layer.addFeatures(features);
342         t.eq(layer.features.length, 5, "addFeatures adds 5 features");
343         layer.selectedFeatures.push(features[0]); 
344         layer.destroyFeatures();
345         t.eq(layer.features.length, 0, "destroyFeatures triggers removal");
346         t.eq(layer.selectedFeatures, [], "Destroy features removes selected features");
347         features = [];
348         for (var i = 0; i < 5; i++) {
349             features.push(new OpenLayers.Feature.Vector(
350                           new OpenLayers.Geometry.Point(0,0)));
351         }
352         layer.addFeatures(features);
353         layer.selectedFeatures.push(features[0]);
354         layer.selectedFeatures.push(features[1]);
355         layer.destroyFeatures([features[0], features[1]]);
356         t.eq(layer.features.length, 3, "destroyFeatures removes appropriate features");
357         t.eq(layer.selectedFeatures, [], "destroyFeatures removes appropriate selected features");
358     }
359
360     function test_Layer_Vector_destroy (t) {
361         t.plan(5);    
362
363         var options = {protocol: new OpenLayers.Protocol(), 
364                        strategies: [new OpenLayers.Strategy(), new OpenLayers.Strategy()]}
365         var layer = new OpenLayers.Layer.Vector(name, options);
366         var map = new OpenLayers.Map('map');
367         map.addLayer(layer);
368         layer.destroy();
369         t.eq(layer.map, null, "layer.map is null after destroy");
370         t.eq(layer.getFeatureFromEvent({'target':'map'}), null, 
371             "getFeatureIdFromEvent doesn't cause an error when called on layer which has been destroyed.");
372
373         t.eq(layer.protocol, null, "layer.protocol is null after destroy");
374         t.eq(layer.strategies, null, "layer.strategies is null after destroy");
375         
376         // test that we can call layer.destroy a second time without trouble
377         try {
378             layer.destroy();
379             layer.destroy();
380             t.ok(true, "layer.destroy called twice without any issues");
381         } catch(err) {
382             t.fail("calling layer.destroy twice triggers exception: " + err + " in " + err.fileName + " line " + err.lineNumber);
383         }
384         
385     }
386
387     function test_Layer_Vector_externalGraphic(t) {
388         t.plan(11);
389         var layer = new OpenLayers.Layer.Vector("Test Layer", {isBaseLayer: true});
390         var renderer = layer.renderer;
391         var map = new OpenLayers.Map('map');
392         map.addLayers([layer]);
393
394         var geometryX = 10;
395         var geometryY = 10;
396         var geometry = new OpenLayers.Geometry.Point(geometryX, geometryY);
397         var feature = new OpenLayers.Feature.Vector(geometry);
398
399         map.zoomToMaxExtent();
400
401         var customStyle1 = new Object({
402                 externalGraphic: 'test.png',
403                 pointRadius: 10
404         });
405         var customStyle2 = new Object({
406                 externalGraphic: 'test.png',
407                 graphicWidth: 12
408         });
409         var customStyle3 = new Object({
410                 externalGraphic: 'test.png',
411                 graphicHeight: 14
412         });
413         var customStyle4 = new Object({
414                 externalGraphic: 'test.png',
415                 graphicWidth: 24,
416                 graphicHeight: 16
417         });
418         var customStyle5 = new Object({
419                 externalGraphic: 'test.png',
420                 graphicWidth: 24,
421                 graphicOpacity: 1
422         });
423         var customStyle6 = new Object({
424                 externalGraphic: 'test.png',
425                 graphicWidth: 24,
426                 graphicHeight: 16,
427                 graphicXOffset: -24,
428                 graphicYOffset: -16
429         });
430                
431         var root = renderer.vectorRoot;
432         if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.SVG') {
433                 feature.style = customStyle1;
434                 layer.drawFeature(feature);
435                 t.eq(root.firstChild.getAttributeNS(null, 'width'),
436                              (2*customStyle1.pointRadius).toString(),
437                              "given a pointRadius, width equals 2*pointRadius");
438                 t.eq(root.firstChild.getAttributeNS(null, 'height'),
439                              (2*customStyle1.pointRadius).toString(),
440                              "given a pointRadius, height equals 2*pointRadius");
441                 feature.style = customStyle2;
442                 layer.drawFeature(feature);
443                 t.eq(root.firstChild.getAttributeNS(null, 'width'),
444                              root.firstChild.getAttributeNS(null, 'height'),
445                              "given a graphicWidth, width equals height");
446                 t.eq(root.firstChild.getAttributeNS(null, 'width'),
447                              customStyle2.graphicWidth.toString(),
448                              "width is set correctly");
449                 feature.style = customStyle3;
450                 layer.drawFeature(feature);
451                 t.eq(root.firstChild.getAttributeNS(null, 'height'),
452                              root.firstChild.getAttributeNS(null, 'width'),
453                              "given a graphicHeight, height equals width");
454                 t.eq(root.firstChild.getAttributeNS(null, 'height'),
455                              customStyle3.graphicHeight.toString(),
456                              "height is set correctly");
457                 feature.style = customStyle4;
458                 layer.drawFeature(feature);
459                 t.eq(root.firstChild.getAttributeNS(null, 'height'),
460                              customStyle4.graphicHeight.toString(),
461                              "given graphicHeight and graphicWidth, both are set: height");
462                 t.eq(root.firstChild.getAttributeNS(null, 'width'),
463                              customStyle4.graphicWidth.toString(),
464                              "given graphicHeight and graphicWidth, both are set: width");
465                 feature.style = customStyle5;
466                 layer.drawFeature(feature);
467                 t.eq(root.firstChild.getAttributeNS(null, 'style'),
468                              'opacity: '+customStyle5.graphicOpacity.toString()+((OpenLayers.Util.getBrowserName() == "opera" || OpenLayers.Util.getBrowserName() == "safari") ? "" : ';'),
469                              "graphicOpacity correctly set");
470                 feature.style = customStyle6;
471                 layer.drawFeature(feature);
472                 var x = geometryX / renderer.getResolution() + renderer.left;
473                 var y = geometryY / renderer.getResolution() - renderer.top;
474                 // SVG setStyle() gets x and y using getAttributeNS(), which returns
475                 // a value with only 3 decimal digits. To mimic this we use toFixed(3) here
476                 x = x.toFixed(3);
477                 y = y.toFixed(3);
478                 // toFixed() returns a string
479                 x = parseFloat(x);
480                 y = parseFloat(y);
481                 t.eq(root.firstChild.getAttributeNS(null, 'x'),
482                         (x + customStyle6.graphicXOffset).toFixed().toString(),
483                         "graphicXOffset correctly set");
484                 t.eq(root.firstChild.getAttributeNS(null, 'y'),
485                         (-y + customStyle6.graphicYOffset).toFixed().toString(),
486                         "graphicYOffset correctly set");
487         }
488         if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.VML') {
489                 feature.style = customStyle1;
490                 layer.drawFeature(feature);
491                 t.eq(root.firstChild.style.width,
492                              (2*customStyle1.pointRadius).toString()+'px',
493                              "given a pointRadius, width equals 2*pointRadius");
494                 t.eq(root.firstChild.style.height,
495                              (2*customStyle1.pointRadius).toString()+'px',
496                              "given a pointRadius, height equals 2*pointRadius");
497                 feature.style = customStyle2;
498                 layer.drawFeature(feature);
499                 t.eq(root.firstChild.style.width,
500                              root.firstChild.style.height,
501                              "given a graphicWidth, width equals height");
502                 t.eq(root.firstChild.style.width,
503                              customStyle2.graphicWidth.toString()+'px',
504                              "width is set correctly");
505                 feature.style = customStyle3;
506                 layer.drawFeature(feature);
507                 t.eq(root.firstChild.style.height,
508                              root.firstChild.style.width,
509                              "given a graphicHeight, height equals width");
510                 t.eq(root.firstChild.style.height,
511                              customStyle3.graphicHeight.toString()+'px',
512                              "height is set correctly");
513                 feature.style = customStyle4;
514                 layer.drawFeature(feature);
515                 t.eq(root.firstChild.style.height,
516                              customStyle4.graphicHeight.toString()+'px',
517                              "given graphicHeight and graphicWidth, both are set: height");
518                 t.eq(root.firstChild.style.width,
519                              customStyle4.graphicWidth.toString()+'px',
520                              "given graphicHeight and graphicWidth, both are set: width");
521                 feature.style = customStyle5;
522                 layer.renderer.clear();
523                 layer.drawFeature(feature);
524                 var fill = root.firstChild.getElementsByTagName("v:fill")[0];
525                 var opacity;
526                 if(fill) {
527                     opacity = fill.getAttribute('opacity');
528                 }
529                 if(opacity === undefined) {
530                     fill = root.firstChild.getElementsByTagName("fill")[0];
531                     opacity = fill.getAttribute('opacity');
532                 }
533                 t.eq(opacity,
534                              customStyle5.graphicOpacity,
535                              "graphicOpacity correctly set"); 
536                 feature.style = customStyle6;
537                 layer.drawFeature(feature);
538                 var x = geometryX / renderer.getResolution();
539                 var y = geometryY / renderer.getResolution();
540                 t.eq(root.firstChild.style.left,
541                             (x + customStyle6.graphicXOffset).toFixed().toString()+'px',
542                             "graphicXOffset correctly set");
543                             
544                 t.eq(root.firstChild.style.top,
545                             (y - (customStyle6.graphicYOffset+parseInt(root.firstChild.style.height))).toFixed().toString()+'px',
546                             "graphicYOffset correctly set");
547
548         }
549     }
550
551   </script>
552 </head>
553 <body>
554 <div id="map" style="width:500px;height:550px"></div>
555 </body>
556 </html>