2

Google 拡張機能で DOM を操作する

Gmailウィンドウにリンクを挿入する必要があるGoogle Chrome拡張機能を作成しています。ウィンドウの上部に単純な拡張ボタンを作成し、電子メール ドキュメントの要素を置き換えるコードを実行できます。

ここで、入力時にcontenteditableセクションにリンクを追加したいと思います。JavaScript ドキュメント オブジェクト モデルで、テキストをリンクに置き換える簡単な方法があるはずです。また、これはクロムでのみ機能する必要があります。これは、すぐにFirefoxまたはつまりバージョンを作成するつもりがないためです。

もともと私は次のことをやろうとしていました:

  1. 現在のキャレット位置からテキストを挿入
  2. キャレットの位置をキャプチャします。
  3. キャレットの位置をオフセットで設定します。

getSelection、それほど高速ではありません

現在の範囲と位置を取得するために、gmail コンテキスト (コンテンツ編集可能に設定され、gmail タブの iframe 内に埋め込まれた body 要素) 内でwindow.getSelectionを使用してみました。テキストが選択されているかどうかに関係なく、選択範囲は常に空であり、範囲は含まれていませんでした。

getSelectionコードが機能しない理由は、document.getSelectionが間違ったウィンドウで選択されていたためであることがわかりました。gmail で新しいメッセージを作成するときに使用できる iframe (ウィンドウ) は 5 つあります。このフレームの奥深くにネストされた iframe と呼ばれるものがあります。これは、正しいテキスト選択を取得するためにgetSelectionを呼び出す必要がある iframe です。電子メール メッセージの contenteditable 領域内で選択されたキャレット位置を取得できるようにするコードを次に示します。

これは、gmail ドキュメント ウィンドウの選択を取得する 1 つの方法です。

var mySelection = $("iframe")[4].contentDocument.
    querySelector("iframe").contentDocument.getSelection();

最初のテキスト置換試行

私は今、うまくいけば解決策に少し近づいています。ずさんな場合は申し訳ありませんが、このコードの書き方に関する適切なドキュメントが見つかりません。

// Select the keyword
var range = s.getRangeAt(0);
var keyEl = range.startContainer.splitText(index);
var newRange = doc.createRange();
newRange.selectNode(keyEl);
s.removeAllRanges();
newRange.setEnd(keyEl, length);
s.addRange(newRange);

// Insert the link
var newLink = document.createElement("a");
newLink.setAttribute("href", value);
s.removeAllRanges();
newRange.surroundContents(newLink);

// Set the position
newRange.setStartAfter(newLink);
newRange.collapse(true);
s.addRange(newRange);

これはほぼ完全に機能しますが、問題はテキストキャレットがリンク内にあるため、その後に入力されたテキストがリンクに挿入されることです。これは大きな問題です。そして、その問題を部分的に解消することができたいくつかのことを試してみました. 同様の新しい問題により、いくつかの奇妙なリンクが次の単語に拡張されましたが、数文字のみでした.

うまくいけば、テキスト置換の最後の試み

// find position in text 
var index = s.focusNode.data.search(keyword);
var length = keyword.length;

var range = s.getRangeAt(0);
var keyEl = range.startContainer.splitText(index);
var newRange = doc.createRange();
newRange.selectNode(keyEl);
s.removeAllRanges();
newRange.setEnd(keyEl, length);
s.addRange(newRange);

var newLink = document.createElement("a");
newLink.setAttribute("href", value);
$(newLink).css("text-decoration", "none");
$(newLink).css("cursor", "pointer");
$(newLink).css("color", "color:#3366FF");
newRange.surroundContents(newLink);
newRange.collapse(false);
s.removeAllRanges();
s.addRange(newRange);

私の多くの試練の中で蔓延しているように見えた問題が 1 つありましたが、それは今ではなくなりました。これにより、次の単語に拡張されたいくつかの奇妙なリンクが作成されました。

コードをより簡潔にするために、コードをクリーンアップするのを手伝ってください

4

1 に答える 1

0

キャレットを挿入する位置が正確にわかっている場合は、次のようにします。

var node = someTextNode;
var caret = 10; // insert caret after the 10th character
var range = document.createRange();
range.setStart(node,caret);
range.setEnd(node,caret);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

ただし、これは DOM テキスト ノードでのみ機能します。そのため、contenteditable div などのコンテンツを操作する場合は、その子要素を再帰的にたどってテキスト ノードを確認する必要があります。

私は最近、GMail を含む Web サイトでテキスト置換を行う Chrome 拡張機能を作成しました。対応する jQuery プラグインのソースは次のとおりです。ユース ケースに適合する場合は、自由に活用してください: https://github.com/squidpeople/ASCIImoji/blob/マスター/asciimoji.jquery.js

于 2013-07-29T17:35:20.373 に答える