From 2fa71057b18da64522624bde88b2d7662e87248a Mon Sep 17 00:00:00 2001 From: ahocevar Date: Wed, 20 Jun 2012 15:26:02 +0200 Subject: [PATCH 1/7] Finalizing tests for ol.Events --- src/ol/event/Events.js | 6 +- test/spec/ol/Events.test.js | 137 ++++++++++++++++++++++++++++++++++-- 2 files changed, 133 insertions(+), 10 deletions(-) diff --git a/src/ol/event/Events.js b/src/ol/event/Events.js index 81d1c13c8d..2761281fd1 100644 --- a/src/ol/event/Events.js +++ b/src/ol/event/Events.js @@ -83,7 +83,7 @@ ol.event.Events.prototype.getObject = function() { * @param {boolean} includeXY */ ol.event.Events.prototype.setIncludeXY = function(includeXY) { - this._includeXY = includeXY; + this.includeXY_ = includeXY; }; /** @@ -215,7 +215,7 @@ ol.event.Events.prototype.un = function(object) { }; /** - * Unregister a listener for an egent + * Unregister a listener for an event * * @param {string} type Name of the event to unregister * @param {Function} listener The callback function. @@ -283,7 +283,7 @@ ol.event.Events.prototype.handleBrowserEvent = function(evt) { evt.clientX = x / num; evt.clientY = y / num; } - if (this.includeXY) { + if (this.includeXY_) { var element = /** @type {!Element} */ this.element_; evt.xy = goog.style.getRelativePosition(evt, element); } diff --git a/test/spec/ol/Events.test.js b/test/spec/ol/Events.test.js index 99ae690a2f..44bac2356f 100644 --- a/test/spec/ol/Events.test.js +++ b/test/spec/ol/Events.test.js @@ -1,31 +1,154 @@ describe("ol.Events", function() { + + var count = 0, log = [], + countFn = function() {count++;}, + logFn = function(e) {log.push({scope: this, evt: e});}; it("constructs instances", function() { var events, element = document.createElement("div"); - events = new ol.event.Events("foo"); + + events = new ol.event.Events("foo"); expect(events.getObject()).toBe("foo"); - expect(events.getElement()).toBe(null); + expect(events.getElement()).toBe(null); events.destroy(); - events = new ol.event.Events("foo", element, true); + + events = new ol.event.Events("foo", element, true); expect(events.getElement()).toBe(element); - expect(events.includeXY_).toBe(true); + expect(events.includeXY_).toBe(true); events.destroy(); }); it("destroys properly", function() { var events = new ol.event.Events("foo"); - events.destroy(); + events.destroy(); expect(events.getObject()).toBe(undefined); }); + it("relays browser events and knows about pointer position", function() { + var element = document.createElement("div"), + events = new ol.event.Events("foo", element); + + //TODO Figure out a good way to deal with fixtures + element.style.position = "absolute"; + element.style.left = "5px"; + element.style.top = "10px"; + document.body.appendChild(element); + // mock dom element so we can trigger events on it + goog.object.extend(element, new goog.events.EventTarget()); + + log = []; + events.register("click", logFn); + element.dispatchEvent("click"); + expect(log.length).toBe(1); + + // detach from the element + events.setElement(); + element.dispatchEvent("click"); + expect(log.length).toBe(1); + + // attach to the element again + events.setElement(element); + events.setIncludeXY(true); + element.dispatchEvent({ + type: "click", + touches: [{clientX: 9, clientY: 22}, {clientX: 11, clientY: 18}] + }); + expect(log.length).toBe(2); + expect(log[1].evt.xy.x).toBe(5); + expect(log[1].evt.xy.y).toBe(10); + expect(log[1].evt.clientX).toBe(10); + expect(log[1].evt.clientY).toBe(20); + + events.destroy(); + document.body.removeChild(element); + }); + + it("calls listeners with a scope and an event object", function() { + var scope = {}, evt = {}, events = new ol.event.Events("foo"); + + log = []; + events.register("bar", logFn, scope); + events.triggerEvent("bar", evt); + expect(log[0].scope).toBe(scope); + expect(log[0].evt).toBe(evt); + }); + it("respects event priority", function() { var log = [], events = new ol.event.Events("foo"); + + // register a normal listener events.register("bar", function() {log.push("normal");}); + // register a priority listener events.register( - "bar", function() {log.push("priority");}, undefined, true); - events.triggerEvent("bar"); + "bar", function() {log.push("priority");}, undefined, true); + events.triggerEvent("bar"); expect(log[0]).toBe("priority"); expect(log[1]).toBe("normal"); + + events.destroy(); + }); + + it("allows to abort the event chain", function() { + var events = new ol.event.Events("foo"); + + count = 0; + // register a listener that aborts the event chain + events.register("bar", function() {count++; return false;}); + // register a listener that just does something + events.register("bar", countFn); + events.triggerEvent("bar"); + expect(count).toBe(1); + + count = 0; + // register a priority listener that just does something + events.register("bar", countFn, undefined, true); + events.triggerEvent("bar"); + expect(count).toBe(2); + + events.destroy(); + }); + + it("allows to unregister events", function() { + var events = new ol.event.Events("foo"); + + count = 0; + events.register("bar", countFn); + events.triggerEvent("bar"); + expect(count).toBe(1); + + events.unregister("bar", countFn); + events.triggerEvent("bar"); + expect(count).toBe(1); + + events.destroy(); + }); + + it("has working on() and un() convenience methods", function() { + var scope = {}, events = new ol.event.Events("foo"); + + count = 0; + log = []; + events.on({ + "bar": countFn, + "baz": logFn, + scope: scope + }); + events.triggerEvent("bar"); + expect(count).toBe(1); + events.triggerEvent("baz"); + expect(log[0].scope).toBe(scope); + + events.un({ + "bar": countFn, + "baz": logFn, + scope: scope + }); + events.triggerEvent("bar"); + events.triggerEvent("baz"); + expect(count).toBe(1); + expect(log.length).toBe(1); + + events.destroy(); }); }); From 80f76a91e1851e5661c9b9418e65518f1a3313ea Mon Sep 17 00:00:00 2001 From: ahocevar Date: Wed, 20 Jun 2012 15:52:08 +0200 Subject: [PATCH 2/7] Always provide a proper event object. --- src/ol/event/Events.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ol/event/Events.js b/src/ol/event/Events.js index 2761281fd1..da65865929 100644 --- a/src/ol/event/Events.js +++ b/src/ol/event/Events.js @@ -242,6 +242,9 @@ ol.event.Events.prototype.triggerEvent = function(type, evt) { var returnValue, listeners = goog.events.getListeners(this, type, true) .concat(goog.events.getListeners(this, type, false)); + if (arguments.length === 1) { + evt = {type: type}; + } for (var i=0, ii=listeners.length; i Date: Wed, 20 Jun 2012 15:52:24 +0200 Subject: [PATCH 3/7] Better cleanup. --- src/ol/event/Events.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ol/event/Events.js b/src/ol/event/Events.js index da65865929..9b1702e466 100644 --- a/src/ol/event/Events.js +++ b/src/ol/event/Events.js @@ -297,6 +297,7 @@ ol.event.Events.prototype.handleBrowserEvent = function(evt) { * Destroy this Events instance. */ ol.event.Events.prototype.destroy = function() { + this.setElement(); for (var p in this) { delete this[p]; } From 66a5a8ad7a4c9fe352cba591379fac9d3efd508a Mon Sep 17 00:00:00 2001 From: ahocevar Date: Wed, 20 Jun 2012 15:53:01 +0200 Subject: [PATCH 4/7] countFn not needed - do everything with logFn. --- test/spec/ol/Events.test.js | 40 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/test/spec/ol/Events.test.js b/test/spec/ol/Events.test.js index 44bac2356f..198dc61109 100644 --- a/test/spec/ol/Events.test.js +++ b/test/spec/ol/Events.test.js @@ -1,7 +1,6 @@ describe("ol.Events", function() { - var count = 0, log = [], - countFn = function() {count++;}, + var log = [], logFn = function(e) {log.push({scope: this, evt: e});}; it("constructs instances", function() { @@ -91,19 +90,19 @@ describe("ol.Events", function() { it("allows to abort the event chain", function() { var events = new ol.event.Events("foo"); - count = 0; + log = []; // register a listener that aborts the event chain - events.register("bar", function() {count++; return false;}); + events.register("bar", function(e) {logFn(e); return false;}); // register a listener that just does something - events.register("bar", countFn); + events.register("bar", logFn); events.triggerEvent("bar"); - expect(count).toBe(1); + expect(log.length).toBe(1); - count = 0; + log = []; // register a priority listener that just does something - events.register("bar", countFn, undefined, true); + events.register("bar", logFn, undefined, true); events.triggerEvent("bar"); - expect(count).toBe(2); + expect(log.length).toBe(2); events.destroy(); }); @@ -111,14 +110,14 @@ describe("ol.Events", function() { it("allows to unregister events", function() { var events = new ol.event.Events("foo"); - count = 0; - events.register("bar", countFn); + log = []; + events.register("bar", logFn); events.triggerEvent("bar"); - expect(count).toBe(1); + expect(log.length).toBe(1); - events.unregister("bar", countFn); + events.unregister("bar", logFn); events.triggerEvent("bar"); - expect(count).toBe(1); + expect(log.length).toBe(1); events.destroy(); }); @@ -126,27 +125,26 @@ describe("ol.Events", function() { it("has working on() and un() convenience methods", function() { var scope = {}, events = new ol.event.Events("foo"); - count = 0; log = []; events.on({ - "bar": countFn, + "bar": logFn, "baz": logFn, scope: scope }); events.triggerEvent("bar"); - expect(count).toBe(1); + expect(log[0].evt.type).toBe("bar"); events.triggerEvent("baz"); - expect(log[0].scope).toBe(scope); + expect(log[1].scope).toBe(scope); + expect(log[1].evt.type).toBe("baz"); events.un({ - "bar": countFn, + "bar": logFn, "baz": logFn, scope: scope }); events.triggerEvent("bar"); events.triggerEvent("baz"); - expect(count).toBe(1); - expect(log.length).toBe(1); + expect(log.length).toBe(2); events.destroy(); }); From f74d265dec1a557f7622b219c4e43953c62bdaf1 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Wed, 20 Jun 2012 16:02:41 +0200 Subject: [PATCH 5/7] Verified isSingleTouch and isMultiTouch functions. --- src/ol/event/Events.js | 8 ++++---- test/spec/ol/Events.test.js | 14 +++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/ol/event/Events.js b/src/ol/event/Events.js index 9b1702e466..981c03b119 100644 --- a/src/ol/event/Events.js +++ b/src/ol/event/Events.js @@ -11,21 +11,21 @@ goog.require('goog.style'); /** * Determine whether event was caused by a single touch * - * @param {Event} evt + * @param {!Event} evt * @return {boolean} */ ol.event.isSingleTouch = function(evt) { - return evt.touches && evt.touches.length == 1; + return !!(evt.touches && evt.touches.length == 1); }; /** * Determine whether event was caused by a multi touch * - * @param {Event} evt + * @param {!Event} evt * @return {boolean} */ ol.event.isMultiTouch = function(evt) { - return evt.touches && evt.touches.length > 1; + return !!(evt.touches && evt.touches.length > 1); }; diff --git a/test/spec/ol/Events.test.js b/test/spec/ol/Events.test.js index 198dc61109..53a7f86e93 100644 --- a/test/spec/ol/Events.test.js +++ b/test/spec/ol/Events.test.js @@ -122,7 +122,7 @@ describe("ol.Events", function() { events.destroy(); }); - it("has working on() and un() convenience methods", function() { + it("has on() and un() convenience methods", function() { var scope = {}, events = new ol.event.Events("foo"); log = []; @@ -149,4 +149,16 @@ describe("ol.Events", function() { events.destroy(); }); + it("provides an isSingleTouch() function", function() { + expect(ol.event.isSingleTouch({touches: [{}, {}]})).toBe(false); + expect(ol.event.isSingleTouch({touches: [{}]})).toBe(true); + expect(ol.event.isSingleTouch({})).toBe(false); + }); + + it("provides an isMultiTouch() function", function() { + expect(ol.event.isMultiTouch({touches: [{}, {}]})).toBe(true); + expect(ol.event.isMultiTouch({touches: [{}]})).toBe(false); + expect(ol.event.isMultiTouch({})).toBe(false); + }); + }); From 5eeb21c12516c5be79ccde56dc19ad691c146c23 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Wed, 20 Jun 2012 16:11:15 +0200 Subject: [PATCH 6/7] Disallow nowhere. --- src/api/loc.js | 19 ++++++++++++++++--- test/spec/api/loc.test.js | 11 ++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/api/loc.js b/src/api/loc.js index 0a8ce222ea..4c36d11535 100644 --- a/src/api/loc.js +++ b/src/api/loc.js @@ -22,11 +22,20 @@ ol.loc = function(opt_arg){ return opt_arg; } - var x = 0; - var y = 0; + /** @type {number|undefined} */ + var x; + + /** @type {number|undefined} */ + var y; + + /** @type {number|undefined} */ var z; + + /** @type {Object|undefined} */ var projection; + var usage = 'ol.loc accepts a coordinate array or an object with x, y, and (optional) z properties'; + if (arguments.length == 1 && goog.isDef(opt_arg)) { if (goog.isArray(opt_arg)) { x = opt_arg[0]; @@ -39,9 +48,13 @@ ol.loc = function(opt_arg){ z = opt_arg['z']; projection = opt_arg['projection']; } else { - throw new Error('ol.loc'); + throw new Error(usage); } } + + if (!goog.isNumber(x) || !goog.isNumber(y)) { + throw new Error(usage); + } if (goog.isDef(projection)) { projection = ol.projection(projection); diff --git a/test/spec/api/loc.test.js b/test/spec/api/loc.test.js index a7bbf71168..0296f15ca4 100644 --- a/test/spec/api/loc.test.js +++ b/test/spec/api/loc.test.js @@ -1,11 +1,12 @@ describe("ol.loc", function() { - it("allows empty construction", function() { - var loc; + it("doesn't allow empty construction", function() { + + expect(function() { + // nowhere + var loc = ol.loc(); + }).toThrow(); - // nowhere - loc = ol.loc(); - expect(loc).toBeA(ol.Loc); }); it("allows construction from an obj config", function() { From 7bf05964b89301296513a330b4e6329c93015303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Wed, 20 Jun 2012 16:17:40 +0200 Subject: [PATCH 7/7] [ol.layer.XYZ] more tiling fixes, and additional tests --- src/ol/layer/XYZ.js | 24 +++++++----- test/spec/ol/layer/XYZ.test.js | 71 ++++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/src/ol/layer/XYZ.js b/src/ol/layer/XYZ.js index d9ff88ef89..fb44ff361c 100644 --- a/src/ol/layer/XYZ.js +++ b/src/ol/layer/XYZ.js @@ -133,19 +133,23 @@ ol.layer.XYZ.prototype.getData = function(bounds, resolution) { gridLeft = tileOriginX + tileWidthGeo * offsetX, gridTop = tileOriginY - tileHeightGeo * offsetY; - var tiles = [], tile, url, i = 0, j; - while (gridTop - (i * tileHeightGeo) > boundsMinY) { - tiles[i] = []; - j = 0; - while (gridLeft + (j * tileWidthGeo) < boundsMaxX) { - url = me.url_.replace('{x}', offsetX + i + '') - .replace('{y}', offsetY + j + '') + var tiles = [], + tile, + url, + x = 0, + y = 0; + while (gridTop - (y * tileHeightGeo) > boundsMinY) { + tiles[y] = []; + while (gridLeft + (x * tileWidthGeo) < boundsMaxX) { + url = me.url_.replace('{x}', offsetX + x + '') + .replace('{y}', offsetY + y + '') .replace('{z}', zoom); tile = new ol.Tile(url); - tiles[i][j] = tile; - j++; + tiles[y][x] = tile; + x++; } - i++; + y++; + x = 0; } return new ol.TileSet(tiles, tileWidth, tileHeight, resolution); diff --git a/test/spec/ol/layer/XYZ.test.js b/test/spec/ol/layer/XYZ.test.js index d8b595fedc..e048486804 100644 --- a/test/spec/ol/layer/XYZ.test.js +++ b/test/spec/ol/layer/XYZ.test.js @@ -51,11 +51,11 @@ describe('ol.layer.XYZ', function() { expect(tile.getImg()).toBeDefined(); tile = tiles[0][1]; - expect(tile.getUrl()).toEqual('/1/0/1'); + expect(tile.getUrl()).toEqual('/1/1/0'); expect(tile.getImg()).toBeDefined(); tile = tiles[1][0]; - expect(tile.getUrl()).toEqual('/1/1/0'); + expect(tile.getUrl()).toEqual('/1/0/1'); expect(tile.getImg()).toBeDefined(); tile = tiles[1][1]; @@ -81,11 +81,11 @@ describe('ol.layer.XYZ', function() { expect(tile.getImg()).toBeDefined(); tile = tiles[0][1]; - expect(tile.getUrl()).toEqual('/1/0/1'); + expect(tile.getUrl()).toEqual('/1/1/0'); expect(tile.getImg()).toBeDefined(); tile = tiles[1][0]; - expect(tile.getUrl()).toEqual('/1/1/0'); + expect(tile.getUrl()).toEqual('/1/0/1'); expect(tile.getImg()).toBeDefined(); tile = tiles[1][1]; @@ -94,5 +94,68 @@ describe('ol.layer.XYZ', function() { }); }); + describe('extent -96,32,-32,96, resolution 0.5', function() { + + it('returns the expected data', function() { + var tileset = layer.getData( + new ol.Bounds(-96, 32, -32, 96), 0.5); + + var tiles = tileset.getTiles(); + expect(tiles.length).toEqual(1); + expect(tiles[0].length).toEqual(1); + + var tile; + + tile = tiles[0][0]; + expect(tile.getUrl()).toEqual('/1/0/0'); + expect(tile.getImg()).toBeDefined(); + }); + }); + + describe('extent -32,32,32,96, resolution 0.5', function() { + + it('returns the expected data', function() { + var tileset = layer.getData( + new ol.Bounds(-32, 32, 32, 96), 0.5); + + var tiles = tileset.getTiles(); + expect(tiles.length).toEqual(1); + expect(tiles[0].length).toEqual(2); + + var tile; + + tile = tiles[0][0]; + expect(tile.getUrl()).toEqual('/1/0/0'); + expect(tile.getImg()).toBeDefined(); + + tile = tiles[0][1]; + expect(tile.getUrl()).toEqual('/1/1/0'); + expect(tile.getImg()).toBeDefined(); + }); + }); + + describe('extent 32,-32,96,32, resolution 0.5', function() { + + it('returns the expected data', function() { + var tileset = layer.getData( + new ol.Bounds(32, -32, 96, 32), 0.5); + + var tiles = tileset.getTiles(); + expect(tiles.length).toEqual(2); + expect(tiles[0].length).toEqual(1); + expect(tiles[1].length).toEqual(1); + + var tile; + + tile = tiles[0][0]; + expect(tile.getUrl()).toEqual('/1/1/0'); + expect(tile.getImg()).toBeDefined(); + + tile = tiles[1][0]; + expect(tile.getUrl()).toEqual('/1/1/1'); + expect(tile.getImg()).toBeDefined(); + }); + }); + }); });