Javascript .querySelector find <div> by innerTEXT


108

特定のテキストを含むDIVを見つけるにはどうすればよいですか?例えば:

<div>
SomeText, text continues.
</div>

次のようなものを使用しようとしています:

var text = document.querySelector('div[SomeText*]').innerTEXT;
alert(text);

もちろん、それは機能しません。どうすればできますか?


たとえそれができたとしても、すべてのdivを取得してinnerTextプロパティでフィルタリングするよりも速くはありません。それでは、手動で実行してみませんか。
Redu

回答:


99

OPの質問は、jQueryではなくプレーンJavaScriptについてです。答えはたくさんあり、@ Pawan Nogariya answerが好きですが、この代替案をチェックしてください。

JavaScriptでXPATHを使用できます。MDN記事の詳細については、こちらをご覧ください

このdocument.evaluate()メソッドは、XPATHクエリ/式を評価します。そこで、XPATH式をそこに渡し、HTML文書を走査して、目的の要素を見つけることができます。

XPATHでは、次のようなテキストノードによって要素を選択できますdiv。この場合、次のテキストノードを持つを取得します。

//div[text()="Hello World"]

一部のテキストを含む要素を取得するには、以下を使用します。

//div[contains(., 'Hello')]

contains()XPATH のメソッドは、ノードを最初のパラメーターとして、検索するテキストを2番目のパラメーターとして受け取ります。

ここでこのプランクを確認してください。これはJavaScriptでのXPATHの使用例です

ここにコードスニペットがあります:

var headings = document.evaluate("//h1[contains(., 'Hello')]", document, null, XPathResult.ANY_TYPE, null );
var thisHeading = headings.iterateNext();

console.log(thisHeading); // Prints the html element in console
console.log(thisHeading.textContent); // prints the text content in console

thisHeading.innerHTML += "<br />Modified contents";  

ご覧のとおり、HTML要素を取得して、好きなように変更できます。


ありがとうございました!よく働く!しかし、このテキストから単語を1つだけ取得する必要がある場合、「thisHeading.textContent」を「console.log」する方法は?例: '// div [contains(。、\' / You login(。*)times this session / \ ')]'、次にalert(thisHeading.textContent。$ 1)
passwd

わかりました。次のようにしalert(thisHeading.textContent.replace(/.*You have login (.*) times.*/,'$1')) ;
ます。– passwd

@passwd、それはできません。.evaluate()正規表現はXPATH 1.0(使用しています。間違っている場合は誰かが私を修正してください)ではサポートされていないため、最初に、正規表現に一致するものを検索できません。次に、.textContentプロパティは要素のテキストノードを返します。このテキストから値を取得する場合は、おそらく正規表現に一致し、一致する値をグループで返す関数を作成することによって、明示的に処理する必要があります。そのためには、別のスレッドで新しい質問を作成します。
2016年

Internet Explorer:サポートなし。ただし、Edgeではサポートされています。バージョン的にはどういう意味かわかりません。
Rolf

私が探している要素が見つからない場合、どのようにエラーを処理する必要がありますか?
nenito

70

このかなりシンプルなソリューションを使用できます:

Array.from(document.querySelectorAll('div'))
  .find(el => el.textContent === 'SomeText, text continues.');
  1. Array.fromアレイへのNodeListを変換する(拡散オペレータまたはスライスのように、これを行うために複数の方法が存在します)

  2. 結果は配列になり、Array.findメソッドを使用できるようになり、任意の述部を入れることができます。正規表現や好きなものでtextContentをチェックすることもできます。

なお、Array.from及びArray.findES2015機能です。TeはトランスパイラーなしでIE10のような古いブラウザーと互換性があります。

Array.prototype.slice.call(document.querySelectorAll('div'))
  .filter(function (el) {
    return el.textContent === 'SomeText, text continues.'
  })[0];

1
あなたが複数の要素を見つけるしたい場合は、交換してくださいfindfilter
RubbelDieKatz

38

あなたはjavascriptでそれを要求したので、あなたはこのようなものを持つことができます

function contains(selector, text) {
  var elements = document.querySelectorAll(selector);
  return Array.prototype.filter.call(elements, function(element){
    return RegExp(text).test(element.textContent);
  });
}

そしてそれをこのように呼びます

contains('div', 'sometext'); // find "div" that contain "sometext"
contains('div', /^sometext/); // find "div" that start with "sometext"
contains('div', /sometext$/i); // find "div" that end with "sometext", case-insensitive

1
このように機能するようですが、見返りに私はこれだけを取得しています:[object HTMLDivElement],[object HTMLDivElement]
passwd

はい、一致するテキストが含まれるdivを取得し、内部テキストメソッドを次のようfoundDivs[0].innerTextな単純な方法で呼び出すことができます
Pawan Nogariya

20

このソリューションは次のことを行います。

  • ES6スプレッド演算子を使用して、すべてdivののNodeListを配列に変換します。

  • がクエリ文字列と完全に一致するだけでなく、クエリ文字列div が含まれている場合に出力を提供します(他の回答の一部で発生します)。たとえば、「SomeText」だけでなく、「SomeText、テキストが続く」にも出力を提供する必要があります。

  • divクエリ文字列だけでなく、コンテンツ全体を出力します。たとえば、「SomeText、テキストが続く」の場合は、「SomeText」だけでなく、その文字列全体を出力する必要があります。

  • div単一のだけでなく、複数のに文字列を含めることができdivます。

[...document.querySelectorAll('div')]      // get all the divs in an array
  .map(div => div.innerHTML)               // get their contents
  .filter(txt => txt.includes('SomeText')) // keep only those containing the query
  .forEach(txt => console.log(txt));       // output the entire contents of those
<div>SomeText, text continues.</div>
<div>Not in this div.</div>
<div>Here is more SomeText.</div>


3
これ大好き。クリーン、簡潔、そしてわかりやすい-すべてを同時に。
ba_ul 2018

2
恐ろしく非効率的ですか?innerHTML一番上<div>のsの大きさを考えてください。div最初に子を含むを除外する必要があります。また、容疑者document.getElementsByTagName('div')はより速いかもしれませんが、私は確かにベンチマークをします。
Timmmm

これは私にとっては素晴らしいことです。
最初

10

照会するdivの親要素があるかどうかを確認するのが最善です。もしそうなら、親要素を取得してを実行しelement.querySelectorAll("div")ます。取得したらnodeListinnerTextプロパティにフィルターを適用します。我々が照会されていることをdiv要素の親要素が持っていると仮定idするとcontainer。通常はidから直接コンテナにアクセスできますが、適切な方法で実行してみましょう。

var conty = document.getElementById("container"),
     divs = conty.querySelectorAll("div"),
    myDiv = [...divs].filter(e => e.innerText == "SomeText");

以上です。


これは私にとってはうまくいきましたが、innerTextではなくinnerHTMLを使用しました
Chase Sandmann '28

5

jqueryなどを使用したくない場合は、これを試すことができます:

function findByText(rootElement, text){
    var filter = {
        acceptNode: function(node){
            // look for nodes that are text_nodes and include the following string.
            if(node.nodeType === document.TEXT_NODE && node.nodeValue.includes(text)){
                 return NodeFilter.FILTER_ACCEPT;
            }
            return NodeFilter.FILTER_REJECT;
        }
    }
    var nodes = [];
    var walker = document.createTreeWalker(rootElement, NodeFilter.SHOW_TEXT, filter, false);
    while(walker.nextNode()){
       //give me the element containing the node
       nodes.push(walker.currentNode.parentNode);
    }
    return nodes;
}

//call it like
var nodes = findByText(document.body,'SomeText');
//then do what you will with nodes[];
for(var i = 0; i < nodes.length; i++){ 
    //do something with nodes[i]
} 

テキストを含む配列内のノードを取得したら、それらを使用して何かを行うことができます。それぞれに警告するか、コンソールに出力します。1つの注意点は、これは必ずしもdiv自体を取得する必要がない場合があることです。これは、探しているテキストを含むtextnodeの親を取得します。


3

データ属性のテキストの長さに制限がないため、データ属性を使用してください!そして、通常のcssセレクターを使用して、OPが望むように要素を選択できます。

for (const element of document.querySelectorAll("*")) {
  element.dataset.myInnerText = element.innerText;
}

document.querySelector("*[data-my-inner-text='Different text.']").style.color="blue";
<div>SomeText, text continues.</div>
<div>Different text.</div>

理想的には、ドキュメントの読み込み時にデータ属性設定部分を実行し、パフォーマンスのためにquerySelectorAllセレクターを少し絞り込みます。


2

Googleはこれを、特定のテキストを含むノードを見つける必要がある人のためのトップの結果として持っています。更新により、現在のブラウザではノードリストを配列に変換せずに反復可能になりました。

ソリューションは、forEachをそのように使用できます。

var elList = document.querySelectorAll(".some .selector");
elList.forEach(function(el) {
    if (el.innerHTML.indexOf("needle") !== -1) {
        // Do what you like with el
        // The needle is case sensitive
    }
});

これは、通常のセレクターが1つのノードしか選択できないときにノードリスト内でテキストを検索/置換するのに役立ちました。そのため、針をチェックするために各ノードを1つずつフィルターする必要がありました。


2

XPathとdocument.evaluate()を使用し、text()ではなくを使用してください。contains()引数の場合、そうでない場合は、HTML全体、または最も外側のdiv要素が一致します。

var headings = document.evaluate("//h1[contains(text(), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );

または先頭と末尾の空白を無視する

var headings = document.evaluate("//h1[contains(normalize-space(text()), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );

またはすべてのタグタイプ(div、h1、pなど)に一致

var headings = document.evaluate("//*[contains(text(), 'Hello')]", document, null, XPathResult.ANY_TYPE, null );

その後、繰り返す

let thisHeading;
while(thisHeading = headings.iterateNext()){
    // thisHeading contains matched node
}

このメソッドを使用して、要素にクラスを追加できますか?例thisheading.setAttribute('class', "esubject")
マシュー

要素を取得したら、確認してください。ただし、element.classList.add( "esubject")を使用することをお勧めします:)
Steven Spungin

1

これがXPathアプローチですが、最低限のXPath専門用語を使用しています。

要素の属性値に基づく通常の選択(比較用):

// for matching <element class="foo bar baz">...</element> by 'bar'
var things = document.querySelectorAll('[class*="bar"]');
for (var i = 0; i < things.length; i++) {
    things[i].style.outline = '1px solid red';
}

要素内のテキストに基づくXPath選択。

// for matching <element>foo bar baz</element> by 'bar'
var things = document.evaluate('//*[contains(text(),"bar")]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
for (var i = 0; i < things.snapshotLength; i++) {
    things.snapshotItem(i).style.outline = '1px solid red';
}

そして、テキストはより揮発性であるため、大文字と小文字を区別しません。

// for matching <element>foo bar baz</element> by 'bar' case-insensitively
var things = document.evaluate('//*[contains(translate(text(),"ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz"),"bar")]',document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
for (var i = 0; i < things.snapshotLength; i++) {
    things.snapshotItem(i).style.outline = '1px solid red';
}

0

同様の問題がありました。

argからのテキストを含むすべての要素を返す関数。

これは私にとってはうまくいきます:

function getElementsByText(document, str, tag = '*') {
return [...document.querySelectorAll(tag)]
    .filter(
        el => (el.text && el.text.includes(str))
            || (el.children.length === 0 && el.outerText && el.outerText.includes(str)))

}


0

ここにはすでに多くの優れたソリューションがあります。ただし、より合理化されたソリューションを提供するために、querySelectorの動作と構文のアイデアに合わせてもう1つ、Objectをいくつかのプロトタイプ関数で拡張するソリューションを選択しました。これらの関数はどちらも、テキストの照合に正規表現を使用しますが、文字列を緩い検索パラメーターとして指定できます。

以下の機能を実装するだけです。

// find all elements with inner text matching a given regular expression
// args: 
//      selector: string query selector to use for identifying elements on which we 
//                should check innerText
//      regex: A regular expression for matching innerText; if a string is provided,
//             a case-insensitive search is performed for any element containing the string.
Object.prototype.queryInnerTextAll = function(selector, regex) {
    if (typeof(regex) === 'string') regex = new RegExp(regex, 'i'); 
    const elements = [...this.querySelectorAll(selector)];
    const rtn = elements.filter((e)=>{
        return e.innerText.match(regex);
    });
    
    return rtn.length === 0 ? null : rtn
}

// find the first element with inner text matching a given regular expression
// args: 
//      selector: string query selector to use for identifying elements on which we 
//                should check innerText
//      regex: A regular expression for matching innerText; if a string is provided,
//             a case-insensitive search is performed for any element containing the string.
Object.prototype.queryInnerText = function(selector, text){
    return this.queryInnerTextAll(selector, text)[0];
}

これらの関数を実装すると、次のように呼び出しを行うことができます。

  • document.queryInnerTextAll('div.link', 'go');
    これは、すべて見つけるだろうdivを含むリンクの単語を持つクラスを行く(。例えばのinnerText中を移動し、左またはダウンしたり右に行くか、それの囲碁 OD
  • document.queryInnerText('div.link', 'go');
    これは、最初の一致する要素のみを返すことを除いて、上記の例とまったく同じように機能します。
  • document.queryInnerTextAll('a', /^Next$/);
    正確に次のテキストを含むすべてのリンクを検索します(大文字と小文字を区別)。これにより、他のテキストとともにNextという単語を含むリンクが除外されます。
  • document.queryInnerText('a', /next/i);
    大/小文字に関係なく、nextという単語を含む最初のリンクを見つけます(例:Next PageまたはGo to next
  • e = document.querySelector('#page');
    e.queryInnerText('button', /Continue/);
    これにより、コンテナ要素内で、テキスト「Continue(case-sensitive)を含むボタンを検索します。(例えば続行または次に進みなく継続
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.