summaryrefslogtreecommitdiff
path: root/misc/openlayers/tests/Strategy/BBOX.html
blob: 6e409e6dafaa74390f1af2f22d96ea1ca109650c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
<html>
<head>
  <script src="../OLLoader.js"></script>
  <script type="text/javascript">

    function test_initialize(t) {
        t.plan(1);

        var ratio = 4;

        var s = new OpenLayers.Strategy.BBOX({ratio: ratio});
        t.eq(s.ratio, ratio, "ctor sets ratio");
    }

    function test_activate(t) {
        t.plan(5);

        var l = new OpenLayers.Layer.Vector();
        var s = new OpenLayers.Strategy.BBOX();
        s.setLayer(l);

        t.eq(s.active, false, "not active after construction");

        var activated = s.activate();
        t.eq(activated, true, "activate returns true");
        t.eq(s.active, true, "activated after activate");
        t.ok(l.events.listeners["moveend"][0].obj == s &&
             l.events.listeners["moveend"][0].func == s.update,
             "activates registers moveend listener");
        t.ok(l.events.listeners["refresh"][0].obj == s &&
             l.events.listeners["refresh"][0].func == s.update,
             "activates registers refresh listener");
    }

    function test_update(t) {
        t.plan(7);

        // Create a dummy layer that can act as the map base layer.
        // This will be unnecessary if #1921 is addressed (allowing
        // map to have different projection than base layer).
        var dummy = new OpenLayers.Layer(null, {isBaseLayer: true});

        var strategy = new OpenLayers.Strategy.BBOX({
            ratio: 1 // makes for easier comparison to map bounds
        });
        var log = [];
        var layer = new OpenLayers.Layer.Vector(null, {
            isBaseLayer: true,
            protocol: new OpenLayers.Protocol({abort: function(response) { log.push(response); }}),
            strategies: [strategy]
        });

        // create a map with the layers and a center
        var map = new OpenLayers.Map("map", {zoomMethod: null});
        map.addLayers([dummy, layer]);
        map.zoomToMaxExtent();
        
        /**
         * The setCenter call above should set strategy bounds.  I *think* this
         * issue is captured in http://trac.openlayers.org/ticket/1835.
         * For now, I'm going to force an update on the strategy.  This line
         * should be removed when the issue(s) described in #1835 are addressed.
         */
        strategy.update({force: true});
        strategy.response = {};
        strategy.update({force: true});
        t.eq(log.length, 1, "Response aborted");
        log = [];
        strategy.update({force: true});
        strategy.update({force: true, noAbort: true}); 
        t.eq(log.length, 0, "Response not aborted when noAbort is true");

        // test that the strategy bounds were set
        t.ok(map.getExtent().equals(strategy.bounds), "[set center] bounds set to map extent");
        
        // zoom and test that bounds are not reset
        var old = strategy.bounds.clone();
        map.zoomIn();
        t.ok(strategy.bounds.equals(old), "[zoom in] bounds not reset");
        
        // force update and check that bounds change
        strategy.update({force: true});
        t.ok(!strategy.bounds.equals(old), "[force update] bounds changed");
        t.ok(strategy.bounds.equals(map.getExtent()), "[force update] bounds set to map extent");
        
        // change the layer projection to confirm strategy uses same
        layer.projection = new OpenLayers.Projection("EPSG:900913");
        strategy.update({force: true});
        var from = map.getProjectionObject();
        var to = layer.projection;
        
        var strategyBounds = strategy.bounds,
            mapExtent = map.getExtent().transform(from, to),
            // we don't use bounds::toString because we might run into 
            // precision issues
            precision = 7,
            strategyBoundsGot = [
                strategyBounds.left.toFixed( precision ),
                strategyBounds.bottom.toFixed( precision ),
                strategyBounds.right.toFixed( precision ),
                strategyBounds.top.toFixed( precision )
            ].join(','),
            mapExtentExpected = [
                mapExtent.left.toFixed( precision ),
                mapExtent.bottom.toFixed( precision ),
                mapExtent.right.toFixed( precision ),
                mapExtent.top.toFixed( precision )
            ].join(',');
        t.eq(strategyBoundsGot, mapExtentExpected, 
            "[force update different proj] bounds transformed");
    }
    
    function test_events(t) {
        
        t.plan(7);

        var log = [];

        var response = new OpenLayers.Protocol.Response();

        var map = new OpenLayers.Map("map");
        var layer = new OpenLayers.Layer.Vector(null, {
            strategies: [new OpenLayers.Strategy.BBOX()],
            protocol: new OpenLayers.Protocol({
                read: function(config) {
                    config.callback.call(config.scope, response);
                }
            }),
            isBaseLayer: true,
            eventListeners: {
                loadstart: function(event) {
                    log.push(event);
                },
                loadend: function(event) {
                    log.push(event);
                }
            }            
        });
        map.addLayer(layer);
        map.zoomToMaxExtent();

        t.eq(log.length, 2, "2 events logged");
        t.eq(log[0].type, "loadstart", "loadstart first");
        t.ok(log[0].filter.type === OpenLayers.Filter.Spatial.BBOX, "loadstart includes filter used");
        t.eq(log[1].type, "loadend", "loadend second");
        t.ok(log[1].response == response, "loadend includes response");
        
        var calls = [];
        layer.protocol.read = function(obj) {
            calls.push(obj);
        }
        layer.refresh({force: true, whee: 'chicken'});

        t.eq(calls.length, 1, "1 call to read");
        t.eq(calls[0].whee, "chicken", "properties passed to read");

        map.destroy();
        
    }

    function test_triggerRead(t) {
        t.plan(4);

        var s = new OpenLayers.Strategy.BBOX();

        var filter = {"fake": "filter"};

        s.createFilter = function() {
            return filter;
        };
        s.response = {"fake": "response"};
        
        var log = {};

        var protocol = new OpenLayers.Protocol({
            read: function(options) {
                log.options = options;
            },
            abort: function(response) {
                log.abort = response.fake;
            }
        });
        
        var layer = new OpenLayers.Layer.Vector(null, {
            strategies: [s],
            protocol: protocol,
            isBaseLayer: true
        });
        var map = new OpenLayers.Map("map");
        map.addLayer(layer);
        map.zoomToMaxExtent();
        
        t.ok(log.options.filter == filter,
                "protocol read called with correct filter");
        t.ok(log.options.callback == s.merge,
                "protocol read called with correct callback");
        t.ok(log.options.scope == s,
                "protocol read called with correct scope");
        t.eq(log.abort, "response",
                "protocol abort called with correct response");

        map.destroy();

    }
    
    function test_resFactor(t) {
        t.plan(2);
        
        var map = new OpenLayers.Map("map", {zoomMethod: null});
        var bbox = new OpenLayers.Strategy.BBOX();
        var fakeProtocol = new OpenLayers.Protocol({
            'read': function() { 
                t.ok(true, "read called once without resfactor"); 
            }
        });
        var layer = new OpenLayers.Layer.Vector("test", {
            strategies: [bbox],
            protocol: fakeProtocol,
            isBaseLayer: true
        });
        map.addLayer(layer);
        map.setCenter(new OpenLayers.LonLat(0, 0), 0);
        map.zoomIn();
        
        fakeProtocol.read = function() { 
            t.ok("read called again on zooming with resFactor: 1");
        }
        bbox.resFactor = 1;
        map.zoomIn();
        
    }

    function test_createFilter(t) {
        t.plan(3);

        var s = new OpenLayers.Strategy.BBOX();

        var f;

        // 2 test
        s.setLayer({});
        f = s.createFilter();
        t.ok(f.CLASS_NAME.search(/^OpenLayers.Filter.Spatial/) != -1,
             "createFilter returns a spatial filter object");
        t.eq(f.type, OpenLayers.Filter.Spatial.BBOX,
             "createFilter returns a BBOX-typed filter");

        // 1 test
        s.setLayer({filter: {fake: "filter"}});
        f = s.createFilter();
        t.ok(f.CLASS_NAME.search(/^OpenLayers.Filter.Logical/) != -1,
             "createFilter returns a logical filter object");
    }

    function test_merge(t) {
        t.plan(4);
        
        var strategy = new OpenLayers.Strategy.BBOX();
                
        // create map with default projection
        var map = new OpenLayers.Map("map");
        
        // create layer with custom projection
        var layer = new OpenLayers.Layer.Vector(null, {
            isBaseLayer: true,
            strategies: [strategy],
            protocol: new OpenLayers.Protocol(),
            projection: new OpenLayers.Projection("EPSG:900913")
        });
        map.addLayer(layer);
        map.zoomToMaxExtent();
        
        // create some features
        var geometries = [
            new OpenLayers.Geometry.Point(100, 200),
            new OpenLayers.Geometry.Point(1000, 2000)
        ];
        var features = [
            new OpenLayers.Feature.Vector(geometries[0].clone()),
            new OpenLayers.Feature.Vector(geometries[1].clone())
        ];

        // call merge with a mocked up response
        strategy.merge({features: features, success: OpenLayers.Function.True});
        
        // test that feature geometries have been transformed to map projection
        var from = layer.projection;
        var to = map.getProjectionObject();
        t.geom_eq(layer.features[0].geometry, features[0].geometry.transform(from, to), "[different proj] feature 0 geometry transformed");
        t.geom_eq(layer.features[1].geometry, features[1].geometry.transform(from, to), "[different proj] feature 1 geometry transformed");
        
        // same as above but with same map/layer projection
        layer.destroyFeatures();
        layer.projection = map.getProjectionObject();
        
        features = [
            new OpenLayers.Feature.Vector(geometries[0].clone()),
            new OpenLayers.Feature.Vector(geometries[1].clone())
        ];
        
        // call merge again with mocked up response
        strategy.merge({features: features, success: OpenLayers.Function.True});

        // test that feature geometries have not been transformed
        t.geom_eq(layer.features[0].geometry, features[0].geometry, "[same proj] feature 0 geometry not transformed");
        t.geom_eq(layer.features[1].geometry, features[1].geometry, "[same proj] feature 1 geometry not transformed");
        
    }

    // Test fix for Ticket #3142
    function test_layerLoadedAfterBeingAdded(t) {
        t.plan(3);

        var dummy = new OpenLayers.Layer(null, {isBaseLayer: true});

        var strategy = new OpenLayers.Strategy.BBOX({
            ratio: 1 // makes for easier comparison to map bounds
        });
        var layer = new OpenLayers.Layer.Vector(null, {
            protocol: new OpenLayers.Protocol(),
            strategies: [strategy]
        });

        // Make sure to test the case of a vector layer needing to be 
        // reprojected while the map is not yet centered
        var layerReproject = new OpenLayers.Layer.Vector(null, {
            protocol: new OpenLayers.Protocol(),
            strategies: [new OpenLayers.Strategy.BBOX()],
            projection: 'EPSG:900913'
        });

        // Make sure that layers that are not in range don't request data
        var layerOutOfRange = new OpenLayers.Layer.Vector(null, {
            maxResolution: 1,
            protocol: new OpenLayers.Protocol(),
            strategies: [new OpenLayers.Strategy.BBOX()]
        });

        var map = new OpenLayers.Map("map");
        map.addLayer(dummy);
        map.addLayer(layerReproject);
        map.setCenter(new OpenLayers.LonLat(0, 0));
        map.addLayer(layer);
        map.addLayer(layerOutOfRange);
        // test that the strategy bounds were set
        t.ok(map.getExtent().equals(strategy.bounds), "[set center] bounds set to map extent");
        t.eq(layerOutOfRange.strategies[0].bounds, null, "Data not requested if layer is out of range");

        layerOutOfRange.setVisibility(false);
        layerOutOfRange.setVisibility(true);
        t.eq(layerOutOfRange.strategies[0].bounds, null, "Data not requested if layer is out of range when switching visibility");

        map.destroy();
    }

  </script>
</head>
<body>
    <div id="map" style="width: 400px; height: 200px" />
</body>
</html>