iD.behavior.DragNode = function(mode) { var history = mode.history, size = mode.map.size(), nudgeInterval, projection = mode.map.projection; function edge(point) { var pad = [30, 100, 30, 100]; if (point[0] > size[0] - pad[0]) return [-10, 0]; else if (point[0] < pad[2]) return [10, 0]; else if (point[1] > size[1] - pad[1]) return [0, -10]; else if (point[1] < pad[3]) return [0, 10]; return null; } function startNudge(nudge) { if (nudgeInterval) window.clearInterval(nudgeInterval); nudgeInterval = window.setInterval(function() { mode.map.pan(nudge).redraw(); }, 50); } function stopNudge(nudge) { if (nudgeInterval) window.clearInterval(nudgeInterval); nudgeInterval = null; } return iD.behavior.drag() .delegate(".node") .origin(function(entity) { return projection(entity.loc); }) .on('start', function() { history.perform( iD.actions.Noop()); }) .on('move', function(entity) { d3.event.sourceEvent.stopPropagation(); var nudge = edge(d3.event.point); if (nudge) startNudge(nudge); else stopNudge(); history.replace( iD.actions.MoveNode(entity.id, projection.invert(d3.event.point)), 'moved a node'); }) .on('end', function() { stopNudge(); history.replace( iD.actions.Noop(), 'moved a node'); }); };