2010-11-18 18 views
7

HTMLドキュメントでテキストを選択すると、1つのDOM要素内から別の要素に開始することができます。 DOM APIを使用すると、選択したテキストの範囲、選択したすべてのDOM要素の親要素(使用しているブラウザに基づいてcommonAncestorContainerまたはparentElement()を使用)を取得することができます。しかし、私が知っている方法は、選択されたテキストの要素を含むすべての要素をリストすることができますが、それらをすべて含む単一の親要素を取得することはできません。この親の中で選択されていない他の兄弟が存在する可能性があるので、親を使用し、子ノードを横断することはしません。選択したテキストのすべてのDOMブロック要素を取得

したがって、選択したテキストを含むこれらの要素をすべて取得できる方法はありますか?私は主にブロック要素(p、h1、h2、h3、...など)を取得することに興味がありますが、すべての要素を取得する方法がある場合は、それらを通過し、欲しいです。アイデアや提案は大歓迎です。

ありがとうございます。

答えて

16

キーは、ここであなたがやりたいと遊ぶことができるいくつかのサンプルコードがありますwindow.getSelection().getRangeAt(0)https://developer.mozilla.org/en/DOM/range

です。疑問に思っていることを本当に言及すると、人々はより良​​い答えを提供するのに役立ちます。

var selection = window.getSelection(); 
var range = selection.getRangeAt(0); 
var allWithinRangeParent = range.commonAncestorContainer.getElementsByTagName("*"); 

var allSelected = []; 
for (var i=0, el; el = allWithinRangeParent[i]; i++) { 
    // The second parameter says to include the element 
    // even if it's not fully selected 
    if (selection.containsNode(el, true)) { 
    allSelected.push(el); 
    } 
} 


console.log('All selected =', allSelected); 

これが最も効率的な方法ではありません、あなたはnextSibling/previousSiblingはとのchildNodesとともに、レンジのstartContainer/endContainerを使用してDOM自分を横断することができます。

+0

あなたが言ったように完璧な解決策ではありませんが、それは私にそれを行う方法のアイデアを与えました。したがって、私はこれを私の必要性に最も正しい答えとして選択しました。本当にこれを感謝します。 – cria

+0

これはまともな答えですが、Internet Explorer <9では動作しません。selection.getRangeAt(0);も呼び出す前に選択が存在することを確認することができます(選択の 'rangeCount'プロパティを使うのが最も簡単です)。 –

+0

私が言及しなかったたくさんの落とし穴があります。これはちょうど正しい方向に向かうことです。あなたのライブラリは実際にそれを扱うために22kの非圧縮javascriptを必要とし、もし私がそれを必要とするならば、私はそれを使います。 –

0

Traversing from the jQuery APIのように聞こえます。

可能性があります.contents()

希望します!

+0

ええ、方法はすべて素晴らしいです。しかし、ブラウザで選択したテキスト範囲をこれらのメソッドの入力として使用できるとは思いませんか?または多分私は何かを逃しています...ありがとう – cria

10

私のRangy libraryを使用してこれを行うことができます。これは、IEを含むすべてのブラウザ用のDOM RangeおよびSelectionオブジェクトの実装を提供し、余分なRangeメソッドを備えています。これらの一つはgetNodes()です:

function isBlockElement(el) { 
    // You may want to add a more complete list of block level element 
    // names on the next line 
    return /h[1-6]|div|p/i.test(el.tagName); 
} 

var sel = rangy.getSelection(); 
if (sel.rangeCount) { 
    var range = sel.getRangeAt(0); 
    var blockElements = range.getNodes([1], isBlockElement); 
    console.log(blockElements); 
} 
+0

私はこのコードが最も正確なものであることは疑いがありません。しかし、あなたのライブラリを使用することは、libのサイズが大きいため、私の場合には過剰です。したがって、私はそれに対処する必要があるいくつかの問題があるにもかかわらず、私は他の答えを選んだ。 2つの回答を選択する選択肢があった場合、私はあなたも同様にマークします。偉大なlib/workを維持してください:) – cria

+0

@cria:十分な公正。あなたが私と一緒に得るのは、IEのサポートです。 –

+3

@TimDown Rangyに感謝します。それは一連の複雑な問題をはるかに簡単にします。 –

関連する問題