<commit_before>iD.modes.Select = function (entity) {
    var mode = {
        id: 'select',
        button: 'browse',
        entity: entity
    };

    var inspector = iD.ui.inspector(),
        behaviors;

    function remove() {
        if (entity.type === 'way') {
            mode.history.perform(
                iD.actions.DeleteWay(entity.id),
                'deleted a way');
        } else if (entity.type === 'node') {
            var parents = mode.history.graph().parentWays(entity),
                operations = [iD.actions.DeleteNode(entity.id)];
            parents.forEach(function(parent) {
                if (_.uniq(parent.nodes).length === 1) operations.push(iD.actions.DeleteWay(parent.id));
            });
            mode.history.perform.apply(mode.history,
                operations.concat(['deleted a node']));
        }

        mode.controller.exit();
    }

    mode.enter = function () {
        var surface = mode.map.surface;

        behaviors = [
            iD.behavior.Hover(),
            iD.behavior.DragNode(mode),
            iD.behavior.DragWay(mode),
            iD.behavior.DragMidpoint(mode)];

        behaviors.forEach(function(behavior) {
            behavior(surface);
        });

        d3.select('.inspector-wrap')
            .style('display', 'block')
            .style('opacity', 1)
            .datum(entity)
            .call(inspector);

        // Pan the map if the clicked feature intersects with the position
        // of the inspector
        var inspector_size = d3.select('.inspector-wrap').size(),
            map_size = mode.map.size(),
            entity_extent = entity.extent(mode.history.graph()),
            left_edge = map_size[0] - inspector_size[0],
            left = mode.map.projection(entity_extent[1])[0],
            right = mode.map.projection(entity_extent[0])[0];

        if (left > left_edge &&
            right > left_edge) mode.map.centerEase(
                mode.map.projection.invert([(window.innerWidth), d3.event.y]));

        inspector.on('changeTags', function(d, tags) {
            mode.history.perform(
                iD.actions.ChangeEntityTags(d.id, tags),
                'changed tags');

        }).on('changeWayDirection', function(d) {
            mode.history.perform(
                iD.actions.ReverseWay(d.id),
                'reversed a way');

        }).on('splitWay', function(d) {
            mode.history.perform(
                iD.actions.SplitWay(d.id),
                'split a way on a node');

        }).on('remove', function() {
            remove();

        }).on('close', function() {
            mode.controller.exit();
        });

        // Exit mode if selected entity gets undone
        mode.history.on('change.entity-undone', function() {
            if (!mode.history.graph().entity(entity.id)) {
                mode.controller.enter(iD.modes.Browse());
            }
        });

        function click() {
            var datum = d3.select(d3.event.target).datum();
            if (datum instanceof iD.Entity) {
                mode.controller.enter(iD.modes.Select(datum));
            } else {
                mode.controller.enter(iD.modes.Browse());
            }
        }

        function dblclick() {
            var datum = d3.select(d3.event.target).datum();
            if (datum instanceof iD.Entity &&
                (datum.geometry() === 'area' || datum.geometry() === 'line')) {
                var choice = iD.util.geo.chooseIndex(datum,
                        d3.mouse(mode.map.surface.node()), mode.map),
                    node = iD.Node({ loc: choice.loc });

                mode.history.perform(
                    iD.actions.AddNode(node),
                    iD.actions.AddWayNode(datum.id, node.id, choice.index),
                    'added a point to a road');

                d3.event.preventDefault();
                d3.event.stopPropagation();
            }
        }

        surface.on('click.select', click)
            .on('dblclick.browse', dblclick);

        mode.map.keybinding().on('⌫.select', function(e) {
            remove();
            e.preventDefault();
        });

        surface.selectAll("*")
            .filter(function (d) { return d === entity; })
            .classed('selected', true);
    };

    mode.exit = function () {
        var surface = mode.map.surface;

        d3.select('.inspector-wrap')
            .style('display', 'none')
            .html('');

        behaviors.forEach(function(behavior) {
            behavior.off(surface);
        });

        surface.on("click.select", null);
        mode.map.keybinding().on('⌫.select', null);
        mode.history.on('change.entity-undone', null);
<commit_msg>Autosave tags when closing inspector<commit_after>iD.modes.Select = function (entity) {
    var mode = {
        id: 'select',
        button: 'browse',
        entity: entity
    };

    var inspector = iD.ui.inspector(),
        behaviors;

    function remove() {
        if (entity.type === 'way') {
            mode.history.perform(
                iD.actions.DeleteWay(entity.id),
                'deleted a way');
        } else if (entity.type === 'node') {
            var parents = mode.history.graph().parentWays(entity),
                operations = [iD.actions.DeleteNode(entity.id)];
            parents.forEach(function(parent) {
                if (_.uniq(parent.nodes).length === 1) operations.push(iD.actions.DeleteWay(parent.id));
            });
            mode.history.perform.apply(mode.history,
                operations.concat(['deleted a node']));
        }

        mode.controller.exit();
    }

    function changeTags(d, tags) {
        if (!_.isEqual(entity.tags, tags)) {
            mode.history.perform(
                iD.actions.ChangeEntityTags(d.id, tags),
                'changed tags');
        }
    }

    mode.enter = function () {
        var surface = mode.map.surface;

        behaviors = [
            iD.behavior.Hover(),
            iD.behavior.DragNode(mode),
            iD.behavior.DragWay(mode),
            iD.behavior.DragMidpoint(mode)];

        behaviors.forEach(function(behavior) {
            behavior(surface);
        });

        d3.select('.inspector-wrap')
            .style('display', 'block')
            .style('opacity', 1)
            .datum(entity)
            .call(inspector);

        // Pan the map if the clicked feature intersects with the position
        // of the inspector
        var inspector_size = d3.select('.inspector-wrap').size(),
            map_size = mode.map.size(),
            entity_extent = entity.extent(mode.history.graph()),
            left_edge = map_size[0] - inspector_size[0],
            left = mode.map.projection(entity_extent[1])[0],
            right = mode.map.projection(entity_extent[0])[0];

        if (left > left_edge &&
            right > left_edge) mode.map.centerEase(
                mode.map.projection.invert([(window.innerWidth), d3.event.y]));

        inspector
            .on('changeTags', changeTags)
            .on('changeWayDirection', function(d) {
            mode.history.perform(
                iD.actions.ReverseWay(d.id),
                'reversed a way');

        }).on('splitWay', function(d) {
            mode.history.perform(
                iD.actions.SplitWay(d.id),
                'split a way on a node');

        }).on('remove', function() {
            remove();

        }).on('close', function() {
            mode.controller.exit();
        });

        // Exit mode if selected entity gets undone
        mode.history.on('change.entity-undone', function() {
            entity = mode.history.graph().entity(entity.id);
            if (!entity) {
                mode.controller.enter(iD.modes.Browse());
            } else {
                d3.select('.inspector-wrap').datum(entity).call(inspector);
            }
        });

        function click() {
            var datum = d3.select(d3.event.target).datum();
            if (datum instanceof iD.Entity) {
                mode.controller.enter(iD.modes.Select(datum));
            } else {
                mode.controller.enter(iD.modes.Browse());
            }
        }

        function dblclick() {
            var datum = d3.select(d3.event.target).datum();
            if (datum instanceof iD.Entity &&
                (datum.geometry() === 'area' || datum.geometry() === 'line')) {
                var choice = iD.util.geo.chooseIndex(datum,
                        d3.mouse(mode.map.surface.node()), mode.map),
                    node = iD.Node({ loc: choice.loc });

                mode.history.perform(
                    iD.actions.AddNode(node),
                    iD.actions.AddWayNode(datum.id, node.id, choice.index),
                    'added a point to a road');

                d3.event.preventDefault();
                d3.event.stopPropagation();
            }
        }

        surface.on('click.select', click)
            .on('dblclick.browse', dblclick);

        mode.map.keybinding().on('⌫.select', function(e) {
            remove();
            e.preventDefault();
        });

        surface.selectAll("*")
            .filter(function (d) { return d === entity; })
            .classed('selected', true);
    };

    mode.exit = function () {
        var surface = mode.map.surface;

        changeTags(entity, inspector.tags());
        d3.select('.inspector-wrap')
            .style('display', 'none')
            .html('');

        behaviors.forEach(function(behavior) {
            behavior.off(surface);
        });

        surface.on("click.select", null);
        mode.map.keybinding().on('⌫.select', null);
        mode.history.on('change.entity-undone', null);

{'fraction_non_alphanumeric': 0.14682377049180328, 'fraction_numerical': 0.003995901639344262, 'mean_word_length': 1.6175918476803433, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5591754', 'n_tokens_mistral': 2888, 'n_tokens_neox': 2726, 'n_words': 460}