diff --git a/css/ol.css b/css/ol.css index cf46a42de2..0813fc01a6 100644 --- a/css/ol.css +++ b/css/ol.css @@ -1,5 +1,6 @@ .ol-viewport { width:100%; height:100%; position:relative; left:0; top:0; } -.ol-renderer-webgl-canvas { width:100%;height:100%; } +.ol-renderer-webgl-canvas { width:100%; height:100%; } + /** * arrow implementation from http://cssarrowplease.com/ for ol-popup @@ -22,7 +23,6 @@ height: 17px; right: 0; } - .ol-popup-top {} .ol-popup-top:after, .ol-popup-top:before { bottom: 100%; @@ -33,21 +33,18 @@ position: absolute; pointer-events: none; } - .ol-popup-top:after { border-bottom-color: #88b7d5; border-width: 30px; left: 50%; margin-left: -30px; } - .ol-popup-top:before { border-bottom-color: #c2e1f5; border-width: 36px; left: 50%; margin-left: -36px; } - .ol-popup-bottom {} .ol-popup-bottom:after, .ol-popup-bottom:before { top: 100%; @@ -58,7 +55,6 @@ position: absolute; pointer-events: none; } - .ol-popup-bottom:after { border-top-color: #88b7d5; border-width: 30px; @@ -81,7 +77,6 @@ position: absolute; pointer-events: none; } - .ol-popup-right:after { border-left-color: #88b7d5; border-width: 30px; @@ -104,7 +99,6 @@ position: absolute; pointer-events: none; } - .ol-popup-left:after { border-right-color: #88b7d5; border-width: 30px; @@ -118,3 +112,44 @@ margin-top: -36px; } +div.ol-control-zoom { + position: absolute; + top: 8px; + left: 8px; + background: rgba(255,255,255,0.4); + border-radius: 4px; + padding: 2px; +} +div.ol-control-zoom a { + display: block; + margin: 1px; + padding: 0; + color: white; + font-size: 18px; + font-family: 'Lucida Grande', Verdana, Geneva, Lucida, Arial, Helvetica, sans-serif; + font-weight: bold; + text-decoration: none; + text-align: center; + height: 22px; + width:22px; + line-height: 19px; + background: #130085; /* fallback for IE - IE6 requires background shorthand*/ + background: rgba(0, 60, 136, 0.5); + filter: alpha(opacity=80); +} +div.ol-control-zoom a:hover { + background: #130085; /* fallback for IE */ + background: rgba(0, 60, 136, 0.7); + filter: alpha(opacity=100); +} +@media only screen and (max-width: 600px) { + div.ol-control-zoom a:hover { + background: rgba(0, 60, 136, 0.5); + } +} +a.ol-control-zoom-in { + border-radius: 4px 4px 0 0; +} +a.ol-control-zoom-out { + border-radius: 0 0 4px 4px; +} \ No newline at end of file diff --git a/demo/map.html b/demo/map.html index bd4fb74fdc..f15365cab5 100644 --- a/demo/map.html +++ b/demo/map.html @@ -18,6 +18,6 @@ layers: [ol.layer.osm()], center: [45, 5], zoom: 10 - }); + }).getEvents().register("click", function() {console.log("mapclick")}) \ No newline at end of file diff --git a/lib/OpenLayers/Control/Zoom.js b/lib/OpenLayers/Control/Zoom.js deleted file mode 100644 index 37ac48ce66..0000000000 --- a/lib/OpenLayers/Control/Zoom.js +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for - * full list of contributors). Published under the 2-clause BSD license. - * See license.txt in the OpenLayers distribution or repository for the - * full text of the license. */ - -/** - * @requires OpenLayers/Control.js - * @requires OpenLayers/Events/buttonclick.js - */ - -/** - * Class: OpenLayers.Control.Zoom - * The Zoom control is a pair of +/- links for zooming in and out. - * - * Inherits from: - * - - */ -OpenLayers.Control.Zoom = OpenLayers.Class(OpenLayers.Control, { - - /** - * APIProperty: zoomInText - * {String} - * Text for zoom-in link. Default is "+". - */ - zoomInText: "+", - - /** - * APIProperty: zoomInId - * {String} - * Instead of having the control create a zoom in link, you can provide - * the identifier for an anchor element already added to the document. - * By default, an element with id "olZoomInLink" will be searched for - * and used if it exists. - */ - zoomInId: "olZoomInLink", - - /** - * APIProperty: zoomOutText - * {String} - * Text for zoom-out link. Default is "-". - */ - zoomOutText: "-", - - /** - * APIProperty: zoomOutId - * {String} - * Instead of having the control create a zoom out link, you can provide - * the identifier for an anchor element already added to the document. - * By default, an element with id "olZoomOutLink" will be searched for - * and used if it exists. - */ - zoomOutId: "olZoomOutLink", - - /** - * Method: draw - * - * Returns: - * {DOMElement} A reference to the DOMElement containing the zoom links. - */ - draw: function() { - var div = OpenLayers.Control.prototype.draw.apply(this), - links = this.getOrCreateLinks(div), - zoomIn = links.zoomIn, - zoomOut = links.zoomOut, - eventsInstance = this.map.events; - - if (zoomOut.parentNode !== div) { - eventsInstance = this.events; - eventsInstance.attachToElement(zoomOut.parentNode); - } - eventsInstance.register("buttonclick", this, this.onZoomClick); - - this.zoomInLink = zoomIn; - this.zoomOutLink = zoomOut; - return div; - }, - - /** - * Method: getOrCreateLinks - * - * Parameters: - * el - {DOMElement} - * - * Return: - * {Object} Object with zoomIn and zoomOut properties referencing links. - */ - getOrCreateLinks: function(el) { - var zoomIn = document.getElementById(this.zoomInId), - zoomOut = document.getElementById(this.zoomOutId); - if (!zoomIn) { - zoomIn = document.createElement("a"); - zoomIn.href = "#zoomIn"; - zoomIn.appendChild(document.createTextNode(this.zoomInText)); - zoomIn.className = "olControlZoomIn"; - el.appendChild(zoomIn); - } - OpenLayers.Element.addClass(zoomIn, "olButton"); - if (!zoomOut) { - zoomOut = document.createElement("a"); - zoomOut.href = "#zoomOut"; - zoomOut.appendChild(document.createTextNode(this.zoomOutText)); - zoomOut.className = "olControlZoomOut"; - el.appendChild(zoomOut); - } - OpenLayers.Element.addClass(zoomOut, "olButton"); - return { - zoomIn: zoomIn, zoomOut: zoomOut - }; - }, - - /** - * Method: onZoomClick - * Called when zoomin/out link is clicked. - */ - onZoomClick: function(evt) { - var button = evt.buttonElement; - if (button === this.zoomInLink) { - this.map.zoomIn(); - } else if (button === this.zoomOutLink) { - this.map.zoomOut(); - } - }, - - /** - * Method: destroy - * Clean up. - */ - destroy: function() { - if (this.map) { - this.map.events.unregister("buttonclick", this, this.onZoomClick); - } - delete this.zoomInLink; - delete this.zoomOutLink; - OpenLayers.Control.prototype.destroy.apply(this); - }, - - CLASS_NAME: "OpenLayers.Control.Zoom" -}); diff --git a/src/api/geom/linestring.js b/src/api/geom/linestring.js index a3c3bc3431..52c89ff022 100644 --- a/src/api/geom/linestring.js +++ b/src/api/geom/linestring.js @@ -132,6 +132,6 @@ ol.geom.LineString.prototype.remove = function(vertices){ this.removeVertex(v); return true; }, this); - + return this; }; diff --git a/src/ol.js b/src/ol.js index 163edd4dcb..0e07878d04 100644 --- a/src/ol.js +++ b/src/ol.js @@ -2,8 +2,8 @@ goog.provide("ol"); goog.require('ol.base'); goog.require('ol.bounds'); -goog.require('ol.control.Control'); goog.require('ol.control.Navigation'); +goog.require('ol.control.Zoom'); goog.require('ol.event.Drag'); goog.require('ol.event.Events'); goog.require("ol.map"); diff --git a/src/ol/Map.js b/src/ol/Map.js index 0f0f8f0cda..6c1b2d7be3 100644 --- a/src/ol/Map.js +++ b/src/ol/Map.js @@ -108,8 +108,6 @@ ol.Map = function() { */ this.container_ = null; - this.setControls(ol.Map.DEFAULT_CONTROLS); - }; /** @@ -136,7 +134,7 @@ ol.Map.DEFAULT_TILE_SIZE = 256; @const @type {Array.} */ -ol.Map.DEFAULT_CONTROLS = ["navigation"]; +ol.Map.DEFAULT_CONTROLS = ["navigation", "zoom"]; /** * @return {ol.Loc} Location. @@ -355,9 +353,19 @@ ol.Map.prototype.setMaxRes = function(res) { * @param {Element} container the container to render the map to */ ol.Map.prototype.setContainer = function(container) { - this.events_.setElement(container); this.container_ = container; this.setViewport(); + this.createRenderer(); + //TODO Controls could be set earlier, but we need to deal with content that + // controls place on overlays. + this.setControls(ol.Map.DEFAULT_CONTROLS); +}; + +/** + * @return {Element} + */ +ol.Map.prototype.getViewport = function() { + return this.viewport_; }; ol.Map.prototype.setViewport = function() { @@ -367,9 +375,21 @@ ol.Map.prototype.setViewport = function() { this.staticOverlay_ = goog.dom.createDom('div', 'ol-overlay-static'); goog.dom.append(this.viewport_, this.mapOverlay_, this.staticOverlay_); } + this.events_.setElement(this.viewport_); goog.dom.appendChild(this.container_, this.viewport_); }; +ol.Map.prototype.createRenderer = function() { + /*var registeredRenderers = ol.renderer.RENDERER_MAP, + candidate; + for (var r in registeredRenderers) { + if (registeredRenderers[r].isSupported()) { + break; + } + } + this.renderer_ = new registeredRenderers[r](this.viewport_);*/ +}; + /** * @return {ol.event.Events} the events instance for this map */ @@ -385,6 +405,14 @@ ol.Map.prototype.moveByPx = function(dx, dy) { // call moveByPx on renderers }; +ol.Map.prototype.zoomIn = function() { + this.setZoom(this.zoom_++); +}; + +ol.Map.prototype.zoomOut = function() { + this.setZoom(this.zoom_--); +}; + /** * @param {ol.geom.Point} loc the location being requested * @returns {Array} the position of the location in pixel space diff --git a/src/ol/TileCache.js b/src/ol/TileCache.js index 08311ae19f..0772adf06b 100644 --- a/src/ol/TileCache.js +++ b/src/ol/TileCache.js @@ -9,13 +9,7 @@ goog.require('goog.structs.LinkedMap'); * @param {number=} opt_size */ ol.TileCache = function(opt_size) { - /** - * @constant - * @type {number} - */ - this.size_ = opt_size || 100; - - goog.base(this, 1, true /* cache mode */); + goog.base(this, opt_size || 100, true /* cache mode */); }; goog.inherits(ol.TileCache, goog.structs.LinkedMap); diff --git a/src/ol/control/Navigation.js b/src/ol/control/Navigation.js index 34edc79335..e87eb7300c 100644 --- a/src/ol/control/Navigation.js +++ b/src/ol/control/Navigation.js @@ -42,10 +42,11 @@ ol.control.Navigation.prototype.deactivate = function() { }; /** - * @param {ol.event.DragEvent} evt + * @param {Object} evt */ ol.control.Navigation.prototype.moveMap = function(evt) { this.getMap().moveByPx(evt.dx, evt.dy); + return false; }; ol.control.addControl('navigation', ol.control.Navigation); \ No newline at end of file diff --git a/src/ol/control/Zoom.js b/src/ol/control/Zoom.js new file mode 100644 index 0000000000..214a255721 --- /dev/null +++ b/src/ol/control/Zoom.js @@ -0,0 +1,103 @@ +goog.provide('ol.control.Zoom'); + +goog.require('ol.control.Control'); +goog.require('goog.dom'); + + +/** + * @constructor + * @extends {ol.control.Control} + * @param {boolean|undefined} opt_autoActivate + */ +ol.control.Zoom = function(opt_autoActivate) { + + goog.base(this, opt_autoActivate); + + /** + * Activate this control when it is added to a map. Default is true. + * + * @type {boolean} autoActivate + */ + this.autoActivate_ = + goog.isDef(opt_autoActivate) ? opt_autoActivate : true; + +}; +goog.inherits(ol.control.Zoom, ol.control.Control); + +/** + * @param {ol.Map} map + */ +ol.control.Zoom.prototype.setMap = function(map) { + goog.base(this, 'setMap', map); + var container = goog.dom.createDom('div', ol.control.Zoom.RES.CLS); + var inButton = goog.dom.createDom( + 'div', ol.control.Zoom.RES.IN_CLS, + goog.dom.createDom('a', {'href': '#zoomIn'}) + ); + goog.dom.setTextContent( + /** @type {Element} */ (inButton.firstChild), + ol.control.Zoom.RES.IN_TEXT + ); + var outButton = goog.dom.createDom( + 'div', ol.control.Zoom.RES.OUT_CLS, + goog.dom.createDom('a', {'href': '#zoomOut'}) + ); + goog.dom.setTextContent( + /** @type {Element} */ (outButton.firstChild), + ol.control.Zoom.RES.OUT_TEXT + ); + goog.dom.append(container, inButton, outButton); + + var viewport = /** @type {Node} */ map.getViewport(); + if (goog.isDefAndNotNull(viewport)) { + goog.dom.append(viewport, container); + } +}; + +/** @inheritDoc */ +ol.control.Zoom.prototype.activate = function() { + var active = goog.base(this, 'activate'); + if (active) { + this.getMap().getEvents().register("click", this.handle, this); + } + return active; +}; + +/** @inheritDoc */ +ol.control.Zoom.prototype.deactivate = function() { + var inactive = goog.base(this, 'deactivate'); + if (inactive) { + this.getMap().getEvents().unregister("click", this.handle, this); + } + return inactive; +}; + +/** + * @param {Event} evt + */ +ol.control.Zoom.prototype.handle = function(evt) { + var target = /** @type {Node} */ (evt.target), + handled = false; + if (goog.dom.getAncestorByClass(target, ol.control.Zoom.RES.IN_CLS)) { + this.getMap().zoomIn(); + handled = true; + } else + if (goog.dom.getAncestorByClass(target, ol.control.Zoom.RES.OUT_CLS)) { + this.getMap().zoomOut(); + handled = true; + } + if (handled) { + evt.preventDefault(); + } + return !handled; +}; + +ol.control.addControl('zoom', ol.control.Zoom); + +ol.control.Zoom.RES = { + CLS: 'ol-control-zoom', + IN_CLS: 'ol-control-zoom-in', + OUT_CLS: 'ol-control-zoom-out', + IN_TEXT: '+', + OUT_TEXT: '\u2013' +}; \ No newline at end of file diff --git a/src/ol/event/Drag.js b/src/ol/event/Drag.js index 82fbab5827..1d806f300c 100644 --- a/src/ol/event/Drag.js +++ b/src/ol/event/Drag.js @@ -1,5 +1,4 @@ goog.provide('ol.event.Drag'); -goog.provide('ol.event.DragEvent'); goog.require('ol.event.ISequence'); goog.require('ol.event.Events'); @@ -52,67 +51,38 @@ ol.event.Drag.prototype.dispatchEvent = function(e) { } else if (e.type === goog.fx.Dragger.EventType.END) { e.type = ol.event.Drag.EventType.DRAGEND; } + e.target = e.browserEvent.target; + e.dx = e.clientX - this.previousX_; + e.dy = e.clientY - this.previousY_; } - this.target_.dispatchEvent(/** @type {Event} */ (e)); + this.target_.triggerEvent(e.type, /** @type {Object} (e.type) */ (e)); return goog.base(this, 'dispatchEvent', e); }; /** @inheritDoc */ ol.event.Drag.prototype.startDrag = function(e) { + goog.base(this, 'startDrag', e); this.previousX_ = e.clientX; this.previousY_ = e.clientY; - goog.base(this, 'startDrag', e); -}; - -/** @inheritDoc */ -ol.event.Drag.prototype.doDrag = function(e, x, y, dragFromScroll) { - e.dx = e.clientX - this.previousX_; - e.dy = e.clientX - this.previousY_; - goog.base(this, 'doDrag', e, x, y, dragFromScroll); }; /** @override */ +ol.event.Drag.prototype.doDrag = function(e, x, y, dragFromScroll) { + goog.base(this, 'doDrag', e, x, y, dragFromScroll); + this.previousX_ = e.clientX; + this.previousY_ = e.clientY; +}; + +/** @inheritDoc */ ol.event.Drag.prototype.defaultAction = function(x, y) {}; /** @inheritDoc */ ol.event.Drag.prototype.destroy = ol.event.Drag.prototype.dispose; + ol.event.addSequenceProvider('drag', ol.event.Drag); -/** - * Object representing a drag event - * - * @param {string} type Event type. - * @param {goog.fx.Dragger} dragobj Drag object initiating event. - * @param {number} clientX X-coordinate relative to the viewport. - * @param {number} clientY Y-coordinate relative to the viewport. - * @param {goog.events.BrowserEvent} browserEvent Object representing the - * browser event that caused this drag event. - * @constructor - * @extends {goog.fx.DragEvent} - */ -ol.event.DragEvent = function(type, dragobj, clientX, clientY, browserEvent) { - - goog.base(this, type, dragobj, clientX, clientY, browserEvent); - - /** - * The move delta in X direction since the previous drag event - * - * @type {number} - */ - this.dx = 0; - - /** - * The move delta in Y direction since the previous drag event - * - * @type {number} - */ - this.dy = 0; -}; -goog.inherits(ol.event.DragEvent, goog.fx.DragEvent); - - /** * @type {Object.} */ diff --git a/src/ol/event/Events.js b/src/ol/event/Events.js index ca65cf4438..666ed0c60f 100644 --- a/src/ol/event/Events.js +++ b/src/ol/event/Events.js @@ -136,7 +136,7 @@ ol.event.Events.prototype.setElement = function(element) { for (t in types) { // register the event cross-browser goog.events.unlisten( - this.element_, types[t], this.dispatchEvent, true, this + this.element_, types[t], this.handleBrowserEvent, true, this ); } this.destroySequences(); @@ -148,7 +148,7 @@ ol.event.Events.prototype.setElement = function(element) { for (t in types) { // register the event cross-browser goog.events.listen( - element, types[t], this.dispatchEvent, true, this + element, types[t], this.handleBrowserEvent, true, this ); } } @@ -243,15 +243,14 @@ ol.event.Events.prototype.triggerEvent = function(type, opt_evt) { }; /** - * Basically just a wrapper to the parent's dispatchEvent() function, but takes - * care to set a property 'xy' on the event with the current mouse position and - * normalize clientX and clientY for multi-touch events. + * Prepares browser events before they are dispatched. This takes care to set a + * property 'xy' on the event with the current pointer position (if + * {@code includeXY} is set to true), and normalizes clientX and clientY for + * multi-touch events. * * @param {Event} evt Event object. - * @return {boolean} If anyone called preventDefault on the event object (or - * if any of the handlers returns false this will also return false. */ -ol.event.Events.prototype.dispatchEvent = function(evt) { +ol.event.Events.prototype.handleBrowserEvent = function(evt) { var type = evt.type, listeners = goog.events.getListeners(this.element_, type, false) .concat(goog.events.getListeners(this.element_, type, true)); @@ -276,7 +275,7 @@ ol.event.Events.prototype.dispatchEvent = function(evt) { evt.xy = goog.style.getRelativePosition(evt, this.element_); } } - return goog.base(this, 'dispatchEvent', evt); + this.triggerEvent(evt.type, evt); }; /** diff --git a/src/ol/event/ISequence.js b/src/ol/event/ISequence.js index 83f6103cfc..0b4cb60c83 100644 --- a/src/ol/event/ISequence.js +++ b/src/ol/event/ISequence.js @@ -4,10 +4,10 @@ goog.provide('ol.event.ISequence'); * Interface for event sequences. Event sequences map sequences of native * browser events to high level events that the sequence provides. * - * Implementations are expected to call dispatchEvent on the {@code target} to - * to fire their high level events. + * Implementations are expected to call {@code triggerEvent} on the + * {@code target} to to fire their high level events. * - * Implementations can expect the {@code target}'s {@code getElement()} method + * Implementations can expect the {@code target}'s {@code getElement} method * to return an {Element} at construction time. * * @interface diff --git a/test/spec/api/geom/linestring.test.js b/test/spec/api/geom/linestring.test.js index f0adcbc622..2b401de42b 100644 --- a/test/spec/api/geom/linestring.test.js +++ b/test/spec/api/geom/linestring.test.js @@ -194,10 +194,9 @@ describe("ol.geom.linestring", function() { }); }); - describe("the method 'remove'", function() { it("exists", function(){ - expect( ls.add ).toBeA( Function ); + expect( ls.remove ).toBeA( Function ); }); it("works with a single point", function(){ @@ -217,6 +216,26 @@ describe("ol.geom.linestring", function() { expect(ls.vertices().length).toBe(0); }); }); + + describe("the centroid method is functional", function(){ + it("returns an instance of ol.geom.Point", function(){ + expect(ls.centroid()).toBeA(ol.geom.Point); + }); + + it("has the expected coordinates", function(){ + + ls = ol.geom.linestring([ + ol.geom.point([0.5, 1]), + ol.geom.point([1, 1.5]), + ol.geom.point([1.5, 1]), + ol.geom.point([1, 0.5]) + ]); + + var c = ls.centroid(); + + expect(c.x() + ',' + c.y()).toBe('1,1'); + }); + }); }); diff --git a/test/spec/ol/Events.test.js b/test/spec/ol/Events.test.js index eda6930b4e..1275168503 100644 --- a/test/spec/ol/Events.test.js +++ b/test/spec/ol/Events.test.js @@ -71,6 +71,7 @@ describe("ol.event.Events", function() { events.triggerEvent("bar", evt); expect(log[0].scope).toBe(scope); expect(log[0].evt).toBe(evt); + expect(log[0].evt.object).toBe("foo"); }); it("respects event priority", function() { diff --git a/test/spec/ol/TileCache.test.js b/test/spec/ol/TileCache.test.js index a3a8a3140d..bcb80bd52a 100644 --- a/test/spec/ol/TileCache.test.js +++ b/test/spec/ol/TileCache.test.js @@ -1,5 +1,23 @@ describe('ol.TileCache', function() { + describe('add tiles to cache', function() { + var Tile, tilecache; + + beforeEach(function() { + Tile = ol.Tile.createConstructor(200, 200); + tilecache = new ol.TileCache(5); + }); + + it('does add tiles, without exceeding cache size', function() { + for (var i=0; i<6; i++) { + var url = 'url' + i; + var tile = new Tile(url); + tilecache.set(url, tile); + } + expect(tilecache.getCount()).toEqual(5); + }); + }); + describe('exceed the cache capacity', function() { var Tile, tilecache, tile; diff --git a/test/spec/ol/geom/LineString.test.js b/test/spec/ol/geom/LineString.test.js index 4160958b71..5ddf06f43f 100644 --- a/test/spec/ol/geom/LineString.test.js +++ b/test/spec/ol/geom/LineString.test.js @@ -109,4 +109,23 @@ describe("ol.geom.LineString", function() { expect( vertices[1].getX() + ',' + vertices[1].getY()).toBe( '10,20' ); expect( vertices[2].getX() + ',' + vertices[2].getY()).toBe( '30,40' ); }); + + describe("the getCentroid method is functional", function(){ + it("returns an instance of ol.geom.Point", function(){ + expect(ls.getCentroid()).toBeA(ol.geom.Point); + }); + + it("has the expected coordinates", function(){ + + ls.setVertices([ + new ol.geom.Point(0.5, 1), + new ol.geom.Point(1, 1.5), + new ol.geom.Point(1.5, 1), + new ol.geom.Point(1, 0.5) + ]); + var c = ls.getCentroid(); + + expect(c.getX() + ',' + c.getY()).toBe('1,1'); + }); + }); });