3 <script src="../../lib/OpenLayers.js"></script>
4 <script type="text/javascript">
6 function test_initialize(t) {
10 // construct with a single layer
11 var layer = new OpenLayers.Layer.Vector();
12 var control = new OpenLayers.Control.Snapping({
16 t.ok(control.layer === layer, "[a] source layer properly set");
17 t.eq(control.targets.length, 1, "[a] one target layer");
18 t.ok(control.targets[0].layer === layer, "[a] target set");
21 // construct with a different target, default target config
22 var layer2 = new OpenLayers.Layer.Vector();
23 control = new OpenLayers.Control.Snapping({
28 t.eq(control.targets.length, 1, "[b] one target layer");
29 t.ok(control.targets[0].layer == layer2, "[b] target set");
33 function test_setLayer(t) {
37 var layer = new OpenLayers.Layer.Vector();
38 var control = new OpenLayers.Control.Snapping();
39 control.setLayer(layer);
41 t.ok(control.layer === layer, "layer properly set");
43 // confirm that the control is deactivated and reactivated when setting new layer
48 control.activate = function() {
51 control.deactivate = function() {
54 control.active = true;
56 var layer2 = new OpenLayers.Layer.Vector();
57 control.setLayer(layer2);
59 t.eq(log.deactivated, 1, "control deactivated");
60 t.ok(control.layer === layer2, "layer properly reset");
61 t.eq(log.activated, 1, "control reactivated");
66 function test_setTargets(t) {
70 var layer1 = new OpenLayers.Layer.Vector();
71 var layer2 = new OpenLayers.Layer.Vector();
72 var control = new OpenLayers.Control.Snapping();
78 control.addTarget = function(target) {
79 log.addTarget.push(target);
81 control.addTargetLayer = function(target) {
82 log.addTargetLayer.push(target);
85 control.setTargets([layer1, {layer: layer2}]);
87 t.eq(log.addTargetLayer.length, 1, "setTargetLayer called once");
88 t.ok(log.addTargetLayer[0] === layer1, "setTargetLayer called with layer1");
89 t.eq(log.addTarget.length, 1, "setTarget called once");
90 t.ok(log.addTarget[0].layer === layer2, "setTarget called with layer2");
95 function test_addTarget(t) {
98 var layer = new OpenLayers.Layer.Vector();
100 var control = new OpenLayers.Control.Snapping({
108 control.addTarget({layer: layer});
110 t.eq(control.targets.length, 1, "single target");
111 var target = control.targets[0];
112 t.ok(target.layer === layer, "correct target layer");
113 t.eq(target.nodeTolerance, 30, "correct nodeTolerance");
114 t.eq(target.edgeTolerance, 40, "correct edgeTolerance");
115 t.eq(target.vertexTolerance, 40, "correct vertexTolerance");
120 function test_removeTargetLayer(t) {
124 var layer1 = new OpenLayers.Layer.Vector();
125 var layer2 = new OpenLayers.Layer.Vector();
126 var layer3 = new OpenLayers.Layer.Vector();
127 var control = new OpenLayers.Control.Snapping({
128 targets: [layer1, layer2, layer3]
131 control.removeTargetLayer(layer2);
133 t.eq(control.targets.length, 2, "correct targets length");
134 t.ok(control.targets[0].layer === layer1, "layer1 remains");
135 t.ok(control.targets[1].layer === layer3, "layer3 remains");
141 function test_activate(t) {
144 var layer = new OpenLayers.Layer.Vector();
145 var control = new OpenLayers.Control.Snapping({
151 t.eq(layer.events.listeners.sketchmodified.length, 1, "one sketchmodified listener");
152 t.ok(layer.events.listeners.sketchmodified[0].func === control.onSketchModified, "correct sketchmodified listener");
153 t.eq(layer.events.listeners.vertexmodified.length, 1, "one vertexmodified listener");
154 t.ok(layer.events.listeners.vertexmodified[0].func === control.onVertexModified, "correct vertexmodified listener");
159 function test_deactivate(t) {
162 var layer = new OpenLayers.Layer.Vector();
163 var control = new OpenLayers.Control.Snapping({
168 control.deactivate();
170 t.eq(layer.events.listeners.sketchmodified.length, 0, "no sketchmodified listeners");
171 t.eq(layer.events.listeners.vertexmodified.length, 0, "no vertexmodified listeners");
176 function test_snapping(t) {
180 var map = new OpenLayers.Map("map", {
182 maxExtent: new OpenLayers.Bounds(0, 0, 100, 100)
185 var layer1 = new OpenLayers.Layer.Vector(null, {
189 new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT(
190 "LINESTRING(0 0, 10 10, 20 20, 30 30)"
192 new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT(
193 "LINESTRING(11 10, 20 10, 30 10)"
197 var layer2 = new OpenLayers.Layer.Vector();
199 new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT(
200 "LINESTRING(10 10, 20 20, 30 30)"
202 new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT(
203 "LINESTRING(21 10, 20 20, 20 30)"
207 map.addLayers([layer1, layer2]);
208 map.zoomToMaxExtent();
210 var control = new OpenLayers.Control.Snapping({
212 targets: [layer1, layer2],
213 defaults: {tolerance: 4}
216 map.addControl(control);
218 // log beforesnap, snap, and unsnap events
220 function listener(event) {
224 beforesnap: listener,
229 // create a vertex and a convenience method for mocking the drag
230 var vertex = new OpenLayers.Geometry.Point(-100, -100);
231 function drag(x, y) {
232 var px = map.getPixelFromLonLat(new OpenLayers.LonLat(x, y));
233 layer1.events.triggerEvent("vertexmodified", {
234 vertex: vertex, pixel: px
238 // mock up drag far from features
240 t.eq(events.length, 0, "no snapping");
242 // mock up drag near first node of first feature
244 t.eq(events.length, 2, "[a] 2 events triggered");
245 t.eq(events[0].type, "beforesnap", "[a] beforesnap triggered");
246 t.eq(events[0].snapType, "node", "[a] beforesnap triggered for node");
247 t.ok(events[0].point === vertex, "[a] beforesnap triggered with vertex");
248 t.eq(events[0].x, 0, "[a] beforesnap triggered correct x");
249 t.eq(events[0].y, 0, "[a] beforesnap triggered with correct y");
250 t.eq(events[1].type, "snap", "[a] snap triggered");
251 t.eq(events[1].snapType, "node", "[a] snap triggered for node");
252 t.ok(events[1].point === vertex, "[a] snap triggered with point");
253 t.eq(events[1].distance, 1, "[a] snap triggered correct distance");
254 t.ok(events[1].layer === layer1, "[a] snap triggered with correct target layer");
255 t.eq(vertex.x, 0, "[a] vertex x modified");
256 t.eq(vertex.y, 0, "[a] vertex y modified");
259 // mock up drag that unsnaps
261 t.eq(events.length, 1, "[b] 1 event triggered");
262 t.eq(events[0].type, "unsnap", "[b] unsnap triggered");
263 t.ok(events[0].point === vertex, "[b] unsnap triggered with vertex");
264 t.eq(vertex.x, -100, "[b] vertex x unsnapped");
265 t.eq(vertex.y, -50, "[b] vertex y unsnapped");
268 // drag near node of second feature in first layer to demonstrate precedence of node snapping
270 t.eq(events.length, 2, "[c] 2 events triggered");
271 t.eq(events[0].type, "beforesnap", "[c] beforesnap triggered first");
272 t.eq(events[1].type, "snap", "[c] snap triggered second");
273 t.eq(events[1].snapType, "node", "[c] snap to node");
278 // drag near node of second feature in second layer to demonstrate greedy property
279 // with greedy true (default) the best target from the first layer with eligible targets is used
281 t.eq(events.length, 2, "[d] 2 events triggered");
282 t.eq(events[1].type, "snap", "[d] snap triggered second");
283 t.eq(events[1].snapType, "vertex", "[d] snap to vertex");
284 t.ok(events[1].layer === layer1, "[d] snap to vertex in first layer");
285 t.eq(vertex.x, 20, "[d] vertex x modified");
286 t.eq(vertex.y, 10, "[d] vertex y modified");
291 // do the same drag but with greedy false - this will look for best target in all layers
292 control.greedy = false;
294 t.eq(events.length, 2, "[d] 2 events triggered");
295 t.eq(events[1].type, "snap", "[d] snap triggered second");
296 t.eq(events[1].snapType, "node", "[d] snap to node");
297 t.ok(events[1].layer === layer2, "[d] snap to node in second layer");
300 control.greedy = true;
303 // demonstrate snapping on sketchstarted
304 var p = new OpenLayers.Geometry.Point(0, 1);
305 layer1.events.triggerEvent("sketchstarted", {
307 feature: new OpenLayers.Feature.Vector(p)
309 t.eq(events.length, 2, "[sketchstarted] 2 events triggered");
310 t.eq(events[0].type, "beforesnap", "[sketchstarted] beforesnap triggered");
311 t.eq(events[0].snapType, "node", "[sketchstarted] beforesnap triggered for node");
312 t.ok(events[0].point === p, "[sketchstarted] beforesnap triggered with vertex");
313 t.eq(events[0].x, 0, "[sketchstarted] beforesnap triggered correct x");
314 t.eq(events[0].y, 0, "[sketchstarted] beforesnap triggered with correct y");
315 t.eq(events[1].type, "snap", "[sketchstarted] snap triggered");
316 t.eq(events[1].snapType, "node", "[sketchstarted] snap triggered for node");
317 t.ok(events[1].point === p, "[sketchstarted] snap triggered with point");
318 t.eq(events[1].distance, 1, "[sketchstarted] snap triggered correct distance");
319 t.ok(events[1].layer === layer1, "[sketchstarted] snap triggered with correct target layer");
320 t.eq(p.x, 0, "[sketchstarted] vertex x modified");
321 t.eq(p.y, 0, "[sketchstarted] vertex y modified");
332 <div id="map" style="width: 100px; height: 100px;"></div>