/*
 * L.Handler.ShiftDragZoom is used to add shift-drag zoom interaction to the map
  * (zoom to a selected bounding box), enabled by default.
 */

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

L.Map.BoxZoom = L.Handler.extend({
	initialize: function (map) {
		this._map = map;
		this._container = map._container;
		this._pane = map._panes.overlayPane;
	},

	addHooks: function () {
		L.DomEvent.on(this._container, 'mousedown', this._onMouseDown, this);
	},

	removeHooks: function () {
		L.DomEvent.off(this._container, 'mousedown', this._onMouseDown);
	},

	_onMouseDown: function (e) {
		if (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }

		L.DomUtil.disableTextSelection();

		this._startLayerPoint = this._map.mouseEventToLayerPoint(e);

		this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._pane);
		L.DomUtil.setPosition(this._box, this._startLayerPoint);

		//TODO refactor: move cursor to styles
		this._container.style.cursor = 'crosshair';

		L.DomEvent
		    .on(document, 'mousemove', this._onMouseMove, this)
		    .on(document, 'mouseup', this._onMouseUp, this)
		    .preventDefault(e);

		this._map.fire("boxzoomstart");
	},

	_onMouseMove: function (e) {
		var startPoint = this._startLayerPoint,
		    box = this._box,

		    layerPoint = this._map.mouseEventToLayerPoint(e),
		    offset = layerPoint.subtract(startPoint),

		    newPos = new L.Point(
		        Math.min(layerPoint.x, startPoint.x),
		        Math.min(layerPoint.y, startPoint.y));

		L.DomUtil.setPosition(box, newPos);

		// TODO refactor: remove hardcoded 4 pixels
		box.style.width  = (Math.max(0, Math.abs(offset.x) - 4)) + 'px';
		box.style.height = (Math.max(0, Math.abs(offset.y) - 4)) + 'px';
	},

	_onMouseUp: function (e) {
		this._pane.removeChild(this._box);
		this._container.style.cursor = '';

		L.DomUtil.enableTextSelection();

		L.DomEvent
		    .off(document, 'mousemove', this._onMouseMove)
		    .off(document, 'mouseup', this._onMouseUp);

		var map = this._map,
		    layerPoint = map.mouseEventToLayerPoint(e);

		if (this._startLayerPoint.equals(layerPoint)) { return; }

		var bounds = new L.LatLngBounds(
		        map.layerPointToLatLng(this._startLayerPoint),
		        map.layerPointToLatLng(layerPoint));

		map.fitBounds(bounds);

		map.fire("boxzoomend", {
			boxZoomBounds: bounds
		});
	}
});

L.Map.addInitHook('addHandler', 'boxZoom', L.Map.BoxZoom);

@@ -1098,24 +1098,78 @@
 seUp, this)%0A
+%09%09    .on(document, 'keydown', this._onKeyDown, this)%0A
 %09%09    .preve
@@ -1178,24 +1178,24 @@
 Default(e);%0A
-
 %0A%09%09this._map
@@ -1775,25 +1775,22 @@
 %0A%09%7D,%0A%0A%09_
-onMouseUp
+finish
 : functi
@@ -1789,25 +1789,24 @@
 : function (
-e
 ) %7B%0A%09%09this._
@@ -2022,16 +2022,117 @@
 MouseUp)
+%0A%09%09    .off(document, 'keydown', this._onKeyDown);%0A%09%7D,%0A%0A%09_onMouseUp: function (e) %7B%0A%0A%09%09this._finish()
 ;%0A%0A%09%09var
@@ -2483,14 +2483,96 @@
 nds%0A
-
 %09%09%7D);%0A
+%09%7D,%0A%0A%09_onKeyDown: function (e) %7B%0A%09%09if (e.keyCode === 27) %7B%0A%09%09%09this._finish();%0A%09%09%7D%0A
 %09%7D%0A%7D

Allow for canceling a boxzoom being drawn pressing Escape key