2013-04-29 4 views
6

CKEditorのインライン編集をKnockout.jsと統合しようとしています。私は正常にCKEditorとknockout.jsをロードすることができます。インラインCKEditorとknockoutjsの統合

私はちょうどko.observable更新プロパティを取得するように見えることはできません。ここで

<script type="text/javascript"> 

    var viewModel = function() { 
     var self = this; 
     self.editorText = ko.observable('ABC'); 
     self.testNewValue = function() { 
      console.log(this.editorText()); 
     }; 
    } 

    ko.applyBindings(new viewModel()); 
</script> 

はhtmlです:

<div id="editable" contenteditable="true" data-bind="html: editorText"> 
</div> 
<div> 
    <input type="button" data-bind="click: testNewValue" value="test" /> 
</div> 

にconsole.log結果は関係なく、常に "ABC" を示していあなたがそれを更新したかどうか。注:また試しましたdata-bind="text: editorText"

+1

です.HTMLバインディングは双方向ではありません(https://github.com/SteveSanderson/knockout/issues/430)。独自の[contenteditableのカスタムバインディング](http://stackoverflow.com/questions/7904522/knockout-content-editable-custom-binding)を作成する必要があります。 – nemesv

+0

それだけです。ありがとうございました! – jmogera

+0

あなたのCSSをインラインにしないFroalaもあります。ノックアウトプラグイン:https:// github。com/froala/knockout-froala –

答えて

11

observableプロパティをCKEditorのインスタンスにリンクするには、カスタムバインディングハンドラを記述する必要があります。

まず、カスタムバインディングhereから開始することができます。投稿の1つにカスタムバインディングが含まれていますが、それはうまくいきません。あなたはチェックする必要があります。私はクレジットはもちろん、私には行っていない、ここではそれを下にコピーされた:

ko.bindingHandlers.ckEditor = { 

    init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
     var txtBoxID = $(element).attr("id"); 
     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); 
    } 
} 

典型的な使用は、HTMLで次のようになります。第二に

<textarea id="txt_viewModelVariableName" 
      data-bind="ckEditor: viewModelVariableName"></textarea> 

、あなたが最初にによって書かれたcustom binding handler for TinyMCEをチェックアウトすることができRyan Niemeyerと他の有能な人たちによって更新されました。たぶんTinyMCEはCKEditorの代わりにあなたのために働くことができますか?

+0

インライン編集に適用されますか? – jmogera

+0

エラー、正直に分かりません。私はまずCKEditor4のウェブサイトにアクセスして "インライン編集"が何を意味するのかを知る必要がありましたが、コードを書くのが最も良い方法です:-) – Jalayn

+3

Steve SandersonはknockoutJsの作成者です、Ryan Niemeyerはちょうど素晴らしい男。 –

2

特定の質問に答えるには、更新が2回トリガーされないように編集の開始位置を把握する必要があります。 Observableがエディタから更新されていないときは、エディタで突然の変更を行わずにオブザーバブルを再更新する必要があります。エディタがオブザーバブルを更新するときと同じアイデアで、オブザーバブルにエディタに再度通知する必要はありません。私はそれらを追跡するためにブール値を使用していました。編集者に依存しないコードは以下の通りです:

var isObservableChange = false; 
var isEditorChange = false; 

editor.change = function() { 
    if(!isObservableChange){ 
     isEditorChange = true; 
     observable(editor.data); 
     isEditorChange = false; 
    } 
}; 

observable.subscribe(function (newValue) { 
    if(!isEditorChange){ 
     isObservableChange = true; 
     editor.data = observable(); 
     isObservableChange = false; 
    } 
}); 

私はCKEditorバージョンでインライン編集を取得するために全力をしようとしていたプロジェクトがありました。私は最終的にあきらめて、同じタイプのコードでTinyMCEを試してみました。次の例では、ノックアウト2.3.0、tinymce 4.0.8、およびjquery 1.10.2を使用しています。 jqueryは、通常の文書IDでアクセスすることで置き換えることができますが、jqueryを高速コード用の松葉杖として使用します。バインディングコードは次のとおりです。

ko.bindingHandlers.wysiwyg = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
     var value = valueAccessor(); 
     var valueUnwrapped = ko.unwrap(value); 
     var allBindings = allBindingsAccessor(); 
     var $element = $(element); 
     $element.attr('id', 'wysiwyg_' + Date.now()); 
     if (ko.isObservable(value)) { 
      var isSubscriberChange = false; 
      var isEditorChange = true; 
      $element.html(value()); 
      var isEditorChange = false; 

      tinymce.init({ 
       selector: '#' + $element.attr('id'), 
       inline: true, 
       plugins: [ 
        "advlist autolink lists link image charmap print preview anchor", 
        "searchreplace visualblocks code fullscreen", 
        "insertdatetime media table contextmenu paste" 
       ], 
       toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image", 
       setup: function (editor) { 
        editor.on('change', function() { 
         if (!isSubscriberChange) { 
          isEditorChange = true; 
          value($element.html()); 
          isEditorChange = false; 
         } 
        }); 
       } 
      }); 
      value.subscribe(function (newValue) { 
       if (!isEditorChange) { 
        isSubscriberChange = true; 
        $element.html(newValue); 
        isSubscriberChange = false; 
       } 
      }); 
     } 
    } 
} 

これを使用するには、divにバインドします。以下のようなので、

<div data-bind="wysiwyg: test"></div> 

作業の例では、私はこれが役に立てば幸いここhttp://jsfiddle.net/dhQk/2xjKc/ を見つけることができます。

EDIT:

のCKEditorバージョンは結局働くように見えます。私はちょうど別のcdnを使用しなければならなかった。そのリンクはhttp://jsfiddle.net/dhQk/CSwr6/

関連する問題