English 中文(简体)
Knockout, CKEditor & 单页 App
原标题:Knockout, CKEditor & Single Page App

我遇到一个与 KnockoutJS & amp; CKEditor 有关的情况。

基本上,我们的网站有一部分是单页应用程序样式,目前它只涉及两页,但可能会随着时间推移而扩大,目前它只是一个列表页面和列表中项目的管理页面。

管理页面本身需要 某种丰富的文本编辑器, 我们已经与 CKEditor 一起寻找一个全公司解决方案。

因为这两页是单页样式, 显然 CKEditor 无法对管理元素进行注册, 因为它们没有在页面上加载 - 问题非常简单, 需要修正。 因此, 作为样本, 我附加了 CKEditor, 点击事件效果很好。 下一个问题是, 设置的击倒观测结果没有更新, 因为 CKEditor 实际上没有修改它所附加的文本区域, 它创造了所有您实际编辑的 div s/ html 元素 。

我发现了一个跟小MCE一起做这件事的人的例子——,我想我可以为CKEditor改写类似的东西。

目前我已相当接近找到一个可行的解决方案, 我已利用这个技术(我将在底部张贴代码), 开始并更新正确的观测结果, 甚至正确张贴到服务器上- 棒极了 。

目前我遇到的问题是 单页应用程序部分 和重新启用CKEditor。

基本上,您可以从列表中单击来管理然后保存(可追溯到列表页面),然后,当您去另一个管理 CKEditor 时,该 CKEditor 已经初始化,但其中没有任何值,我检查了更新代码(下面),值肯定有正确的值,但是它没有被推到 CKEditor 本身 。

也许是因为对CKEditor的流程/初始化进程缺乏了解, 或者对击杀约束缺乏了解, 或者或许是因为我们为单页应用程序设置的框架有问题- 我不确定。

这是代码:

//Test one for ckeditor
ko.bindingHandlers.ckeditor = {
    init: function (element, valueAccessor, allBindingsAccessor, context) {
        var options = allBindingsAccessor().ckeditorOptions || {};
        var modelValue = valueAccessor();

        $(element).ckeditor();

        var editor = $(element).ckeditorGet();

        //handle edits made in the editor
        editor.on( blur , function (e) {
            var self = this;
            if (ko.isWriteableObservable(self)) {
                self($(e.listenerData).val());
            }
        }, modelValue, element);


        //handle destroying an editor (based on what jQuery plugin does)
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            var existingEditor = CKEDITOR.instances[element.name];
            existingEditor.destroy(true);
        });
    },
    update: function (element, valueAccessor, allBindingsAccessor, context) {
        //handle programmatic updates to the observable
        var value = ko.utils.unwrapObservable(valueAccessor());
        $(element).html(value);
    }
};

所以在 HTML 中, 它是一个相当标准的击倒数据组合: 当视图模式被初始化时, 应用约束的 ckeyitor 。

我用调试器;在代码中看到流, 它看起来像当我装载 它第一次叫进, 然后更新, 当我在第二次去的时候 它击中ko.utis.domNodeDisposal 来处理元素。

我尝试过不破坏它,而CKEditor后来抱怨说,这个名字已经存在。我尝试过不销毁它,检查它是否存在,并初始化它是否不存在,这是第一次起作用,但第二次我们没有CKEditor。

我想,我所缺少的只有一件事 能够让它发挥作用 但我已经用尽了所有的选择

有谁知道这三件事能帮我吗?

外面有没有淘汰专家 能帮我解脱吗?

任何帮助都将非常感谢。

MMD 多边

最佳回答

对于任何感兴趣的人,我分类了它:

所有这一切都是一个基本的执行顺序, 我只是需要设定值 文本区域 html 之前,它被启动。

注意此选项使用 jquery 适配器扩展名执行.cockeditor () 的元素 。

或许还有更好的方法 做模糊的部分。

这一扩展目前也与选项不起作用,但比较起来应该很简单。

ko.bindingHandlers.ckeditor = {
    init: function (element, valueAccessor, allBindingsAccessor, context) {
        var options = allBindingsAccessor().ckeditorOptions || {};
        var modelValue = valueAccessor();
        var value = ko.utils.unwrapObservable(valueAccessor());

        $(element).html(value);
        $(element).ckeditor();

        var editor = $(element).ckeditorGet();

        //handle edits made in the editor

        editor.on( blur , function (e) {
            var self = this;
            if (ko.isWriteableObservable(self)) {
                self($(e.listenerData).val());
            }
        }, modelValue, element);
    }
};
问题回答

我为此工作了好一阵子, 并再次在.on (“ blur”) 方法上遇到了几个问题。 也就是说, 当人们点击内容丰富的文本, 然后输入文本, 然后直接滚转到我格式上的“ 拯救” 按钮时, 观察效果不够快。 有一大堆方法可以处理延误问题, 但我想要一些更正式的东西。 我挖了到 CKEditor 文件, 找到了这个宝石 : http://docs. ckfource.com/ cockeditor_ api/symbols/ CKEDItor. topoint Manager. html " rel=“ noreberr” >pointManger

这是一个内置功能, 处理所有焦点和模糊的事例, 并允许您将真正的模糊事件连接到控制中 。

这里是我的装订手 内容丰富的文字,然后

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

       var txtBoxID = $(element).attr("id");
       var instance = CKEDITOR.instances[txtBoxID];

       var options = allBindingsAccessor().richTextOptions || {};
       options.toolbar_Full = [
            [ Source ,  - ,  Format ,  Font ,  FontSize ,  TextColor ,  BGColor ,  - ,  Bold ,  Italic ,  Underline ,  SpellChecker ],
            [ NumberedList ,  BulletedList ,  - ,  Outdent ,  Indent ,  - ,  Blockquote ,  CreateDiv ,  - ,  JustifyLeft ,  JustifyCenter ,  JustifyRight ,  JustifyBlock ,  - ,  BidiLtr ,  BidiRtl ],
            [ Link ,  Unlink ,  Image ,  Table ]
       ];

       //handle disposal (if KO removes by the template binding)
       ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
          if (CKEDITOR.instances[txtBoxID]) { CKEDITOR.remove(CKEDITOR.instances[txtBoxID]); };
       });

       $(element).ckeditor(options);

       //wire up the blur event to ensure our observable is properly updated
       CKEDITOR.instances[txtBoxID].focusManager.blur = function () {
          var observable = valueAccessor();
          observable($(element).val());
       };
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {

       var val = ko.utils.unwrapObservable(valueAccessor());
       $(element).val(val);

    }
}

1号邮件,如果我做错了什么请通知我

在我的项目中,我提供了视觉反馈,说明是否有未保存的更改,因此需要在 keyup 上更新可观测到的更新。在 点击工具栏按钮时点击 这也符合我使用 valuation update:[后按下键,属性变化,输入] 在我 data-bind 属性中的

此外,对于性能,我使用了 .cockeditor(回召,选项) 的回召方法参数,而不是 .on(eventName, handler)

这是我想出的一个习俗约束:

ko.bindingHandlers.ckeditor = {
    init: function (element, valueAccessor, allBindingsAccessor, context) {
        // get observable
        var modelValue = valueAccessor();;

        $(element).ckeditor(function(textarea) {
            // <span> element that contains the CKEditor markup
            var $ckeContainer = $(this.container.$);
            // <body> element within the iframe (<html> is contentEditable)
            var $editorBody =
                    $ckeContainer.find( iframe ).contents().find( body );
            // sets the initial value
            $editorBody.html( modelValue() );
            // handle edits made in the editor - by typing
            $editorBody.keyup(function() {
                modelValue( $(this).html() );
            });
            // handle edits made in the editor - by clicking in the toolbar
            $ckeContainer.find( table.cke_editor ).click(function() {
                modelValue( $editorBody.html() );
            });
        });


        // when ko disposes of <textarea>, destory the ckeditor instance
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).ckeditorGet().destroy(true);
        });
    },
    update: function (element, valueAccessor, allBindingsAccessor, context) {
        // handle programmatic updates to the observable
        var newValue = ko.utils.unwrapObservable(valueAccessor());
        var $ckeContainer = $(element).ckeditorGet().container;
        if( $ckeContainer ) {
            // <span> element that contains the CKEditor markup
            $ckeContainer = $($ckeContainer.$);
            // <body> element within the iframe (<html> is contentEditable)
            var $editorBody =
                    $ckeContainer.find( iframe ).contents().find( body );
            // if new value != existing value, replace it in the editor
            if( $editorBody.html() != newValue )
                $editorBody.html( newValue );
        }
    }
};

<强>理由说明:

我知道我可能应该使用 .getData () > 和 .setData(html) ,而不是在 > ibrade> lt;table cel="cke_editor" > 中找到 iframe 内容的这种相当骇人的方式。

原因, update: 更新的原因: 条件在:

if( $(element).ckeditorGet().getData() != newValue )
    $(element).ckeditorGet().setData( newValue )

由于 CKEditor 使用的 HTML 格式格式, 最初是真实的。 因此, 通知用户一个肮脏的记录, 尽管它不是。 “ 坚固” 对我来说是特有的 < / 坚固 >, 所以我觉得你应该知道, 以防你想知道原因 。

我使用CKEditor 4 的这种技术来覆盖现有的“ html ” ( 1- way) 装有双向绑定的“ html ” 。 我使用 CKEditor 的内嵌 CKEditor, 其行为可能( 不确定) 不同于完整/ 静态编辑 。 我用“ value” 装订了“ value ”, 并用“ code>innerHTML

ko.bindingHandlers.html = {
     init : function (element, valueAccessor, allBindingsAccessor) {
        var eventsToCatch = ["blur"];
        var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
        var valueUpdateHandler = null;

        if (requestedEventsToCatch) {
            if (typeof requestedEventsToCatch == "string")
                requestedEventsToCatch = [requestedEventsToCatch];

            ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
            eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
        }

        valueUpdateHandler = function () {
            var modelValue = valueAccessor();
            var oldValue = ko.utils.unwrapObservable(modelValue);
            var elementValue = element.innerHTML;
            var valueHasChanged = (oldValue !== elementValue);

            if (valueHasChanged)
                modelValue(elementValue);
        }

        ko.utils.arrayForEach(eventsToCatch, function (eventName) {
            var handler = valueUpdateHandler;

            if (eventName.indexOf("after") == 0) {
                handler = function () {
                    setTimeout(valueUpdateHandler, 0)
                };

                eventName = eventName.substring("after".length);
            }

            ko.utils.registerEventHandler(element, eventName, handler);
        });
    },
     update : function (element, valueAccessor) {
        var newValue = ko.utils.unwrapObservable(valueAccessor());
        var elementValue = element.innerHTML;
        var valueHasChanged = (newValue !== elementValue);

        if (valueHasChanged)
            element.innerHTML = newValue;
    }
};

Calivat: 这也许应该更新, 以便使用 CKEditor S 自己的 change 事件 。

我重写此选项是为了更新每个键盘上的可见效果, 而不是模糊。 这是更多关于可见效果的更新, 但是只要您用按钮保存下来, 目前看来效果很好!

//handle edits made in the editor
CKEDITOR.instances.thread_message.on( contentDom , function() {
  CKEDITOR.instances.thread_message.document.on( keyup , function(e) {

    var self = this;
    if (ko.isWriteableObservable(self)) {
      var ckValue = CKEDITOR.instances.element_id.getData();
      self(ckValue);
      //console.log("value: " + ckValue);
    }
  }, modelValue, element);
});

对于模糊的部分,我尝试了下面的代码 它似乎有效

              editor.on( blur , function (e) {
                var self = this;
                if (ko.isWriteableObservable(self)) {
                    var ckValue = e.editor.getData();
                    self(ckValue);
                }
            }, modelValue, element);

我认为,如果你“更新”从别处观察到的“最新消息”部分(而不是通过编辑,





相关问题
WebForms and ASP.NET MVC co-existence

I am trying to make a WebForms project and ASP.NET MVC per this question. One of the things I ve done to make that happen is that I added a namespaces node to the WebForms web.config: <pages ...

Post back complex object from client side

I m using ASP.NET MVC and Entity Framework. I m going to pass a complex entity to the client side and allow the user to modify it, and post it back to the controller. But I don t know how to do that ...

Create an incremental placeholder in NHaml

What I want to reach is a way to add a script and style placeholder in my master. They will include my initial site.css and jquery.js files. Each haml page or partial can then add their own required ...

asp.net mvc automapper parsing

let s say we have something like this public class Person { public string Name {get; set;} public Country Country {get; set;} } public class PersonViewModel { public Person Person {get; ...

structureMap mocks stub help

I have an BLL that does validation on user input then inserts a parent(PorEO) and then inserts children(PorBoxEO). So there are two calls to the same InsertJCDC. One like this=>InsertJCDC(fakePor)...

ASP.NET MVC: How should it work with subversion?

So, I have an asp.net mvc app that is being worked on by multiple developers in differing capacities. This is our first time working on a mvc app and my first time working with .NET. Our app does not ...

System.Web.Mvc.Controller Initialize

i have the following base controller... public class BaseController : Controller { protected override void Initialize(System.Web.Routing.RequestContext requestContext) { if (...

热门标签