function doMove()

in modules/modes/drag_node.js [185:264]


    function doMove(entity, nudge) {
        nudge = nudge || [0, 0];

        var currPoint = (d3_event && d3_event.point) || context.projection(_lastLoc);
        var currMouse = geoVecSubtract(currPoint, nudge);
        var loc = context.projection.invert(currMouse);

        if (!_nudgeInterval) {   // If not nudging at the edge of the viewport, try to snap..
            // related code
            // - `mode/drag_node.js`     `doMode()`
            // - `behavior/draw.js`      `click()`
            // - `behavior/draw_way.js`  `move()`
            var d = datum();
            var target = d && d.properties && d.properties.entity;
            var targetLoc = target && target.loc;
            var targetNodes = d && d.properties && d.properties.nodes;
            var edge;

            if (targetLoc) {   // snap to node/vertex - a point target with `.loc`
                if (shouldSnapToNode(target)) {
                    loc = targetLoc;
                }

            } else if (targetNodes) {   // snap to way - a line target with `.nodes`
                edge = geoChooseEdge(targetNodes, context.mouse(), context.projection, end.id);
                if (edge) {
                    loc = edge.loc;
                }
            }
        }

        context.replace(
            actionMoveNode(entity.id, loc)
        );

        // Below here: validations
        var isInvalid = false;

        // Check if this connection to `target` could cause relations to break..
        if (target) {
            isInvalid = hasRelationConflict(entity, target, edge, context.graph());
        }

        // Check if this drag causes the geometry to break..
        if (!isInvalid) {
            isInvalid = hasInvalidGeometry(entity, context.graph());
        }


        var nope = context.surface().classed('nope');
        if (isInvalid === 'relation' || isInvalid === 'restriction') {
            if (!nope) {   // about to nope - show hint
                uiFlash()
                    .duration(4000)
                    .text(t('operations.connect.' + isInvalid,
                        { relation: context.presets().item('type/restriction').name() }
                    ))();
            }
        } else {
            if (nope) {   // about to un-nope, remove hint
                uiFlash()
                    .duration(1)
                    .text('')();
            }
        }


        var nopeDisabled = context.surface().classed('nope-disabled');
        if (nopeDisabled) {
            context.surface()
                .classed('nope', false)
                .classed('nope-suppressed', isInvalid);
        } else {
            context.surface()
                .classed('nope', isInvalid)
                .classed('nope-suppressed', false);
        }

        _lastLoc = loc;
    }