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/src/ol/event/Events.js b/src/ol/event/Events.js index 81d1c13c8d..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); }; @@ -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. @@ -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 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/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() { diff --git a/test/spec/ol/Events.test.js b/test/spec/ol/Events.test.js index 99ae690a2f..53a7f86e93 100644 --- a/test/spec/ol/Events.test.js +++ b/test/spec/ol/Events.test.js @@ -1,31 +1,164 @@ describe("ol.Events", function() { + + var log = [], + 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"); + + log = []; + // register a listener that aborts the event chain + events.register("bar", function(e) {logFn(e); return false;}); + // register a listener that just does something + events.register("bar", logFn); + events.triggerEvent("bar"); + expect(log.length).toBe(1); + + log = []; + // register a priority listener that just does something + events.register("bar", logFn, undefined, true); + events.triggerEvent("bar"); + expect(log.length).toBe(2); + + events.destroy(); + }); + + it("allows to unregister events", function() { + var events = new ol.event.Events("foo"); + + log = []; + events.register("bar", logFn); + events.triggerEvent("bar"); + expect(log.length).toBe(1); + + events.unregister("bar", logFn); + events.triggerEvent("bar"); + expect(log.length).toBe(1); + + events.destroy(); + }); + + it("has on() and un() convenience methods", function() { + var scope = {}, events = new ol.event.Events("foo"); + + log = []; + events.on({ + "bar": logFn, + "baz": logFn, + scope: scope + }); + events.triggerEvent("bar"); + expect(log[0].evt.type).toBe("bar"); + events.triggerEvent("baz"); + expect(log[1].scope).toBe(scope); + expect(log[1].evt.type).toBe("baz"); + + events.un({ + "bar": logFn, + "baz": logFn, + scope: scope + }); + events.triggerEvent("bar"); + events.triggerEvent("baz"); + expect(log.length).toBe(2); + + 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); }); }); 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(); + }); + }); + }); });