javascript - Backbone.undo.js 不跟踪我的第二个跨度并且不保存起始值

标签 javascript jquery html backbone.js

我有一个小应用程序,我想通过单击来编辑跨度。我有两个跨度,但是当我编辑第二个跨度时,第一个跨度会自动更改为与第二个跨度相同的值。我也无法更改为跨度的第一个值,因为单击撤消后的第一个值是 foo

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Backbone.Undo sample</title>
    <style>
        body {
            font-family: sans-serif;
            line-height: 140%;
        }

        #centered {
            position: absolute;
            top: 50%;
            left: 50%;
            margin-left: -180px;
            margin-top: -120px;
        }
    </style>
</head>
<body>
    <ol id="centered">
        <li>
            <span type="text" id="input" value="foo">span1 </span>
            <button id="set">set</button>
        </li>
        <li>
            <span type="text" id="input2" value="foo">span2 </span>
            <button id="Button1">set</button>
        </li>
        <li>
            <button id="undo">undo</button>
            <button id="redo">redo</button>
        </li>
    </ol>
    <script src="jquery-1.9.1.js"></script>
    <script src="underscore.js"></script>
    <script src="backbone.js"></script>
    <script src="../Backbone.Undo.js"></script>
    <script>
        $(function () {
            var model = new Backbone.Model({ "text": "foo" }),
            View = Backbone.View.extend({
                initialize: function () {
                    // If the model's text changes, update the view
                    this.model.on("change:text", function (model, text, options) {
                        if (text != this.$el.text()) {
                            this.$el.text(text);
                        }
                    }, this);
                }
            })
            view = new View({
                model: model,
                el: $("#input")
            })
            // Now: The undo/redo part 
            var undoManager = new Backbone.UndoManager;
            undoManager.register(model);
            undoManager.startTracking();

            $("#undo").on("click", function () {
                undoManager.undo();
            })
            $("#redo").on("click", function () {
                undoManager.redo();
            })
            $("#input").on("click", function () {
                var element = document.getElementById("input");
                element.innerHTML = prompt("#input", element.innerHTML);
                model.set("text", $("#input").text());
            })
            $("#input2").on("click", function () {
                var element = document.getElementById("input2");
                element.innerHTML = prompt("#input2", element.innerHTML);
                model.set("text", $("#input2").text());
            })
        })
    </script>
</body>
</html>

最佳答案

据我所知,您正在使用 1 个模型和 1 个 View ,但您希望它们独立运行。因此,当您单击 span2 时,您仍然设置相同的模型,这就是它们都发生变化的原因。

为此,我将为两个跨度使用单独的模型和单独的 View ,如下所示

var model = new Backbone.Model({
    "text": "span1"
});
var model2 = new Backbone.Model({
    "text": "span2"
});
var View = Backbone.View.extend({
    initialize: function () {
        // If the model's text changes, update the view
        this.model.on("change:text", function (model, text, options) {
            if (text != this.$el.text()) {
                this.$el.text(text);
            }
        }, this);
    }
});
var view1 = new View({
    model: model,
    el: $("#input")
});

var view2 = new View({
    model: model2,
    el: $("#input2")
});

然后在撤消寄存器中注册您的其他模型

// Now: The undo/redo part 
var undoManager = new Backbone.UndoManager;
undoManager.register(model);
undoManager.register(model2);
undoManager.startTracking();

最后更改 span2 上的点击处理程序以编辑新模型

$("#input2").on("click", function () {
    var element = document.getElementById("input2");
    element.innerHTML = prompt("#input2", element.innerHTML);
    model2.set("text", $("#input2").text());
})

here is a fiddle with it all together

您还可以通过让您的 View 处理事件而不是在外部执行此操作来更多地利用主干。这是一个例子

var View = Backbone.View.extend({
    initialize: function () {
        // If the model's text changes, update the view
        this.model.on("change:text", function (model, text, options) {
            if (text != this.$el.text()) {
                this.$el.text(text);
            }
        }, this);
    },

    events: {
        'click': 'editValue'
    },
    editValue: function () {
        var data = prompt("#input2", this.model.get("text"));
        if(data)
        {
            this.model.set("text", data);
        }
    }
    });

现在 View 会处理对模型的更改,我们也不必从 html 中获取数据,我们始终将其保留在模型中。这是一个更新的 fiddle ,展示了这种技术http://fiddle.jshell.net/leighking2/2vx00s4b/9/

<小时/>

一种 More Backboney 方法,为每个模型使用一个模板,一个保存模型的集合,然后一个用于显示集合的 View 和一个用于显示每个模型的 View 。我尝试添加注释来显示不同部分正在做什么,询问您是否需要清除任何内容

Fiddle of this example

HTML

<script type="text/template" id="model-template">
    <span type="text" class="input" value="foo"><%= text %></span>
        <button class="remove">remove</button>
</script>
<div id="centered">
    <ol id="collection-hook"> 
    </ol>
    <button id="undo">undo</button>
    <button id="redo">redo</button>
    <button id="add">add</button>
</div>

JS

var Model = Backbone.Model.extend({
    defaults: {
        text: "Click To Edit Text"
    }
});
var Collection = Backbone.Collection.extend({
    model: Model
});

var ModelView = Backbone.View.extend({
    tagName: "li",
    className: "model",

    //get the template and cache it for future use
    template:_.template($('#model-template').html()),
    initialize: function() {
        // If the model's text changes, update the view
        this.listenTo(this.model, "change:text", this.render, this);
        //if the model is removed from the collection close this view
        this.listenTo(this.model, 'remove', this.close, this);
    },

    //events this view will be listening for
    events: {
        'click span.input': 'editValue',
        'click button.remove': 'removeModel',
    },

    //get the models collection from it's self and tell the collection to remove the model
    removeModel: function() {
        this.model.collection.remove(this.model);
    },

    //ensure model and all events are destroyed and remove this view from the DOM
    close: function() {
        this.model.destroy();
        this.remove();
        this.unbind();
        this.stopListening();
    },

    //render this view with the models data
    render: function() {

        //attach the generated template to this views $el
        this.$el.html(this.template({
            text: this.model.get("text")
        }));

        //return this view so collection view can decided where to place it on the DOM
        return this;
    },

    editValue: function() {
        var data = prompt("Change text", this.model.get("text"));
        if (data) {
            this.model.set("text", data);
        }
    }
});

var CollectionView = Backbone.View.extend({
    el: $("#centered"),
    //store a refrence to where you would like to add your models
    collectinoHook: $("#collection-hook", this.$el),

    initialize: function() {
        this.undoManager = new Backbone.UndoManager;

        this.undoManager.startTracking();

        //when ever a new model is added to the collection call the function
        //to render it
        this.listenTo(this.collection, 'add', this.renderOne, this);

    },

    events: {
        'click #add': 'addModel',
        'click #redo': 'redo',
        'click #undo': 'undo',
    },

    //render the collection items one at a time
    renderOne: function(model) {
        this.undoManager.register(model);
        //create a new view using this model
        var view = new ModelView({
            model: model
        });

        //append the new view to you list
        this.collectinoHook.append(view.render().el);
    },

    //use this to render the view with existing models in the collection
    render: function() {
        //clear the current views that have been rendered not the cleanest method as
        //those views will still exist but this is a quick example
        this.collectinoHook.html('');
        this.collection.each(_.bind(function(model) {
            this.renderOne(model);
        },this));
    },


    undo: function() {
        this.undoManager.undo();
    },
    redo: function() {
        this.undoManager.redo();
    },
    addModel: function() {

        //create a new model and add it to the collection
        var model = new Model();
        this.collection.add(model);
    },

});

var collection = new Collection();
var collectionView = new CollectionView({
    collection: collection
});

关于javascript - Backbone.undo.js 不跟踪我的第二个跨度并且不保存起始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26035525/

相关文章:

javascript - javascript for 循环不是每次都执行的问题

javascript - 我是d3新手,有什么简单的方法吗?

javascript - 小屏幕上的 insertBefore div 和大屏幕上的 insertAfter

php - 将数据发布到表: all data in table shows as 1

html - div标签中的不同背景颜色

javascript - 检查元素是否具有列表/数组中给出的类

javascript - 通过js添加html标签/语义

javascript - 如何从 jquery 调用 Controller ?

javascript - iOS Phonegap 使用手势滑动检测

javascript - 使用 jquery 迭代表格单元格