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

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

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

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

Q&A

解決済

2回答

3777閲覧

jquery「contains」による判別

skipping

総合スコア14

jQuery

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

0グッド

0クリップ

投稿2018/08/30 16:12

編集2018/08/30 16:17

親子関係を持つとき、子供がいる場合を判別して.append()するにはどうしたらいいでしょうか?

下記HTMLでは、子供がいない「Aさん、Dさん、Hさん、Iさん」には.append()したくないということです。

html

1<div> 2<ul> 3 4 <li> 5 <div>Aさん(親)<span class="num">1</span><span class="parent-num">0</span></div> 6 </li> 7 8 <li> 9 <div>Bさん(親)<span class="num">2</span><span class="parent-num">0</span></div> 10 <ul class="childrens"> 11 <li> 12 <div>Cさん(子)<span class="num">2.1</span><span class="parent-num">2</span></div> 13 </li> 14 <li> 15 <div>Dさん(孫)<span class="num">2.1.1</span><span class="parent-num">2.1</span></div> 16 </li> 17 <li> 18 <div>Eさん(子)<span class="num">2.2</span><span class="parent-num">2</span></div> 19 </li> 20 <li> 21 <div>Fさん(孫)<span class="num">2.2.1</span><span class="parent-num">2.2</span></div> 22 </li> 23 <li> 24 <div>Gさん(ひ孫)<span class="num">2.2.1.1</span><span class="parent-num">2.2.1</span></div> 25 </li> 26 <li> 27 <div>Hさん(孫)<span class="num">2.2.2</span><span class="parent-num">2.2</span></div> 28 </li> 29 </ul> 30 </li> 31 32 <li> 33 <div>Iさん(親)<span class="num">3</span><span class="parent-num">0</span></div> 34 </li> 35 36</ul> 37</div>

わかりにくい構造ですが、「Bさん」の子供とは、Bさんの.numの値を、.parent-numとして持っている「Cさん、Eさん」になります。

試しに書いたjQeuryですが、全てに.append()されてしまいます。

jQuery

1$(".childrens li").each(function() { 2 3 var myNum = $(this).find('.num').text(); 4 if( $('.parent-num:contains('+myNum+')') ){ 5 $(this).append('↑彼には子供がいます'); 6 } 7 8}); 9

JSfidleのサンプルです。
https://jsfiddle.net/4hodcm05/

HTMLを変えることなく判別したいと思っているのですが、どなたかできますか?
(ピリオドの数による判別は無しです。実際はピリオドなし番号なので。)

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

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

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

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

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

guest

回答2

0

jQuery

1$('.num').each(function(index, element) { 2 if ($('.parent-num').contents().filter(function() { return this.nodeValue === element.textContent; }).length) { 3 $(this).closest('div').after('↑彼には子供がいます'); 4 } 5});

投稿2018/08/31 01:46

x_x

総合スコア13749

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

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

skipping

2018/09/03 08:43

ありがとうございます。後学のためじっくり解読できるよう努めます。
guest

0

ベストアンサー

こんにちは。

以下のようにif条件を修正すると、いかがでしょうか?

修正前:

javascript

1if( $('.parent-num:contains('+myNum+')') ){

修正後:

javascript

1if( $('.parent-num:contains('+myNum+')').length ){

サンプル: https://jsfiddle.net/jun68ykt/txcsLd73/1/

要点としては、 $(何らかのセレクタ) に該当する要素がなくても、if の条件の中でこれを使って、if($(何らかのセレクタ)) とすると、 $(何らかのセレクタ) は true に評価されてしまって、意図した判定にはならないことです。

なので、「該当するものがある」という条件を書きたい場合は、 lengthプロパティが 0 ではないことによって判定します。

補足すると、以下のように、長さが0の配列も true として扱われます。

shell

1$ node -v 2v10.8.0 3$ node 4> Boolean([]) 5true 6> if([]) console.log('hello'); 7hello 8undefined 9>

以上、参考になれば幸いです。


追伸

こんにちは。
だいぶ時間が経ってしまいましたが、その後も機能追加などの作業が続いていらっしゃるご様子ですね。

さて、次の 1. と 2. について回答します。

  1. コードに対する指摘点
  2. getParentNums が再帰を使っていることで起こるエラーについて

1. コードに対する指摘点

https://jsfiddle.net/psn5849w/97/

を拝見して、どのようなロジックで動いているかもだいたい把握しました。その上で指摘させて頂きたい点は以下です。(1)と(2)は細かいツッコミですが、 (3)はこのままだと不具合が起こる気がする点です。

(1) childrens の末尾の s が不要

<ul class="childrens">childrens は、末尾の s が不要なので削除し children とする。

(2) 配列.indexOf(x) >= 0 の替わりに、配列.includes(x) を使う

配列に何か特定の要素が含まれるかの判定には、 indexOf ではなく、 includes を使う。

 修正前:

javascript

1if (parents.indexOf(my_post_num) >= 0){

 修正後:

javascript

1if (parents.includes(my_post_num)){

(3) 正規表現の修正

closeがクリックされたときの閉じる子要素の判定に使う正規表現の修正

 修正前:

javascript

1var child_ancestor_num = click_ancestor_num+'-'+click_post_num;

 修正後:

javascript

1var child_ancestor_num_pattern = new RegExp(`^${click_ancestor_num}-${click_post_num}(-\d+)*$`);

     として、以下のようにチェックする。

javascript

1if (ancestor_num.match(child_ancestor_num_pattern)){

修正前だと、もし child_ancestor_num がたとえば "0-111-222" で、 ancestor_num"0-10-111-2229-76"のとき、以下の判定

javascript

1"0-10-111-2229-76".match("0-111-222");

はマッチしてしまうので意図しない動作を引き起こす原因になります。修正後のように正規表現を作ることでこれを避けられます。

2. getParentNums が再帰を使っていることで起こるエラーについて

コメントが削除された場合、再帰になっているせいで「親が削除されて見つからない」→「too much recursionエラー!」になってしまうのです。

なるほどですね。おそらく このコード は、

教えて頂いたり拾ったりしたコードを一晩中切って貼ってを繰り返した

とあったとおり、力作ではあるのでしょうから、なんとかしたいお気持ちも分かります。しかし、ある投稿(post)が削除される可能性があり、これに対応しようとするとエラーになってしまったという状況は、私からすると、2018/09/01 01:22 のコメントに書いた、【パターン:あ】を使うことへの所感:

・・・・・ 直感として思うのは、
「慎重に書かないとバグのあるコードを書いてしまいそう」

に当てはまる事態であったりします。

つまり、分かり易くいえば、もし仮に、私と貴殿が同じ職場で働く同僚であったならば、
「ほらみろw だから、【パターン:あ】 は辞めとけっていったのに〜w」
と、(心の中で、そっと) disるかもしれないなあ、ということですね。

ツリーを構成する各ノードの親子関係の操作だとか、ノードの削除、移動などを自分で書くとアルゴリズムの勉強になりますし楽しかったりもするのでハマる気持ちも分かりますが、これがもし何らかの製品として本番サーバーに載せるサービスの一部であるなら、こういうツリー操作はまさにDOM操作のお家芸ですから、先達のプログラマーの成果に乗っかった方が良い気がします。(つまり、投稿の親子関係をDOMの親子関係に乗せた【パターン:い】を採用するということですね。)

さらにより賢明なのは、ツリーの基礎となるグラフ理論の初歩をかじったり、ツリーのノードを一番上から下へ、あるいは、末端のノードから上へ再帰でたどるコードを自分で書いたり、他の人のコードを読んだりして、「やろうと思えば自分で書ける」と思えるだけのプログラミング力はキープしつつ、明らかに先達の作ったコードに乗っかった方がよいときは思いっきり乗っかって楽をして、自分はもっと別の重要なコードを書く方に時間をあてる、みたいな姿勢かなと思います。

とはいえ、明らかに大変なのに、【パターン:あ】に猪突猛進した貴殿の勢い、嫌いではありません。


追伸2

  • それでも、【パターン:い】でいくのであれば、ある投稿(post)が削除されたとしても、それは、バックエンドのデータベースの投稿テーブルでレコードを物理削除しないで論理削除するだけに留めておき、画面表示上は「この投稿は削除されました」といった感じで表示される投稿として、親子関係のツリーからは消えないようにするのが、ひとつ手としてあるかなと思います。

   

  • それと、今後も 【パターン:い】でいくにしても、ツリーの情報をHTML要素の my_ancestor_num などの属性に、ハイフン区切りの文字列で持たせると何かと大変そうなので、投稿ツリーをDOMとは別の場所に、ツリーを保持したデータ構造によって、 持っておくほうがよいのでは?と(無責任な思いつきですが、)思ったりもします。

    

  • たとえば、でいうと、返信ふくめた投稿のツリー情報を XMLで返すAPIをバックエンドで用意しておき、フロントエンドでこれを呼んだレスポンスをパースした結果を親子関係のマスターデータとし、これに対して JQuery のセレクタを使って投稿の親子関係を取得して、画面HTMLのDOMに反映させる、みたいなことですね。

追伸3

いずれにせよ、ここから先は、バックエンドの投稿テーブルの作り方だったり、サーバーサイドでどこまで画面がレンダリングされてきて、どこから先をフロントエンドでやるのか? みたいな詳細に突っ込まないと正確なコメントはできなさそうです。

頑張ってください!

投稿2018/08/30 17:19

編集2018/09/24 12:06
jun68ykt

総合スコア9058

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

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

skipping

2018/08/30 19:45

かなり惜しいですね。ありがとうございます。大変参考になります。 惜しいとは、たとえば質問のHTMLからDさんを消すと、Cさんに子供はいなくなるはずですが、なのにCさんに「↑彼には子供がいます」がappendされてしまうという点です。 これは「:contains」が「完全一致」でなく「含む」である限り仕方のないことですし、実際のページではピリオドでなく番号なので「含む」が起こる可能性も相当低いと考えれば、目をつぶってもいいかもしれませんね。笑 ところで質問と別で重大な問題があり、実際のページは次のように開閉機能がつくのですが、 https://jsfiddle.net/af4v1o7u/ これだと「Eさん開く→Fさん開く→Gさん表示」の後に「Eさん閉じる」をクリックしてもFさんまでしか閉じられず、Fさんの子供であるGさんは表示されたままになってしまうという点です。Eさんを閉じたとき彼の子供以降は全て閉じたいのですが、かなり難しくなってきますね。。
jun68ykt

2018/08/30 22:52

> 惜しいとは、たとえば質問のHTMLからDさんを消すと、Cさんに子供はいなくなるはずですが、なのにCさんに「↑彼には子供がいます」がappendされてしまうという点です。 「含む」ではなく「完全一致」するものがあるかどうかを判断する場合は、一例として以下のようにすればよいかと思います。 var children = $('.parent-num').filter(function(i) { return $(this).text() == myNum; }); if( children.length ){ $(this).append('↑彼には子供がいます'); } 以下は上記のサンプルです。(Dさんを消すと、Cさんの「↑彼には子供がいます」は消えます) https://jsfiddle.net/jun68ykt/txcsLd73/24/
jun68ykt

2018/08/30 23:15

> 実際のページは次のように開閉機能がつくのですが、 https://jsfiddle.net/af4v1o7u/ 上記のほうも拝見しました。 ぱっと見て、もし私がこれを修正するとしたら、どういう方向を考えるかだけコメントしますと、このような開閉するUIを実現されたいのであれば、データとしての親子(または子孫)関係が、HTML要素の親子(または子孫)関係としてDOMに展開されるようにできないか?つまり、XさんがYさんの子である場合、Xさん情報を表示するHTML要素の子または孫要素として、Yさん情報を表示するHTML要素を持つようにして、全体を、いくつかの家系を表す複数のツリーにするような方向を考えます。 ツリーにするということでいえば、以下 jquery tree pluginの調査(alingogoさん@Qiita) https://qiita.com/alingogo/items/b49d48f1b024f6022a85 などを参考にして、欲しい機能を提供してくれるライブラリの利用も考えます。
jun68ykt

2018/08/31 00:04 編集

ちなみに、親子関係のあるデータを、見た目の上でツリー状に表示してくれるプラグインを使った場合、DOMツリーの中で、親Xさん情報を表示するHTML要素の子または孫要素として、Xさんの子Yさん情報を表示するHTML要素を展開するのかは分かりません。そこは個々のプラグインにお任せすることになります。(データ上の親子・子孫関係がDOMでの親子・子孫に反映されていることが自然な気がしますが、そうでなければならないというわけではない、という意味です)
skipping

2018/08/31 11:45

完全一致できましたね。文字列と言えば「:contains」しか発想がございませんでした。 プラグインがあるんですね。拝見させて頂きます。 家系の表示も考えてみます。方向性をありがとうございます。
skipping

2018/08/31 12:17

一気に子孫を閉じるためのツリーにする件ですが、【あ】【い】のどちらが良いと思われますでしょうか? 【パターン:あ】 <span class="parent-num">202-223-336</span> という風に、親の親をどんどんJSで追加していくパターン。 【パターン:い】 <li>親</li> <li>子</li> <li>子</li> <li>孫</li> を <li>親 <ul> <li>子</li> <li>子 <ul> <li>孫</li> </ul> </li> </ul> </li> と言う風に、JSで<ul>を作ってその中にinsartAfterなどで移動させるパターン。
skipping

2018/08/31 12:19

コメントが大量にあるため、【い】でガチャガチャリストを移動させるよりも、【あ】でポコポコ数字を追加してく方が良さそうな気はしているのですが。
jun68ykt

2018/08/31 16:15

こんにちは。 まず、私の書いた 2018/08/31 08:15 のコメントに誤字がありました。正誤は以下のとおりです。  誤:つまり、XさんがYさんの子である場合、・・・  正:つまり、XさんがYさんの親である場合、・・・
jun68ykt

2018/08/31 23:29 編集

次に、【パターン:あ】と【パターン:い】の比較についてです。    お題は「人物の関係としての親子関係のデータを反映した開閉するツリーのUIを作る」ということですが、このお題を、まったく白紙の状態から、これから作るという状況であれば、私なら【パターン:い】を選択すると思います。   理由としては、以下の2点です。 (1) 見た目の上での開く・閉じるという挙動を実現するために、   <ul> に、開いている状態と閉じている状態を表すCSSクラスを定義して、この2つをトグルで切り替えればいい。  とシンプルに考えられる。 のと、 (2) 対象とする人間関係のデータに対して何らかの処理をしたい要件が、HTMLの要素に対する処理として簡単に書けそう。 たとえば「Xさんの子孫を全員列挙する」という要件が、「Xさんの<li> ・・・</li>の中に含まれる <li> を全て取ってくる」というように、HTMLの要素に対する処理に簡単に置き換えられる。JQueryなら たとえば $(“li[myNum=’XさんのMyNumber’]”).find(‘li’) というようなコードを書きさえすれば済むだろうと予想できます。 これに対して、【パターン:あ】だと、例示されている、<span class="parent-num">202-223-336</span> に記載された、 202-223-336 のような ハイフンで区切られた番号によって、DOMツリーとは別のところから人物の親子関係を読みとり、それを開閉などのUIにうまく適用しなければならないので、直感として思うのは、 「慎重に書かないとバグのあるコードを書いてしまいそう」 ということです。 とはいえ、上記は、まったくの白紙から自分が書くとしたらどうかという判断なので、すでにこのご質問のお題に着手されているskippingさんにとっては、【パターン:あ】のほうが、楽にバグのないコードを書けそうという感触なのかもしれませんし、 > コメントが大量にあるため、 といった、ロジックの書きやすさとは別の要因で【パターン:い】を選びにくいという状況もあるようですので、いったん【パターン:あ】で進めてみるとこうことでよろしいかと思います。 以上でお役に立てる回答になっていますでしょうか? さらなるご質問があればお知らせください。
skipping

2018/08/31 16:30

(1) (2) の通りですね。かなり頭の良い方だと伝わります。 結局【あ】で進めていたところ行き詰ってしまったので、【い】で考えようと思います。番号を基点にして親の中に移動すればいいだけですからできそうです。 丁寧で親身なご返信をどうもありがとうございました。
skipping

2018/09/02 12:28 編集

こんにちは。お世話になっております。できました。のご報告です。 あれから結局ひとまず【あ】の番号連結方式で進めて、なんとか、動くようにはできました。 https://jsfiddle.net/34g1u0ce/26/ しかし、教えて頂いたり拾ったりしたコードを一晩中切って貼ってを繰り返した状態でして、無駄がヤバイのです。笑 もう少しスリムにするためのポイントなど、もしよろしければアドバイスを頂戴できませんでしょうか。
jun68ykt

2018/09/02 11:08

おお!これは力作ですね! まだざっとしか見ておりませんが、ちゃんと開閉しますね。 > アドバイス はもう少し読み込んでから後ほど(明日以降になります)いたしますが、 > 一晩中切って貼ってを繰り返した とのことで、まずは一言、お疲れ様でした、と申し上げたく思います。
skipping

2018/09/02 11:44

ありがとうございます。報わます。いつでもお時間あるときに、「ここだけどうしてもおかしい」などがございましたらぜひご指導くださいませ。それでは、どうぞ良い休日を。
skipping

2018/09/03 11:05

ご報告です。↑のひどいコードが多少マシになりました。 https://jsfiddle.net/psn5849w/97/ 今回は自分なりに納得がいったので、もう大丈夫です。 たびたびのお気遣いに心から感謝申し上げます。どうもありがとうございました。
skipping

2018/09/22 07:49

こんにちは。お世話になっております。 たびたび申し訳ございませんが… すぐ上の返信にあるJSFiddleの多少マシになったコードですが、これを「再帰ではなくする方法」などはございませんでしょうか? 再帰しているのはJSFiddleの8行目の「getParentNums」の部分です。 こちらのスライダーの親子関係はコメントの返信関係なのですが、コメントが削除された場合、再帰になっているせいで「親が削除されて見つからない」→「too much recursionエラー!」になってしまうのです。これを回避させる方法がさっぱりわからず、再度jun68yktさまを頼らせて頂ければと思いコメント致しました。 お手すきで気が向いた頃に、どうぞ宜しくお願い致します。
jun68ykt

2018/09/24 09:24

こんにちは。上記の返答を、回答のほうに追伸として書きました。何の役にも立ってないかもしれませんが、参考になればと思います。
skipping

2018/09/24 13:30

ご追伸感激です。ありがとうございます。 まず「1. コードに対する指摘点」について、 ・お里が知れて大変お恥ずかしいのですが、「childrens」は「children」の複数形かと思っておりました。笑 ・何かのきっかけで「indexOf」だけ知りどう使えばいいか悩んだ末にそうなったのですが、「includes」の方が適切ですね。それを知りたかったです。 ・番号の判定についても悩んでおりましてので、正規表現のアドバイス、大変助かります。 次に「2. getParentNums が再帰を使っていることで起こるエラーについて」ですが、disられるのはごもっともですよね。笑 言い訳しますと、WordPressの掲示板プラグイン(BBPress)を使うにあたって、階層構造が最大10階層までしか作れないという前提を覆すことができず、もうこれは番号連結で仮想の階層構造を作るしかないか…と考えた末の【パターン:あ】の選択でした。 つまり困難への猪突猛進という褒められた気概ではなく、ただの前提への盲信だったわけです。笑 また「追伸2」に書いて下さった「この投稿は削除されました」という方法についてもありがとうございます。その方法に致します。他方で「ツリーを保持したデータ構造」などを投稿の情報と一緒に保存させることができれば良さそうですが、それは私には難易度が高すぎるので見送らせてください。 最後に、時間が経った上に見ず知らず相手の件について、ここまで大人力を持ってご対応頂いたこと、とても良い人生経験になりました。深く感謝申し上げます。どうもありがとうございました。
jun68ykt

2018/09/24 14:18

どういたしまして。私も楽しかったです。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問