Add iD.behavior.drag

`iD.behavior.drag` is like `d3.behavior.drag`, with the following differences:

* The `origin` function is expected to return an [x, y] tuple rather than an
  {x, y} object.
* The events are `start`, `move`, and `end`.
  (https://github.com/mbostock/d3/issues/563)
* The `start` event is not dispatched until the first cursor movement occurs.
  (https://github.com/mbostock/d3/pull/368)
* The `move` event has a `loc` and `dxdy` [x, y] tuple properties rather
  than `x`, `y`, `dx`, and `dy` properties.
* The `end` event is not dispatched if no movement occurs.
* An `off` function is available that unbinds the drag's internal event handlers.
* Delegation is supported via the `delegate` function.
This commit is contained in:
John Firebaugh
2012-12-21 08:47:29 -08:00
parent 8b889a4e48
commit 2c40de62be
8 changed files with 182 additions and 4 deletions

View File

@@ -30,6 +30,8 @@ all: \
js/id/util.js \
js/id/actions.js \
js/id/actions/*.js \
js/id/behavior.js \
js/id/behavior/*.js \
js/id/modes.js \
js/id/modes/*.js \
js/id/controller/*.js \

View File

@@ -62,6 +62,9 @@
<script src='js/id/actions/reverse_way.js'></script>
<script src='js/id/actions/split_way.js'></script>
<script src='js/id/behavior.js'></script>
<script src='js/id/behavior/drag.js'></script>
<script src='js/id/modes.js'></script>
<script src='js/id/modes/drag_features.js'></script>
<script src='js/id/modes/add_area.js'></script>

1
js/id/behavior.js Normal file
View File

@@ -0,0 +1 @@
iD.behavior = {};

151
js/id/behavior/drag.js Normal file
View File

@@ -0,0 +1,151 @@
/*
`iD.behavior.drag` is like `d3.behavior.drag`, with the following differences:
* The `origin` function is expected to return an [x, y] tuple rather than an
{x, y} object.
* The events are `start`, `move`, and `end`.
(https://github.com/mbostock/d3/issues/563)
* The `start` event is not dispatched until the first cursor movement occurs.
(https://github.com/mbostock/d3/pull/368)
* The `move` event has a `loc` and `dxdy` [x, y] tuple properties rather
than `x`, `y`, `dx`, and `dy` properties.
* The `end` event is not dispatched if no movement occurs.
* An `off` function is available that unbinds the drag's internal event handlers.
* Delegation is supported via the `delegate` function.
*/
iD.behavior.drag = function () {
function d3_eventCancel() {
d3.event.stopPropagation();
d3.event.preventDefault();
}
var event = d3.dispatch("start", "move", "end"),
origin = null,
selector = '';
event.of = function(thiz, argumentz) {
return function(e1) {
try {
var e0 = e1.sourceEvent = d3.event;
e1.target = drag;
d3.event = e1;
event[e1.type].apply(thiz, argumentz);
} finally {
d3.event = e0;
}
};
};
function mousedown() {
var target = this,
event_ = event.of(target, arguments),
eventTarget = d3.event.target,
touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null,
offset,
origin_ = point(),
moved = 0;
var w = d3.select(window)
.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove)
.on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true);
if (origin) {
offset = origin.apply(target, arguments);
offset = [ offset[0] - origin_[0], offset[1] - origin_[1] ];
} else {
offset = [ 0, 0 ];
}
if (touchId == null) d3_eventCancel();
function point() {
var p = target.parentNode;
return touchId != null ? d3.touches(p).filter(function (p) {
return p.identifier === touchId;
})[0] : d3.mouse(p);
}
function dragmove() {
if (!target.parentNode) return dragend();
var p = point(),
dx = p[0] - origin_[0],
dy = p[1] - origin_[1];
if (!moved) {
event_({
type: "start"
});
}
moved |= dx | dy;
origin_ = p;
d3_eventCancel();
event_({
type: "move",
loc: [p[0] + offset[0], p[1] + offset[1]],
dxdy: [dx, dy]
});
}
function dragend() {
if (moved) {
event_({
type: "end"
});
d3_eventCancel();
if (d3.event.target === eventTarget) w.on("click.drag", click, true);
}
w.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", null)
.on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", null);
}
function click() {
d3_eventCancel();
w.on("click.drag", null);
}
}
function drag(selection) {
var matchesSelector = iD.util.prefixDOMProperty('matchesSelector'),
delegate = mousedown;
if (selector) {
delegate = function() {
var root = this,
target = d3.event.target;
for (; target && target !== root; target = target.parentNode) {
if (target[matchesSelector](selector)) {
return mousedown.call(target, target.__data__);
}
}
}
}
selection.on("mousedown.drag" + selector, delegate)
.on("touchstart.drag" + selector, delegate);
}
drag.off = function(selection) {
selection.on("mousedown.drag" + selector, null)
.on("touchstart.drag" + selector, null);
};
drag.delegate = function(_) {
if (!arguments.length) return selector;
selector = _;
return drag;
};
drag.origin = function (_) {
if (!arguments.length) return origin;
origin = _;
return drag;
};
return d3.rebind(drag, event, "on");
};

View File

@@ -2,7 +2,7 @@ iD.Background = function() {
var tile = d3.geo.tile(),
projection,
cache = {},
transformProp = iD.util.prefixProperty('Transform'),
transformProp = iD.util.prefixCSSProperty('Transform'),
source = d3.functor('');
function atZoom(t, distance) {

View File

@@ -20,7 +20,7 @@ iD.Map = function() {
class_fill = iD.Style.styleClasses('stroke'),
class_area = iD.Style.styleClasses('area'),
class_casing = iD.Style.styleClasses('casing'),
transformProp = iD.util.prefixProperty('Transform'),
transformProp = iD.util.prefixCSSProperty('Transform'),
support3d = iD.util.support3d(),
supersurface, surface, defs, tilegroup, r, g, alength;

View File

@@ -56,7 +56,25 @@ iD.util.qsString = function(obj) {
}).join('&');
};
iD.util.prefixProperty = function(property) {
iD.util.prefixDOMProperty = function(property) {
var prefixes = ['webkit', 'ms', 'moz', 'o'],
i = -1,
n = prefixes.length,
s = document.body;
if (property in s)
return property;
property = property.substr(0, 1).toUpperCase() + property.substr(1);
while (++i < n)
if (prefixes[i] + property in s)
return prefixes[i] + property;
return false;
};
iD.util.prefixCSSProperty = function(property) {
var prefixes = ['webkit', 'ms', 'Moz', 'O'],
i = -1,
n = prefixes.length,
@@ -74,7 +92,7 @@ iD.util.prefixProperty = function(property) {
iD.util.support3d = function() {
// test for translate3d support. Based on https://gist.github.com/3794226 by lorenzopolidori and webinista
var transformProp = iD.util.prefixProperty('Transform');
var transformProp = iD.util.prefixCSSProperty('Transform');
var el = document.createElement('div'),
has3d = false;
document.body.insertBefore(el, null);

View File

@@ -61,6 +61,9 @@
<script src='../js/id/actions/remove_way_node.js'></script>
<script src='../js/id/actions/reverse_way.js'></script>
<script src='../js/id/behavior.js'></script>
<script src='../js/id/behavior/drag.js'></script>
<script src='../js/id/modes.js'></script>
<script src='../js/id/modes/add_area.js'></script>
<script src='../js/id/modes/add_point.js'></script>