diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc
index d64cd8437a..58341a5152 100644
--- a/src/objectliterals.jsdoc
+++ b/src/objectliterals.jsdoc
@@ -30,6 +30,12 @@
* then it gets set by using `window.devicePixelRatio`.
* @property {ol.Collection|Array.
|undefined} interactions
* Interactions that are initially added to the map.
+ * @property {Element|Document|undefined} keyboardEventTarget The element to listen to keyboard events on.
+ * This determines when the `KeyboardPan` and `KeyboardZoom` interactions trigger. For example, if
+ * this option is set to `document` the keyboard interactions will always trigger. If this option
+ * is not specified, the element the library listens to keyboard events on is the map target (i.e.
+ * the user-provided div for the map). In that case the target element needs to be focused for key
+ * events to be emitted, requiring that the target element has a `tabindex` attribute.
* @property {Array.|ol.Collection|undefined} layers Layers.
* @property {boolean|undefined} ol3Logo Show ol3 logo. Default is `true`.
* @property {ol.Collection|Array.|undefined} overlays
diff --git a/src/ol/map.js b/src/ol/map.js
index e53a1f3477..bb2b89be95 100644
--- a/src/ol/map.js
+++ b/src/ol/map.js
@@ -284,6 +284,12 @@ ol.Map = function(options) {
this.handleMapBrowserEvent, false, this);
this.registerDisposable(mapBrowserEventHandler);
+ /**
+ * @private
+ * @type {Element|Document}
+ */
+ this.keyboardEventTarget_ = optionsInternal.keyboardEventTarget;
+
/**
* @private
* @type {goog.events.KeyHandler}
@@ -876,10 +882,9 @@ ol.Map.prototype.handleTargetChanged_ = function() {
} else {
goog.dom.appendChild(targetElement, this.viewport_);
- // The key handler is attached to the user-provided target. So the key
- // handler will only trigger events when the target element is focused
- // (requiring that the target element has a tabindex attribute).
- this.keyHandler_.attach(targetElement);
+ var keyboardEventTarget = goog.isNull(this.keyboardEventTarget_) ?
+ targetElement : this.keyboardEventTarget_;
+ this.keyHandler_.attach(keyboardEventTarget);
}
this.updateSize();
@@ -1312,6 +1317,7 @@ ol.Map.prototype.withFrozenRendering = function(f, opt_this) {
/**
* @typedef {{controls: ol.Collection,
* interactions: ol.Collection,
+ * keyboardEventTarget: (Element|Document),
* ol3Logo: boolean,
* overlays: ol.Collection,
* rendererConstructor:
@@ -1327,6 +1333,12 @@ ol.MapOptionsInternal;
*/
ol.Map.createOptionsInternal = function(options) {
+ /**
+ * @type {Element|Document}
+ */
+ var keyboardEventTarget = goog.isDef(options.keyboardEventTarget) ?
+ options.keyboardEventTarget : null;
+
/**
* @type {Object.}
*/
@@ -1421,6 +1433,7 @@ ol.Map.createOptionsInternal = function(options) {
return {
controls: controls,
interactions: interactions,
+ keyboardEventTarget: keyboardEventTarget,
ol3Logo: ol3Logo,
overlays: overlays,
rendererConstructor: rendererConstructor,