質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

3回答

1635閲覧

ある文字列を囲んでいるタグ(要素)を取得したい

kadot

総合スコア27

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

1クリップ

投稿2021/06/12 03:56

編集2021/06/12 07:26

JavaScipt(またはjQuery)や正規表現を使って、電話番号を囲んでいるタグだけにクラスをつけたいです。

今考えているのは、
正規表現で電話番号を検索し、その電話番号を囲んでいるタグ(要素)をどうにかして取得して、クラスを追加する方法です。

添付画像でいうと、
黄色部分をまず検索し、何らかの方法で赤線まで取得して、クラスを追加するイメージです。

しかし、その方法がわかりません。

わかる方いたら教えていただけきたいです。
よろしくお願いいたします。

【追記】
質問の仕方で混乱させてしまい申し訳ありません。
添付画像は一例です。
ページ内のどこにどんな構造で電話番号があるかわからないケースを想定しています。

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

jQueryを使ってよいなら、:contains() はどうでしょうか。
:contains() Selector | jQuery API Documentation

js

1$( "p:contains('000-1166-0000')" ).addClass('Klass')

質問を勘違いしていたので追記

NodeIterator がいいかもしれないですね。
NodeIterator - Web APIs | MDN

js

1const nodeIterator = document.createNodeIterator( 2 document.body, 3 NodeFilter.SHOW_TEXT, 4 { 5 acceptNode: function (node) { 6 return /\d{3}-\d{4}-\d{4}/.test(node.nodeValue) ? 7 NodeFilter.FILTER_ACCEPT : 8 NodeFilter.FILTER_REJECT; 9 } 10 } 11); 12 13while ((node = nodeIterator.nextNode())) { 14 node.parentNode.classList.add('Klass'); 15}

投稿2021/06/12 04:17

編集2021/06/12 05:57
Lhankor_Mhy

総合スコア36134

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2021/06/12 04:17

あ、正規表現でしたか…… 失礼しました。
kadot

2021/06/12 05:07

ありがとうございます。 NodeIterator初めて見ました。 ちょっと読み解いてみます! 正規表現使わない方法でも大丈夫です! ただ、どこにどんな構造で電話番号があるかわからないケースを想定しているので、正規表現でヒットさせる方法しか思いついてない状態です。 :containsも初めて見ましたので調べてみます。
kadot

2021/06/12 15:06 編集

NodeIterator、やっと何が書いてあるかだいたい理解できました。 テキストノードを取得して、親ノードを取得すれば、囲んでいるタグを取得できることを知って感動しました。 2点、追加で教えていただきたいことがあります。 ・フィルタ関数の箇所は、名前なしでいきなりfunction...と書き始める記事(https://developer.mozilla.org/ja/docs/Web/API/Document/createNodeIterator)が多そうですが、acceptNode: としたのは、名前があったほうがわかりやすいからという理由でしょうか? acceptNode:と書いても挙動が変わらないものなのか気になりまして。 ・TreeWalkerの記事(https://uhyohyo.net/javascript/7_3.html)を見ながら読み解いたのですが、そのままNodeIteratorで読み変えるとまずい部分はありますか? よろしくお願いいたします。
Lhankor_Mhy

2021/06/13 14:57

そうですね、普通に関数を置いて構わないと思います。 MDNの解説に「NodeFilter インターフェースを実装したオブジェクト」とあったので、それに従ってコードを書いたのですが、よく見るとそのあとに「 (代わりに単純なコールバック関数を使用することもできます)」とありました。 調べてみたところ、このような理由のようでした。 https://qiita.com/yuki3/items/ab20985e70247c80d19c 勉強になりました。 --- 問題ないと思いますが、私もあまり使ったことがないAPIなので、間違っていたらすみません。
kadot

2021/06/14 12:48

なるほどですね。 じっくり読んでみます。 いえ、僕のほうこそ勉強になりました。 ーーーーーーーーーー 承知しました。 自分でももっと調べてみます。 Lhankor_Mhyさんから教えてもらったNodeIteratorですが、最終的にこういう感じで使わせていただきました。(https://teratail.com/questions/343751) NodeIteratorを教えてもらっていなかったらたどり着けなかったかもしれません。 ありがとうございました。 また機会がありましたらよろしくお願いいたします。
guest

0

最初のwrapperクラスの場合は、以下でできそうです。

JavaScript

1var el = document.querySelector("div.wrapper div p"); 2el.classList.add("hoge"); 3console.log(el); 4//<p class="hoge">電話番号は000-1166-0000</p>

2つ目以降のwrapperクラスに操作する場合には、id="test"をつけて、これでどうでしょうか?

JavaScript

1var el2 = document.querySelector("#test div p"); 2el2.classList.add("hoge"); 3console.log(el2);

参考:MDN|Document.querySelector()

追記しました。
不確定なタグに特定の電話番号(文字列)がある場合に、タグにClassを追加する方法ついて追記しました。

JavaScript

1var bodyText = document.body.innerHTML; 2var phoneNumber = "000-1166-0000";//検索する電話番号 3var addedClass = "myClass";//付与するclass 4 5var reg = new RegExp(`<(.*)>(.*)${phoneNumber}(.*)?>`); 6bodyText = bodyText.replace(reg, `<$1 class=${addedClass}>$2${phoneNumber}$3>`); 7document.body.innerHTML = bodyText;

一個一個のタグを調べてはおらずざっくり全体から調べてClassを追加していますが、ご希望にかなっていれば幸いです。

複数の電話番号に対応しました。RegExp内の"g"で解決します。
もっとスマートな正規表現もあるかもしれないですが、とりあえずこれでご確認ください。

JavaScript

1var bodyText = document.body.innerHTML; 2var addedClass = "myClass";//付与するclass 3 4var reg = new RegExp(/<(.+)>(.*)(\d{3}-\d{4}-\d{4})(.+)?>/,"g"); 5bodyText = bodyText.replace(reg, `<$1 class=${addedClass}>$2$3$4>`); 6document.body.innerHTML = bodyText;

投稿2021/06/12 05:55

編集2021/06/12 13:47
gas.engine

総合スコア608

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kadot

2021/06/12 07:23

添付画像の例だけなら、gas.engineさんの方法で行けそうなのですが、 ページ内のどこにどんな構造で電話番号があるかわからないケースを想定しています。 僕の質問の仕方が良くなかったと思います。 でも、回答いただきとても嬉しいです。ありがとうございます。
kadot

2021/06/12 13:15

追記してくださりありがとうございます。 電話番号も動的にしたいのですが、 phoneNumberを下記のように正規表現で書いてもいけそうでしょうか? var phoneNumber = /\d{3}-\d{4}-\d{4}/;//検索する電話番号 いま試したら挙動が変わってしまったので、 どこか書き直さないといけない箇所はありますか? (正規表現、まだ理解が不足していまして…)
gas.engine

2021/06/12 13:49

それ単体は正しいのですが、代入などしているうちにおかしくなるようです。 複数に対応できるよう修正しましたので、お試しください。
kadot

2021/06/12 15:12 編集

ありがとうございます。 電話番号の箇所が正規表現でもいけるのはとても嬉しいです。 ちょっといろいろなHTMLのパターンで試してみます! またメッセージします!(おそらく明日になります)
kadot

2021/06/13 02:56

試してみました。 クラスをすでに持っている要素や、入れ子が複雑の時(あいうえお~の箇所)に、クラスが追加されないようです。 例えば、以下のようなHTML <body> <div class="wrapper"> <p>000-5623-0000</p> <div> <p class="testtest">電話番号は000-1166-0000</p> <p class="test">&lt;p&gt;000-0000-0000&lt;/p&gt;</p> <p>000-0000-0000</p> </div> <form action=""> <input type="text" value="000-5555-5555"> <select name="" id=""> <option value="">000-9999-9999</option> </select> </form> <p> あいうえお000-0000-6980 000-0000-6980 000-0000-6980かきくけこ <span> 000-0000-0000 <a href="#">000-0000-0000</a> <span> 000-0000-0000 </span> </span> </p> <a href="">test000-0000-0000</a> <p>000-0000-0000</p> </div> </body> でも、たぶん正規表現わかればいけそうでしょうか。シンプルなコードで済むのは魅力的だと感じているので正規表現をもっと勉強してみたいと思います。
gas.engine

2021/06/13 15:26

//classが既にある場合に追加 var reg1 = new RegExp(/<(.+ class=".+)">(.*)(\d{3}-\d{4}-\d{4})(.+)?>/,"g"); bodyText = bodyText.replace(reg1, `<$1 ${addedClass}">$2$3$4>`); //classがない場合 var reg2 = new RegExp(/<(.+)>(.*)(\d{3}-\d{4}-\d{4})(.+)>/,"g"); bodyText = bodyText.replace(reg2, `<$1 class="${addedClass}">$2$3$4>`); 若干上記で検出が増えますが、漏れがあるものをコツコツつぶす必要があるので、大変だと思います。 createNodeIteratorのほうでお願いいたします。(笑)
kadot

2021/06/14 12:52

今日、正規表現を少し勉強して、昨日よりは読めるようになりました。 いろんなパターンを網羅する必要があるのですね。 今回はcreateNodeIteratorを使いますが、gas.engineさんのやり方も覚えておきます! ありがとうございました。 また機会がありましたらよろしくお願いいたします。
guest

0

bodyのツリーのノードを愚直に1つ1つ辿って行って、ノード毎にinnerHTMLを調べて、マッチしたらそのノードにクラスを追加する。
それより簡単な方法は私は思いつきません。

投稿2021/06/12 04:14

itagagaki

総合スコア8402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kadot

2021/06/12 05:02

ありがとうございます。 試してみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問