14

インターネット上には多数の WYSIWYG エディタがありますが、ドラッグ アンド ドロップの実装を何らかの形で実装するものはまだ見つかりません。

独自のエディターを作成するのは簡単ですが、ユーザーが編集可能領域の外から要素 (つまりトークン) をドラッグして、編集可能領域内の任意の場所にドロップできるようにしたいと考えています。

編集可能な要素の特定の場所に html を挿入するのは簡単ですが、ユーザーが編集可能な領域の要素に DIV をドラッグしているときに、キャレットがどこにあるべきかをどのように判断するのでしょうか。私が説明しようとしていることをよりよく説明するために、次のシナリオを参照してください。

編集可能領域 (編集モードの IFRAME または contentEditable 属性が true に設定された DIV) には、既に次のテキストが含まれています。

「親愛なる、ご了承ください....」

ユーザーは、要素のリストから何らかのトークンを表す要素を編集可能領域にドラッグし、上記のようにテキスト内のコンマ (,) の直前にキャレットが表示されるまでカーソルをテキスト上に移動します。ユーザーがその場所でマウス ボタンを離すと、HTML が挿入され、次のような結果になる可能性があります。

「{UserFirstName} 様、ご注意ください ...」.

誰かがこれに似たようなことをしたことがあるかどうか、または少なくとも JavaScript を使用してこれを行う方法を知っているかどうかはわかりません。

どんな助けでも大歓迎です。

4

3 に答える 3

6

編集可能な要素のカスタム ドラッグ要素の問題を解決するための私のアプローチを次に示します。大きな問題は、編集可能な要素の上にカーソルを置いたときに、マウス カーソルのテキスト オフセットを特定できないことです。マウスのクリックを偽造してキャレットを目的の位置に設定しようとしましたが、うまくいきませんでした。あったとしても、ドラッグ中にキャレットの配置を視覚的に確認することはできず、結果のドロップのみが表示されます。

マウスオーバー イベントをテキスト ノードではなく要素にバインドできるため、編集可能な要素を一時的に編集不可に設定できます。テキストの流れを壊さないように、すべての要素を検索し、各テキスト ノードをスパンでラップします。各スパンにはクラス名を付けて、再度見つけられるようにする必要があります。

ラッピング後、ラップされたすべてのテキストノードを再度見つけて、各文字を別のスパンでラップし、それらを再び見つけることができるクラス名を付ける必要があります。

イベント委任を使用すると、メインの編集可能な要素にイベントを追加して、キャレット (背景として点滅する GIF 画像) を表示する各文字スパンにスタイルを適用できます。

ここでも、イベント委任を使用して、各キャラクターのマウスアップ イベント (ドロップ イベント) のイベントを追加する必要があります。親(ラップされたテキストノード)内の文字スパンの位置(オフセット)を使用してオフセットを決定できるようになりました。計算されたオフセットへの参照を保持しながら、適用可能なテキストノードへの参照を保持しながらラッピングを元に戻すことで、すべてのラッピングを元に戻すことができるようになりました。

ブラウザの範囲と選択オブジェクトを使用して、計算されたオフセットを使用して適切なテキストノードに選択を設定し、新しく設定された選択 (キャレット位置) に必要な HTML を挿入できます。

テキストノードを見つけてラップする jQuery を使用したスニペットを次に示します。

editElement.find("*:not(.text-node)").contents().filter(function(){ 
    return this.nodeType != 1;
}).wrap("<span class=\"text-node\"/>");

各テキストノードを見つけて各文字をラップするには、次を使用します。

editElement.find(".text-node").each(function()
{
    var textnode = $(this), text = textnode.text(), result = [];

    for (var i = 0; i < text.length; i++) result.push(text.substr(i, 1));

    textnode.html("<span class=\"char\">" 
        + result.join("</span><span class=\"char\">") + "</span>");
});

ラッピングを元に戻すには:

editElement.find(".text-node").each(function()
{
    this.parentNode.replaceChild(document.createTextNode($(this).text()), this);
});

このアプローチが同様の課題を抱えている人に役立つことを願っています

于 2011-08-15T07:42:15.193 に答える
2

あなたの言っていることが理解できれば、これは基本的なドラッグ アンド ドロップにすぎません。以下のソリューションは、FIREFOX の最良の回答に近いはずです。IEにはさまざまな機能があると確信しています。詳細については、 http://www.html5rocks.com/en/tutorials/dnd/basics/にアクセスしてください。

ドラッグするオブジェクトの「ドラッグ可能」属性を設定し、オブジェクトの「ondragstart」メソッドを「dragStartHandler」または呼び出される関数に設定します。

// You can set this to 'text/plain' if you don't want to insert HTML content
var internalDNDType = 'text/html';

function dragStartHandler(event) {
  // This is whatever html data you want to insert.
  var textContent = "<b>"+userFirstName+"</b>";

  event.dataTransfer.setData(internalDNDType, textContent);
  event.dataTransfer.effectAllowed = 'copy';
}

function dragEnterHandler(event)
{
  event.preventDefault();
  return false;
}

function dragOverHandler(event)
{
  event.preventDefault();
  return false;
}

function dropHandler(event) {
  event.preventDefault();
  event.stopPropogation();
  return false;
}
于 2012-01-03T19:28:18.453 に答える
1

現在、これを行うための HTML5 API が開発されていますが、残念ながら IE ではサポートされていません。編集: どうやら IE は実際にドラッグ アンド ドロップをサポートしているようですが、私はそれがどのように機能するかについてあまり詳しくありません。「IEドラッグアンドドロップ」をググってみてください。

これらのサイトを見てみてください:

于 2010-06-18T23:48:20.357 に答える