最初の質問: 特定の要素の部分選択を防ぐことは可能ですか?
うーん...プレースホルダープラグインのサンプルを確認できます-編集不可能なインライン要素を使用して、少なくともChromeでは部分的に選択できないプレースホルダーを作成します。ただし、それはあなたにとって満足のいく解決策ではないと思います:)
もう1つの考えられる解決策はeditor#selectionChange
、選択範囲の1つがその要素内にあるかどうかを確認できるイベントを使用し、そうであれば、その要素の前または後に設定することです。次のようになります (私はこのコードをテストしていません。これは単なるプロトです)。
editor.on( 'selectionChange', function( evt ) {
var sel = evt.data.selection,
range = sel.getRanges()[ 0 ];
if ( protectedElement.contains( range.startContainer ) || protectedElement.equals( range.startContainer ) )
range.setStartAt( protectedElement, CKEDITOR.POSITION_BEFORE_START );
if ( protectedElement.contains( range.endContainer ) || protectedElement.equals( range.endContainer ) )
range.setEndAt( protectedElement, CKEDITOR.POSITION_AFTER_END );
sel.selectRanges( [ range ] );
} );
ただし、この種のソリューションは常に危険であり、多くの予測不可能な状況を引き起こす可能性があります. しかし、チェックする価値があるかもしれません。
問題の根本に戻ります。同じレベルで機能するスタイルを作成したいということは理解しています。つまり、1 つの場所に適用できるのは 1 つだけです。これは、スタイリング システムを使用することはできません。スタイルを適用する前に範囲を準備する必要があります。コードはリスナーに似ていselectionChange
ます。端がスタイル要素に固定されているかどうかを確認し、そうであれば、範囲の端をそこから移動する必要があります。唯一の問題は、この状況で要素全体を範囲から除外する方法です。
<p>foo[bar<span class="st1">bom</span>bim]foo</p>
結果は 2 つの範囲になります。
<p>foo[bar]<span class="st1">bom</span>[bim]foo</p>
残念ながら、現在の範囲の API には のような便利なメソッドが含まれていないため、独自のメソッドrange#exclude
を実装する必要があります。これをwalkerでやってみます。範囲の開始から終了まで反復し、すべてのスタイル要素を記憶します。これを両方向に行うと、両端で部分的に選択された要素も収集されるため、最初に説明した手順は不要になります。範囲から除外する要素のリストがある場合は、両端とこれらの要素の間に範囲を作成するだけです。この部分は簡単なはずです。Element#getPositionは役に立ちますが、文書化されていないため、コードを確認して使用方法を理解する必要があります。