2017-10-27 5 views
0

CKEditor5では、カスタム要素を実装してモデルを編集用に表示するように変換しようとしました。次に、コンテナ要素(@ ckeditor/ckeditor5-engine/src/view/containerelement)内の編集可能な要素(@ ckeditor/ckeditor5-engine/src/view/editableelement)が親コンテナ要素にフォーカスされ、編集できません。例えばCKEditor5のEditableElementに入力できません

、次のようにそれが実装されている場合:

buildModelConverter().for(editing.modelToView) 
      .fromElement('myElement') 
      .toElement(new ContainerElement('div', {}, [new EditableElement('h4')])); 

実際の編集DOMの結果 'MYELEMENT' とのKeyDown "ABC" を挿入した後。私ものcontentEditable属性を適用するためのウィジェットを使用してみました

<div>​​​​​​​ 
    abc 
    <h4> 
    <br data-cke-filler="true"> 
    </h4> 
</div> 

(私はH4タグに「ABC」のテキストを入力しますが...願っています)。 しかし、h4にテキストを入力できませんでした。

<div class="ck-widget" contenteditable="false">​​​​​​​ 
    <h4 class="ck-editable" contenteditable="true"> 
    <br data-cke-filler="true"> 
    </h4> 
</div> 

このバグはありますか、コンテナ要素を間違えていましたか?

[追加の詳細]

私は、ランキングリストのためのウィジェットプラグインを作成すると仮定しています。

まず、ランキングリストは、複数の項目があるため、<ol>タグと<li>タグで構成されています。 "rankingList"と "rankingListItem"という2つのスキーマを定義して、 というように解決しましたので、入れ子になったモデル要素を使って動的要素を実現しました。

const item1 = new ModelElement('rankingListItem'); 
const item2 = new ModelElement('rankingListItem'); 
const model = new ModelElement('rankingList', {}, [item1, item2]); 
// and insert 

次に、ランキングリストの項目には、リンク、イメージ、タイトル、およびメモがあります。

const {ref, src, title, notes} = data; // how to get data? 
const view = new ContainerElement('a', {ref}, [ 
    new EmptyElement('img', {src}), 
    new EditableElement('h3', {}, new Text(title)), 
    new EditableElement('p', {}, new Text(title)), 
    ]); 
// maybe incorrect ... 

は結論として、私は定義されたDOMを壊さない編集可能なビューを使用したい:

<ol><!-- apply toWidget --> 
    <li> 
    <a href="link[editable]"> 
     <img src="image[editable]"> 
     <h3>title[editable]</h3> 
     <p>notes[editable]</p> 
    </a> 
    </li> 
    ... 
</ol> 

私はビュー要素は以下の通りです期待: したがって、ランキングリストの項目は、次のDOM構造を有しています木。 どうすれば実現できますか?

+1

こんにちは!私があなたに答える前に、あなたが達成したいことについてもっと詳細を教えてください。 'EditableElement'の役割は、イメージフィーチャーのキャプションのように、ネストされた編集可能な要素を作成しています。このためのユースケースは、DOMサブツリーの一部を編集できないようにする(画像機能の画像そのものなど)が、内部には(キャプション)にする必要がある場合です。したがって、2番目のhtmlサンプルは、 'EditableElement'のユースケースに非常に近いものです。 'h4'要素を' div'でラップしたければ、別の 'ContainerElement'だけを使うべきです。私に知らせてください、そして、私はあなたに詳細な答えを教えます。 –

+0

すぐにお返事ありがとうございます。 ご質問部分に詳細を追加しましたので、ご確認ください。 – inoutch

答えて

5

ありがとうございます。開発者がどのようにエディタを使用しているのか、そしてあなたの期待が何であるかを知ることは、現時点では私たちの多くを意味します。

残念ながら、これは非常に複雑な機能のようです。また、カスタムURLを必要とするように見えます(リンクURLと画像srcを編集するには - エディタに追加しても変更されない限り)。モデルとビューの間

  • 位置マッピング、
  • ネストされたeditables:あなたが二つの問題で苦労しているようです。

についてEditableElementあなたの質問に答えるために、まず、 - h3p要素のためにそれらを使用するのが正しいと思われます。

ただし、このような複雑な機能にはカスタムコンバータが必要です。あなたが使用したコンバータビルダーは、要素から要素への変換や属性から属性への変換などの単純なケースで使用されることに専念しています。

nice APIの背後にあるbuild converterは、1つまたは複数の関数を作成する関数ファクトリです。それらはModelConversionDispatcher(これはeditor.editing.modelToViewのインスタンスです)へのコールバックとして追加されます。 ModelConversionDispatcherは、変換中に一連のイベントを発生させます。これは、モデルの変更をビューに変換するプロセスです。

私が言及したように、あなたはそれらの変換機能を自分で書く必要があります。

これは詳細で徹底的な回答のためには大きすぎるテーマですので、興味深い内容を簡単に紹介します。残念ながら、カスタムコンバータの作成についてのガイドはまだありません。これは非常に広いテーマです。

まず、問題のほとんどがどこから来たのかを説明します。すでに知っているように、エディタには、モデル(データ)、ビュー(DOMのような構造)、DOMの3つのレイヤがあります。モデルはビューに変換され、ビューはDOMにレンダリングされます。また、逆に、データをロードすると、DOMはビューに変換され、ビューはモデルに変換されます。これは、あなたのフィーチャーにモデル・ツー・ビュー・コンバーターとビュー・ツー・モデル・コンバーターを提供する必要がある理由です。

このパズルの重要な部分はengine.conversion.Mapperです。その役割は、要素と位置をモデルからビューにマップすることです。既に見たように、モデルはビューとはかなり異なる場合があります。それらの間の正しい位置マッピングが重要です。キャレット位置(DOM内)に文字を入力すると、この位置はモデルにマッピングされ、文字はモデルに挿入され、その後にのみビューとDOMに変換されます。ビューからモデルへの位置変換が間違っていると、その場所で入力することや実際に何かを行うことができなくなります。

Mapperは非常に簡単です。必要なのは、どのビュー要素がどのモデル要素にバインドされているかを指定するだけです。たとえば、モデルにあなたが持っているかもしれません:

<listItem type="bulleted" indent="0">Foo</listItem> 
<listItem type="bulleted" indent="1">Bar</listItem> 

をお持ちのビューでいる間:

<ul> 
    <li> 
    Foo 
    <ul> 
     <li>Bar</li> 
    </ul> 
    </li> 
</ul> 

マッパーが最初listItemが最初<li>で結合され、第二listItemがでバインドされていることを知っている場合2番目の<li>の場合、ポジションを正しく変換できます。

ケースに戻る。各コンバータはMapperのデータを提供する必要があります。あなたがコンバータビルダーを使用して以来、コンバータはすでにこれを行ってビルドしています。しかし、彼らはシンプルなので、あなたが提供する場合:

buildModelConverter().for(editing.modelToView) 
     .fromElement('myElement') 
     .toElement(new ContainerElement('div', {}, [new EditableElement('h4')])); 

myElement<div>にバインドされていることを、想定しています。だから<div>の内側に書かれているものがmyElementに直行し、その後myElementの冒頭でレンダリングされます。

<div> 
    <h4></h4> 
</div> 

あなただけ<h4>xを書いたと仮定すると、その位置は、中myElement0オフセットマッピングされますモデルを作成して、<div>の先頭に表示します。

モデル:

<myElement>x</myElement> 

ビュー:あなたが見ることができるように

<div>x<h4></h4></div> 

、あなたのケースでは、それはmyElementで結合されなければならない<h4>です。

現時点では、リファクタリングフェーズ中です。目標の1つは、コンバータビルダーのためのより多くのユーティリティ機能を提供することです。それらのユーティリティの1つは、上記のdiv + h4のようなラッパー要素を持つ要素のコンバーターです。これはイメージ機能の場合もあります。画像は<image>(モデル)ですが、ビュー内では<figure><img /></figure>です。 ckeditor5-imageを見ると、これらのコンバータがどのように見えるかを確認できます。我々はそれらを単純化したい。

内部に複数の要素があるため、残念ながら実際のケースはさらに複雑です。 CKE5アーキテクチャはあなたのケースを処理できるはずですが、適切なガイドなしでこれを書くことはほとんど不可能であることを理解する必要があります。

もしあなたがしっかりしたいなら、studyckeditor5-imageレポ。それは簡単ではありませんが、これが最良の方法です。 ImageプラグインとImageCaptionはあなたのケースに非常によく似ています。

モデル:あなたのケースでは、私はどこかにこれらの行の間でモデル参照してくださいねながら

<figure class="image"> 
    <img alt="x" src="y" /> 
    <figcaption>Foo</caption> 
</figure> 

<image alt="x" src="y"> 
    <caption>Foo</caption> 
</image> 

ビュー

<rankItem imageSrc="x" linkUrl="y"> 
    <rankTitle>Foo</rankTitle> 
    <rankNotes>Bar</rankNotes> 
</rankItem> 

をそして私が作るだろうビューは少し重いですが、コンバーターを書く方が簡単です:

<li contenteditable="false"> 
    <a href="y"> 
    <img src="x" /> 
    <span class="data"> 
     <span class="title" contenteditable="true">Foo</span> 
     <span class="notes" contenteditable="true">Bar</span> 
    </span> 
    </a> 
</li> 

rankTitleおよびrankNotes- caption要素(ckeditor5-image/src/imagecaption/imagecaptionengine.js)に基づいてください。

rankItemについては、image要素(ckeditor5-image/src/image/)です。

もう一度、このすべてを簡略化していることに注意してください。私たちは、あなたのような複雑なものであっても、人々が自分の特徴を書くことを望みます。しかし、私たちはそれが現在どの程度複雑であるかを認識しています。そのため、現時点ではドキュメントが存在しないため、私たちは物事を変更して単純化しようとしています。

そして最後に - あなたは、シンプルなリストランキングLinkプラグインと要素コンバータビルダーでビルド使用していることを作成することができます: - ><ol class="rank">

  • rankItem - ><li>
  • rankImage -

    • rankListを><img />,
    • rankNotes - ><span class="notes">,
    • rankTitle - ><span class="title">

    しかし、構造全体が編集可能になるので、それを混乱させる可能性があります。

    モデル: "foo" と "バー" もlinkHref属性が設定されている

    <rankList> 
        <rankItem> 
        <rankImage linkHref="" /> 
        <rankTitle>Foo</rankTitle> 
        <rankNotes>Bar</rankNotes> 
        </rankItem> 
        ... 
    </rankList> 
    

    ビュー:このような

    <ol class="rank"> 
        <li> 
        <a href=""><img src="" /></a> 
        <span class="title"><a href="">Title</a></span> 
        <span class="notes"><a href="">Foo</a></span> 
        </li> 
        ... 
    </ol> 
    

    は何か、しばらく遠く完璧から、限り、私たちはリファクタリングの前とガイドを書き込む前にあるとして記述する方がはるかに簡単でなければなりません。

    もちろん、ビューからモデルへのコンバータも用意する必要があります。自分で書きたいと思うかもしれません(ckeditor5-list/src/converters.jsviewModelConverter()ですが、入れ子にされたリストではないのでフラットになりますので、あなたの方が簡単になります)。または、コンバータビルダを使用してそれらを生成することもできます。

    おそらく上記の手法を使用することは可能ですが、構造を制御するにはcontentEditable属性を使用します。 rankList<ol>contentEditable="false"と変換する必要があります。例えば、より良い選択処理のために何とかtoWidgetを使用することができます。 rankNotesrankTitleは、contentEditable="true"(おそらくtoWidgetEditable()を使用)の要素に変換する必要があります。

  • +0

    詳細な回答と実装のアドバイスをありがとうございます。 これは非常に理解しやすく、私が望むものでした。 私はモデリングによってカスタムウィジェットを実装しようとします。 – inoutch

    関連する問題