0

I'm having a string that contains many editable region, please consider this string

 var str = "Regular ... are patterns used to match character .... in strings. In ..., regular expressions are also objects."

editable regions are contains ('...'), I want to make that places editable. means i want inject a editable content inside that string. I would like to use knockout for this purpose. I've referred the niemeyer's about content editable using knockout. can anyone suggest me a better way to achieve this. this my code here

         ko.bindingHandlers.editableContent = {
        init: function(element, valueAccessor, allBindingsAccessor) {

            $(element).css({ "background-color": "#ff77ee", "margin-left": "-2px", "letter-spacing": "0.05"});

            ko.utils.registerEventHandler(element, "keyup", function() {
                var modelValue = valueAccessor();
                var elementValue = element.innerHTML;
                if (ko.isWriteableObservable(modelValue)) {
                    modelValue(elementValue);
                }
                else { //handle non-observable one-way binding
                    var allBindings = allBindingsAccessor();
                    if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers'].editableContent) allBindings['_ko_property_writers'].editableContent(elementValue);
                }
            })
        },
        update: function(element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor()) || "";
            element.innerHTML = value;
        }
    };




    ko.bindingHandlers.myBinding = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

            var div = document.createElement("div");
            var fulltext = valueAccessor();

            element.appendChild(div);

            div.innerHTML = fulltext().replace(/\.\.\./g, "<span data-bind = 'editableContent : editedText' contenteditable='true'></span>");

            ko.applyBindings(viewModel,div);


        },

        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        }
    };

    $(document).ready(function () {

        var viewModel = function () {
            var self = this;
            self.fullText = ko.observable('Regular ... are patterns used to match character .... in strings. In ..., regular expressions are also objects.');
            self.editedText = ko.observable('...');

        }

        ko.applyBindings(new viewModel());

    });
4

1 回答 1

2

主要问题是每个 editableContent 绑定都绑定到同一个可观察对象,因此它们相互更新。

这是将文本拆分为多个片段并为每个单独的 contenteditable 添加单独的 observable 的快速尝试。

    ko.bindingHandlers.myBinding = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var div = document.createElement("div"),
                fulltext = valueAccessor(),
                split = fulltext().split(/\.\.\./g),
                span, editable, editableSpan, pieces = [];

            element.appendChild(div);

            //loop through each pieces and add text and editable content
            for (var i = 0, j = split.length; i < j; i++) {
              //create a span for the fixed content
              span = document.createElement("span");
              span.innerHTML = split[i];

              //keep track of each piece, so we can later put them back together to update original
              pieces.push(split[i]);
              div.appendChild(span);

              //add editable content between the pieces, except at the end
              if (i < split.length - 1) {
                editable = ko.observable("...");
                editableSpan = document.createElement("span");
                pieces.push(editable);
                div.appendChild(editableSpan);
                ko.applyBindingsToNode(editableSpan, { editableContent: editable });
              }

            }

            //update the original observable with the current value
            ko.computed({
                read: function() {
                    var result = "";
                    ko.utils.arrayForEach(pieces, function(piece) {
                       result += ko.utils.unwrapObservable(piece); 
                    });

                    valueAccessor()(result);
                },
                disposeWhenNodeIsRemoved: element
            });

            return { controlsDescendantBindings: true };
        }
    };

示例:http: //jsfiddle.net/rniemeyer/8CkLn/

请注意,这会根据编辑处理更新原始 observable,但如果您以其他方式更新原始 observable,则不会处理更新内容可编辑块。

于 2013-05-23T14:23:20.543 回答