0

CKEDITOR 選択オブジェクトのいくつかの便利な属性を発見しました ( get via editor.getSelection()):

e.getSelection().getRanges()[0].startOffset
e.getSelection().getRanges()[0].endOffset

これは、選択したテキストの開始位置と終了位置を返しますが、startContainer (要素) と endContainer (要素) に関連する場合のみです。選択したhtmlを識別するために、ドキュメント全体または何か他のものに対する絶対位置を取得したいと思います(開始要素または終了要素のインターンID?)。サーバー側でこの属性を読み取り、そこで選択した html を変更したいと思います。選択したテキストの位置に関する情報をクライアント側からサーバー側に移動する普遍的な方法はありますか?

どうもありがとう。

4

4 に答える 4

2

私があなたを正しく理解していれば、サブミット/ajax呼び出し中にカーソルがあった場所または選択があった場所に基づいて、サーバー側の特定のノードまたは複数のノードを識別したいと考えています。そして、現在の選択のノードを取得するための呪文を既に知っています。

サーバーに送信する前に、要素に手動でタグを付けることをお勧めします。送信する前に対象の被害者にカスタム属性またはクラスを追加し、そのタグを使用してノードのサーバー側を識別します。

たとえば[、選択の開始であり]、終了であり、データは次のとおりです。

<p>foo</p><p>[bar</p><p>baz]</p>

送信する前に、要素を取得して JS でタグ付けし、次のようにします。

<p>foo</p><p class="chosen">bar</p><p class="chosen">baz</p>

そして、好きな XML/HTML 武器を使用して、タグ付けされた要素を見つけることができますchosen(C# を使用している場合は、CSQuery をお勧めします)。次に、タグを削除して、ノードに入札を行うように命令します。複数のノードの場合は、複数のノードにタグを付けるだけです。

于 2013-04-23T20:15:51.327 に答える
1

この計算は、CKEDITOR の原則に大きく反します。しかし、私は最善の解決策を発見したと思います.Nenotlepが提案したものとほぼ同じです:

var bookmarks = e.getSelection().createBookmarks(true);
var startId = bookmarks[0].startNode;
var endId = bookmarks[0].endNode;

これにより、非表示のブックマーク (ID startId と endId にまたがる) がコードに挿入され、サーバー側で処理できるようになります。ここで、複数選択の問題とタグの交差の問題を解決する必要があります。

于 2013-04-24T08:15:34.813 に答える
0

今、私はこの問題を解決する必要があります: - 誰かが (* = 選択境界線) を選択したい場合:<b>some te*xt </b> aaa <i>bb*b</i>

...JS はこのブックマークを置きます:

<b>some te
<span id="cke_bm_69S" style="display: none;">&nbsp;</span>
xt</b> 
aaa 
<i>bb
<span id="cke_bm_69S" style="display: none;">&nbsp;</span>
b</i> 

...そして、私はこのようなことをしなければなりません:

<b>some te
</b><span property="..."><b>xt</b>
aaa 
<i>bb</i></span><i>b</i> 

私の解決策 (まだテストされていません): id="cke_bm_69S" のノードを選択し、タグ交差の問題を確認し、問題がある場合は before() および after() メソッドを使用して html を挿入します。しかし、残念ながら、一時的に閉じられていないタグが存在する可能性があります。大丈夫かどうかはわかりません。

于 2013-04-25T10:07:13.207 に答える
0

私は良いエレガントな解決策を見つけました:

textselector.js (マークの選択 - ブックマーを CKEDITOR に挿入)

 function selectText(irtId, startIdSelectionId, endIdSelectionId) {
    var editor = CKEDITOR.instances[irtId];
    if (editor.getSelection().getRanges()[0].collapsed) {
        document.getElementById(startIdSelectionId).value = "";
        document.getElementById(endIdSelectionId).value = "";
    } else {
        var bookmarks = editor.getSelection().createBookmarks(true);
        var startId = bookmarks[0].startNode;
        var endId = bookmarks[0].endNode;
        document.getElementById(startIdSelectionId).value = startId;
        document.getElementById(endIdSelectionId).value = endId;
    }
    return true;
}

サーバー側でのアクション (競合を特定する - タグの交差、必要に応じて要素を修復する - 2 つの部分に分割してスパンを挿入する):

/**
 * prida span na oznacene html osestreni nezadoucich pripadu: prazdny
 * select, kolize s jinym spanem
 */
public void spanSelectedHtml() {
    // parsovani celeho dokumentu
    Document doc = Jsoup.parse(value);
    // osetreni chybovych stavu
    // - prazdny select
    if (startIdSelection.isEmpty() || endIdSelection.isEmpty()) {
        return;
    }
    // nalezeni znacek
    Element es = doc.getElementById(startIdSelection);
    Element ee = doc.getElementById(endIdSelection);
    // - konflikt s jinou znackou
    // bude doplneno

    // oprava okoli znacek v pripade nutnosti
    repairIfNecessary(es, ee);
    // vytvoreni span tagu s nalezitymi atributy
    Element span = doc.createElement("span");
    span.attr("property", clicked.getUrl());
    span.attr("class", clicked.getStyleClass());
    // nahrazeni prvni znacky span tagem
    es.replaceWith(span);
    // pripojeni vsech nasledujicich uzlu az do koncove znacky
    while (span.nextSibling() != ee) {
        span.appendChild(span.nextSibling());
    }
    // odstraneni koncove znacky
    ee.remove();
    // aktualizace hodnoty textove komponenty
    value = doc.toString();
}

/**
 * oprava okoli elementu v pripade nutnosti - pri zjisteni unikatniho rodice
 *
 * @param e1 prvni element
 * @param e2 druhy element
 */
private void repairIfNecessary(Element e1, Element e2) {
    while (hasUniqueParent(e1, e2)) { // unikatni rodice e1?
        repairElement(e1);
    }
    while (hasUniqueParent(e2, e1)) { // unikatni rodice e2?
        repairElement(e2);
    }
}

/**
 * oprava okoli elementu: rozdeleni na dve casti a vymazani rodice,
 * zachovani atributu
 *
 * @param e element s okolim na opravu
 */
private void repairElement(Element e) {
    // "problemovy rodic", ktereho je treba rozdelit
    Element p = e.parent();
    // 1. cast - pred znackou
    if (e.previousSibling() != null) { // osetreni null
        Element n = p.clone().empty(); // vkladany element musi byt formalne stejny
        p.prependChild(n); // umisteni elementu na zacatek - jako 1. dite
        while (n.nextSibling() != e) { // dokud se nedostanu ke znacce, pridavam uzly
            n.appendChild(n.nextSibling());
        }
    }
    // 2. cast - za znackou
    if (e.nextSibling() != null) { // osetreni null
        Element n = p.clone().empty(); // vkladany element musi byt formalne stejny
        p.appendChild(n); // umisteni elementu na konec - jako posledni dite
        while (n.previousSibling() != e) { // dokud se nedostanu ke znacce, pridavam uzly
            n.prependChild(n.previousSibling());
        }
    }
    p.unwrap(); // vymazani puvodniho "problemoveho rodice"
}

/**
 * ma testovaci element rodice, ktereho kontrolni element nema?
 *
 * @param e testovaci element
 * @param c kontrolni element
 * @return testovaci element ma unikatniho rodice (takoveho, ktery kontrolni
 * element nema)
 */
private boolean hasUniqueParent(Element e, Element c) {
    if (e.parents().isEmpty() || c.parents().isEmpty()) { // test na null
        return false;
    }
    for (Element pe : e.parents()) {
        if (!c.parents().contains(pe)) {
            return true; // unikatni rodic
        }
    }
    return false; // bez unikatniho rodice
}
于 2013-04-27T12:06:13.257 に答える