innerHTML
メールの置き換えに使用-いいえ、特にイベント リスナーが削除され、属性も置き換えられるため、ページが壊れます。
すべてのノードを再帰的にループします。
- DOM を変更するときの競合を防ぐために、逆の順序でループします。
- 各項目について、その値を確認し
nodeType
ます。
- (要素) の場合
.nodeType === 1
、関数を再度呼び出します (再帰)。
- If
.nodeType === 3
(テキスト ノード):
- 正規表現と
exec
メソッドを使用して、 1 つの電子メール アドレスを見つけます。結果の.index
プロパティを使用して、電子メール アドレスの開始位置をresult[0].length
知り、アドレスの長さを知ることができます。
- ノードの
splitText
メソッドを使用して、テキスト ノードを 3 つの部分に分割します。
- 要素を作成し
<a>
ます。
- 電子メールのテキスト ノード (前のテキスト ノードから 2 番目のノード) をこのアンカーに追加します。ドキュメントから自動的に削除されます。
- このリンクを 3 番目のノードの前に挿入します。
デモ
クロム拡張機能ではありませんが、クロム拡張機能がどのように動作するかを示しています: http://jsfiddle.net/ckw89/
Chrome 拡張機能
(正規表現はMongoEngine のEmailField
パターンに基づいています):
script.js
// Initiate recursion
wrapLink(document.body);
function wrapLink(elem) { // elem must be an element node
var nodes = elem.childNodes
, i = nodes.length
, regexp = /([-!\x23$%&'*+\/=?^_`{}|~0-9A-Z]+(\.[-!\x23$%&'*+\/=?^_`{}|~0-9A-Z]+)*|^"([\x01-\x08\x0b\x0c\x0e-\x1f!\x23-\\[\\]-\x7f]|\\[\x01-011\x0b\x0c\x0e-\x7f])*")@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}/i
, node, emailNode, a, result;
while (node = nodes[--i]) {
if (node.nodeType === 1) {
// Skip anchor tags, nested anchors make no sense
if (node.nodeName.toUpperCase() !== 'A')
wrapLink(node);
} else if (node.nodeType === 3) {
// 1: Please note that the regexp has NO global flag,
// and that `node.textContent` shrinks when an address is found
while (result = regexp.exec(node.textContent)) {
// 2: Contact <SPLIT> me@example.com for details
node = node.splitText(result.index);
// 2: Contact <SPLIT>me@example.com<SPLIT> for details
node = node.splitText(result[0].length);
// me@example.com
emailNode = node.previousSibling
// 3. Create link
a = document.createElement('a');
a.href = 'mailto:' + result[0];
// 4: Append emailNode
a.appendChild(emailNode);
// 5: Insert before
elem.insertBefore(a, node);
}
}
}
}
このスクリプトは、コンテンツ スクリプトとして使用するとすぐに機能します。これは、ページとのやり取りが DOM のみであるためです。完全を期すために、manifest.json
ファイルの内容は次のとおりです。
{
"name": "Turns email addresses in `mailto:`s",
"version": "1",
"version_version": 2,
"content_scripts": [{
"matches": ["*://*/*"],
"js": ["script.js"]
}]
}
公演予告
現在のスクリプトは、ライブ ドキュメント内のすべてのノードを置き換えます。操作する前に、ルート ノード (例: <body>
) をドキュメント フラグメントに移動することを検討してください。