Boxselector is resizable #192

Merged
merged 4 commits into from May 2, 2012
@@ -4,11 +4,17 @@ wax.mm = wax.mm || {};
// Box Selector
// ------------
wax.mm.boxselector = function(map, tilejson, opts) {
- var mouseDownPoint = null,
+ var corner = null,
+ nearCorner = null,
callback = ((typeof opts === 'function') ?
opts :
opts.callback),
boxDiv,
+ style,
+ borderWidth = 0,
+ horizontal = false, // Whether the resize is horizontal
+ vertical = false,
+ edge = 5, // Distance from border sensitive to resizing
addEvent = MM.addEvent,
removeEvent = MM.removeEvent,
box,
@@ -32,42 +38,73 @@ wax.mm.boxselector = function(map, tilejson, opts) {
function mouseDown(e) {
if (!e.shiftKey) return;
- mouseDownPoint = getMousePoint(e);
+ corner = nearCorner = getMousePoint(e);
+ horizontal = vertical = true;
- boxDiv.style.left = mouseDownPoint.x + 'px';
- boxDiv.style.top = mouseDownPoint.y + 'px';
+ style.left = corner.x + 'px';
+ style.top = corner.y + 'px';
+ style.width = style.height = 0;
- addEvent(map.parent, 'mousemove', mouseMove);
- addEvent(map.parent, 'mouseup', mouseUp);
+ addEvent(document, 'mousemove', mouseMove);
+ addEvent(document, 'mouseup', mouseUp);
map.parent.style.cursor = 'crosshair';
return MM.cancelEvent(e);
}
+ // Resize existing box
+ function mouseDownResize(e) {
+ var point = getMousePoint(e),
+ TL = {
+ x: parseInt(boxDiv.offsetLeft),
+ y: parseInt(boxDiv.offsetTop)
+ },
+ BR = {
+ x: TL.x + parseInt(boxDiv.offsetWidth),
+ y: TL.y + parseInt(boxDiv.offsetHeight)
+ };
+
+ // Determine whether resize is horizontal, vertical or both
+ horizontal = point.x - TL.x <= edge || BR.x - point.x <= edge;
+ vertical = point.y - TL.y <= edge || BR.y - point.y <= edge;
+
+ if (vertical || horizontal) {
+ corner = {
+ x: (point.x - TL.x < BR.x - point.x) ? BR.x : TL.x,
+ y: (point.y - TL.y < BR.y - point.y) ? BR.y : TL.y
+ };
+ nearCorner = {
+ x: (point.x - TL.x < BR.x - point.x) ? TL.x : BR.x,
+ y: (point.y - TL.y < BR.y - point.y) ? TL.y : BR.y
+ }
+ addEvent(document, 'mousemove', mouseMove);
+ addEvent(document, 'mouseup', mouseUp);
+ return MM.cancelEvent(e);
+ }
+ }
function mouseMove(e) {
- var point = getMousePoint(e),
- style = boxDiv.style;
+ var point = getMousePoint(e);
style.display = 'block';
- if (point.x < mouseDownPoint.x) {
- style.left = point.x + 'px';
- } else {
- style.left = mouseDownPoint.x + 'px';
+ if (horizontal) {
+ style.left = (point.x < corner.x ? point.x : corner.x) + 'px';
+ style.width = Math.abs(point.x - corner.x) - 2 * borderWidth + 'px';
}
- if (point.y < mouseDownPoint.y) {
- style.top = point.y + 'px';
- } else {
- style.top = mouseDownPoint.y + 'px';
+ if (vertical) {
+ style.top = (point.y < corner.y ? point.y : corner.y) + 'px';
+ style.height = Math.abs(point.y - corner.y) - 2 * borderWidth + 'px';
}
- style.width = Math.abs(point.x - mouseDownPoint.x) + 'px';
- style.height = Math.abs(point.y - mouseDownPoint.y) + 'px';
+ changeCursor(point, map.parent);
return MM.cancelEvent(e);
}
function mouseUp(e) {
var point = getMousePoint(e),
- l1 = map.pointLocation(point),
- l2 = map.pointLocation(mouseDownPoint);
+ l1 = map.pointLocation( new MM.Point(
+ horizontal ? point.x : nearCorner.x,
+ vertical? point.y : nearCorner.y
+ ));
+ l2 = map.pointLocation(corner);
// Format coordinates like mm.map.getExtent().
boxselector.extent([
@@ -79,12 +116,36 @@ wax.mm.boxselector = function(map, tilejson, opts) {
Math.max(l1.lon, l2.lon))
]);
- removeEvent(map.parent, 'mousemove', mouseMove);
- removeEvent(map.parent, 'mouseup', mouseUp);
+ removeEvent(document, 'mousemove', mouseMove);
+ removeEvent(document, 'mouseup', mouseUp);
map.parent.style.cursor = 'auto';
}
+ function mouseMoveCursor(e) {
+ changeCursor(getMousePoint(e), boxDiv);
+ }
+
+ // Set resize cursor if mouse is on edge
+ function changeCursor(point, elem) {
+ var TL = {
+ x: parseInt(boxDiv.offsetLeft),
+ y: parseInt(boxDiv.offsetTop)
+ },
+ BR = {
+ x: TL.x + parseInt(boxDiv.offsetWidth),
+ y: TL.y + parseInt(boxDiv.offsetHeight)
+ };
+ // Build cursor style string
+ var prefix = '';
+ if (point.y - TL.y <= edge) prefix = 'n';
+ else if (BR.y - point.y <= edge) prefix = 's';
+ if (point.x - TL.x <= edge) prefix += 'w';
+ else if (BR.x - point.x <= edge) prefix += 'e';
+ if (prefix != '') prefix += '-resize';
+ elem.style.cursor = prefix;
+ }
+
function drawbox(map, e) {
if (!boxDiv || !box) return;
var br = map.locationPoint(box[1]),
@@ -122,15 +183,21 @@ wax.mm.boxselector = function(map, tilejson, opts) {
boxDiv.id = map.parent.id + '-boxselector-box';
boxDiv.className = 'boxselector-box';
map.parent.appendChild(boxDiv);
+ style = boxDiv.style;
+ borderWidth = parseInt(window.getComputedStyle(boxDiv).borderWidth);
addEvent(map.parent, 'mousedown', mouseDown);
+ addEvent(boxDiv, 'mousedown', mouseDownResize);
+ addEvent(map.parent, 'mousemove', mouseMoveCursor);
map.addCallback('drawn', drawbox);
return this;
};
boxselector.remove = function() {
map.parent.removeChild(boxDiv);
removeEvent(map.parent, 'mousedown', mouseDown);
+ removeEvent(boxDiv, 'mousedown', mouseDownResize);
+ removeEvent(map.parent, 'mousemove', mouseMoveCursor);
map.removeCallback('drawn', drawbox);
};