Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/ericmmartinez/Leaflet int…
Browse files Browse the repository at this point in the history
…o keyboard
  • Loading branch information
mourner committed Jul 27, 2012
2 parents a51c841 + e183237 commit ccd6c29
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 0 deletions.
11 changes: 11 additions & 0 deletions build/deps.js
Expand Up @@ -180,6 +180,17 @@ var deps = {
desc: 'Enables zooming to bounding box by shift-dragging the map.'
},

Focus: {
src: ['map/handler/Map.Focus.js'],
desc: 'Enables map to gain focus.'
},

Keyboard: {
src: ['map/handler/Map.Keyboard.js'],
deps: ['Focus'],
desc: 'Enables keyboard pan/zoom when map is focused.'
},

MarkerDrag: {
src: ['layer/marker/Marker.Drag.js'],
deps: ['Marker'],
Expand Down
3 changes: 3 additions & 0 deletions dist/leaflet.css
Expand Up @@ -340,6 +340,9 @@
.leaflet-container {
background: #ddd;
}
.leaflet-container-nofocus {
outline:0;
}
.leaflet-container a {
color: #0078A8;
}
Expand Down
69 changes: 69 additions & 0 deletions src/map/handler/Map.Focus.js
@@ -0,0 +1,69 @@
/*
* L.Handler.Focus is used internally by L.Map to make the map focusable.
*/

L.Map.mergeOptions({
focus: true
});

L.Map.Focus = L.Handler.extend({
_focused: false,

initialize: function (map) {
this._map = map;
this._container = map._container;

this._makeFocusable();
this._focused = false;
},

addHooks: function () {
var container = this._container;
L.DomEvent
.addListener(container, 'focus', this.onFocus, this)
.addListener(container, 'blur', this.onBlur, this)
.addListener(container, 'click', this.onClick, this);
},

removeHooks: function () {
var container = this._container;
L.DomEvent
.removeListener(container, 'focus', this.onFocus, this)
.removeListener(container, 'blur', this.onBlur, this)
.removeListener(container, 'click', this.onClick, this);
},

onClick: function (e) {
if (!this._focused) {
this._container.focus();
}
},

onFocus: function (e) {
this._focused = true;
this._map.fire('focus');
},

onBlur: function (e) {
this._focused = false;
this._map.fire('blur');
},

_makeFocusable: function () {
var map = this._map, container = this._container;


// While we want the map to be "focusable", we don't want the map to
// appear focused (i.e. no outline etc...)
L.DomUtil.addClass(container, 'leaflet-container-nofocus');

// Allows user to tab to the container.
// -1 => User can focus container by clicks, but not tabs
// 0 => User can focus container by clicks or tabs. Order is based on
// DOM source order.
// N => User can focus container by clicks or tabs. N = tab order.
container.tabIndex = "0";
}
});

L.Map.addInitHook('addHandler', 'focus', L.Map.Focus);
138 changes: 138 additions & 0 deletions src/map/handler/Map.Keyboard.js
@@ -0,0 +1,138 @@
L.Map.mergeOptions({
keyboard: true,
keyboardPanOffset: 50,
keyboardZoomOffset: 1
});

L.Map.Keyboard = L.Handler.extend({
// Cross browser list of e.keyCode values for particular keys.
// This list currently covers:
//
// Mac OSX 10.6.8
// Safari 5.1.1
// Firefox 11
// Chrome 18
//
// Windows 7
// IE 8
// IE 9
// Firefox 4
// Chrome 18
_leftKeys: [37],
_rightKeys: [39],
_downKeys: [40],
_upKeys: [38],

_inKeys: [187, 61, 107],
_outKeys: [189, 109, 0],

panKeys: {},
zoomKeys: {},

initialize: function (map) {
this._map = map;
this._container = map._container;

this._setPanOffset(map.options.keyboardPanOffset);
this._setZoomOffset(map.options.keyboardZoomOffset);
},

addHooks: function () {
this._map.on('focus', this._addHooks, this)
.on('blur', this._removeHooks, this);
},

removeHooks: function () {
this._removeHooks();

this._map.off('focus', this._addHooks, this)
.off('blur', this._addHooks, this);
},

_setPanOffset: function (pan) {
var panKeys = {},
keyCode = null,
i = 0;

if (typeof pan !== 'number') {
pan = L.Map.Keyboard.DEFAULT_PAN;
}

// Left
for (i = 0; i < this._leftKeys.length; i++) {
keyCode = this._leftKeys[i];
panKeys[keyCode] = new L.Point(-1 * pan, 0);
}

// Right
for (i = 0; i < this._rightKeys.length; i++) {
keyCode = this._rightKeys[i];
panKeys[keyCode] = new L.Point(pan, 0);
}

// Down
for (i = 0; i < this._downKeys.length; i++) {
keyCode = this._downKeys[i];
panKeys[keyCode] = new L.Point(0, pan);
}

// Up
for (i = 0; i < this._upKeys.length; i++) {
keyCode = this._upKeys[i];
panKeys[keyCode] = new L.Point(0, -1 * pan);
}

this.panKeys = panKeys;
},

_setZoomOffset: function (zoom) {
var zoomKeys = {},
keyCode = null,
i = 0;

if (typeof zoom !== 'number') {
zoom = L.Map.Keyboard.DEFAULT_ZOOM;
}

// In
for (i = 0; i < this._inKeys.length; i++) {
keyCode = this._inKeys[i];
zoomKeys[keyCode] = zoom;
}

// Out
for (i = 0; i < this._outKeys.length; i++) {
keyCode = this._outKeys[i];
zoomKeys[keyCode] = -1 * zoom;
}

this.zoomKeys = zoomKeys;
},

_addHooks: function () {
L.DomEvent.addListener(document, 'keydown', this._onKeyDown, this);
},

_removeHooks: function () {
L.DomEvent.removeListener(document, 'keydown', this._onKeyDown, this);
},

_onKeyDown: function (e) {
var key = e.keyCode,
map = this._map;

if (this.panKeys.hasOwnProperty(key)) {
map.panBy(this.panKeys[key]);
} else if (this.zoomKeys.hasOwnProperty(key)) {
map.setZoom(map.getZoom() + this.zoomKeys[key]);
} else {
return;
}
L.DomEvent.stop(e);
}
});

L.Map.Keyboard.DEFAULT_PAN = 50; // Pixels
L.Map.Keyboard.DEFAULT_ZOOM = 1; // Zoom levels

L.Map.addInitHook('addHandler', 'keyboard', L.Map.Keyboard);

0 comments on commit ccd6c29

Please sign in to comment.