+ This example creates a "zoom to extent" button.
+ See the custom-controls.js
+ source to see how this is done.
+ Per default, the zoom extent control use the map projection extent.
+
+
+
+ custom, control
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/custom-controls.js b/examples/custom-controls.js
new file mode 100644
index 0000000000..9ddadcc92d
--- /dev/null
+++ b/examples/custom-controls.js
@@ -0,0 +1,109 @@
+goog.require('ol');
+goog.require('ol.Map');
+goog.require('ol.RendererHints');
+goog.require('ol.View2D');
+goog.require('ol.control.Control');
+goog.require('ol.control.defaults');
+goog.require('ol.layer.TileLayer');
+goog.require('ol.source.OSM');
+
+
+/**
+ * Define a namespace for the application.
+ */
+window.app = {};
+var app = window.app;
+
+
+//
+// Define zoom extent control.
+//
+
+
+
+/**
+ * @constructor
+ * @extends {ol.control.Control}
+ * @param {Object=} opt_options Control options.
+ */
+app.ZoomExtentControl = function(opt_options) {
+
+ var options = opt_options || {};
+ this.extent_ = options.extent;
+
+ var anchor = document.createElement('a');
+ anchor.href = '#zoom-to';
+ anchor.className = 'zoom-to';
+
+ var this_ = this;
+ var handleZoomTo = function(e) {
+ this_.handleZoomTo(e);
+ };
+
+ anchor.addEventListener('click', handleZoomTo, false);
+ anchor.addEventListener('touchstart', handleZoomTo, false);
+
+ var element = document.createElement('div');
+ element.className = 'zoom-extent ol-unselectable';
+ element.appendChild(anchor);
+
+ ol.control.Control.call(this, {
+ element: element,
+ map: options.map,
+ target: options.target
+ });
+
+};
+ol.inherits(app.ZoomExtentControl, ol.control.Control);
+
+
+/**
+ * @param {Event} e Browser event.
+ */
+app.ZoomExtentControl.prototype.handleZoomTo = function(e) {
+ // prevent #zoomTo anchor from getting appended to the url
+ e.preventDefault();
+
+ var map = this.getMap();
+ var view = map.getView();
+ view.fitExtent(this.extent_, map.getSize());
+};
+
+
+/**
+ * Overload setMap to use the view projection's validity extent
+ * if no extent was passed to the constructor.
+ * @param {ol.Map} map Map.
+ */
+app.ZoomExtentControl.prototype.setMap = function(map) {
+ ol.control.Control.prototype.setMap.call(this, map);
+ if (map && !this.extent_) {
+ this.extent_ = map.getView().getProjection().getExtent();
+ }
+};
+
+
+//
+// Create map, giving it a zoom extent control.
+//
+
+
+var map = new ol.Map({
+ controls: ol.control.defaults({}, [
+ new app.ZoomExtentControl({
+ extent: [813079.7791264898, 848966.9639063801,
+ 5929220.284081122, 5936863.986909639]
+ })
+ ]),
+ layers: [
+ new ol.layer.TileLayer({
+ source: new ol.source.OSM()
+ })
+ ],
+ renderers: ol.RendererHints.createFromQueryData(),
+ target: 'map',
+ view: new ol.View2D({
+ center: [0, 0],
+ zoom: 2
+ })
+});
diff --git a/externs/oli.js b/externs/oli.js
new file mode 100644
index 0000000000..f6feed46c6
--- /dev/null
+++ b/externs/oli.js
@@ -0,0 +1,28 @@
+/**
+ * @externs
+ */
+
+
+/**
+ * @type {Object}
+ */
+var oli;
+
+
+/**
+ * @interface
+ */
+oli.control.Control = function() {};
+
+
+/**
+ * @param {ol.MapEvent} mapEvent Map event.
+ */
+oli.control.Control.prototype.handleMapPostrender = function(mapEvent) {};
+
+
+/**
+ * @param {ol.Map} map Map.
+ * @return {undefined} Undefined.
+ */
+oli.control.Control.prototype.setMap = function(map) {};
diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc
index acf8dd4fb1..578a7f8b3c 100644
--- a/src/objectliterals.jsdoc
+++ b/src/objectliterals.jsdoc
@@ -123,6 +123,13 @@
* @property {Element|undefined} target Target.
*/
+ /**
+ * @typedef {Object} ol.control.ControlOptions
+ * @property {Element|undefined} element Element.
+ * @property {ol.Map|undefined} map Map.
+ * @property {Element|undefined} target Target.
+ */
+
/**
* @typedef {Object} ol.control.DefaultsOptions
* @property {boolean|undefined} attribution Attribution.
diff --git a/src/ol/control/control.exports b/src/ol/control/control.exports
new file mode 100644
index 0000000000..d44b62ce15
--- /dev/null
+++ b/src/ol/control/control.exports
@@ -0,0 +1,4 @@
+@exportClass ol.control.Control ol.control.ControlOptions
+@exportProperty ol.control.Control.prototype.handleMapPostrender
+@exportProperty ol.control.Control.prototype.getMap
+@exportProperty ol.control.Control.prototype.setMap
diff --git a/src/ol/control/control.js b/src/ol/control/control.js
index 6ae418f8b7..e63ba7671a 100644
--- a/src/ol/control/control.js
+++ b/src/ol/control/control.js
@@ -1,5 +1,4 @@
goog.provide('ol.control.Control');
-goog.provide('ol.control.ControlOptions');
goog.require('goog.Disposable');
goog.require('goog.array');
@@ -8,14 +7,6 @@ goog.require('goog.events');
goog.require('ol.MapEventType');
-/**
- * @typedef {{element: (Element|undefined),
- * map: (ol.Map|undefined),
- * target: (Element|undefined)}}
- */
-ol.control.ControlOptions;
-
-
/**
* A thing which is painted over the map to provide a means for interaction
@@ -23,6 +14,7 @@ ol.control.ControlOptions;
*
* @constructor
* @extends {goog.Disposable}
+ * @implements {oli.control.Control}
* @param {ol.control.ControlOptions} options Control options.
*/
ol.control.Control = function(options) {
@@ -79,16 +71,18 @@ ol.control.Control.prototype.getMap = function() {
/**
+ * Function called on each map render. Executes in a requestAnimationFrame
+ * callback. Can be implemented in sub-classes to re-render the control's
+ * UI.
* @param {ol.MapEvent} mapEvent Map event.
*/
-ol.control.Control.prototype.handleMapPostrender = goog.nullFunction;
+ol.control.Control.prototype.handleMapPostrender = function(mapEvent) {};
/**
- * Removes the control from its current map and attaches it to the new map.
- * Subtypes might also wish set up event handlers to get notified about changes
- * to the map here.
- *
+ * Remove the control from its current map and attach it to the new map.
+ * Subclasses may set up event handlers to get notified about changes to
+ * the map here.
* @param {ol.Map} map Map.
*/
ol.control.Control.prototype.setMap = function(map) {
@@ -104,7 +98,8 @@ ol.control.Control.prototype.setMap = function(map) {
var target = goog.isDef(this.target_) ?
this.target_ : map.getOverlayContainer();
goog.dom.appendChild(target, this.element);
- if (this.handleMapPostrender !== goog.nullFunction) {
+ if (this.handleMapPostrender !==
+ ol.control.Control.prototype.handleMapPostrender) {
this.listenerKeys.push(goog.events.listen(map,
ol.MapEventType.POSTRENDER, this.handleMapPostrender, false, this));
}
diff --git a/src/ol/ol.exports b/src/ol/ol.exports
new file mode 100644
index 0000000000..e6371ba44b
--- /dev/null
+++ b/src/ol/ol.exports
@@ -0,0 +1 @@
+@exportSymbol ol.inherits
diff --git a/src/ol/ol.js b/src/ol/ol.js
new file mode 100644
index 0000000000..d118ba330f
--- /dev/null
+++ b/src/ol/ol.js
@@ -0,0 +1,14 @@
+goog.provide('ol');
+
+
+/**
+ * ol.inherits is an alias to the goog.inherits function. It is exported
+ * for use in non-compiled application code. See ol.exports.
+ *
+ * FIXME: We use a new line to fake the linter. Without the new line the
+ * linter complains with:
+ *
+ * "Missing newline between constructor and goog.inherits"
+ */
+ol.inherits =
+ goog.inherits;