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

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

ただいまの
回答率

87.49%

【JavaScript】inputに入力されたテキストと一致しないp要素を非表示にする方法

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,583

score 20

閲覧ありがとうございます。

▼質問
初めてinputへ入力した時に限らず、
入力したものを全て消した後の書き直しなども含め
inputに入力するたび、発火させる方法

▼最終的につくりたいもの
「りんご」「りんごかな」「みかん」「パイナップル」といったp要素があり、
inputに「りんご」と入力された場合、
完全に一致、もしくは部分一致の「りんご」「りんごかな」は表示したままに、
それ以外の「みかん」「パイナップル」には、クラスhiddenを付け非表示にする。

▼問題点
現段階では、実現できているように見えますが、
「りんご」とinputに入力した後、
入力したテキストを一旦全て消し、
新たに「みかん」と打つと、
全く動作しなくなっている状況です。

▼コード
CodePen

参考サイト
javascriptで文字列内に任意の文字列が含まれているかをtrue/falseで返す

▼▼▼以下は、過去のコードと質問です▼▼▼

【2018/09/24のコード】

 <body>
 <div id="container">
[String.indexOfメソッド](https://algorithm.joho.info/programming/javascript/string-partial-match-js/)で文字列の部分一致を判定しようとしていますが、
その箇所が上手くいっていません。
   <form action="#">
     <input type="text" id="inputText" placeholder="文字を入力してください" onkeyup="addValue()">
     <input type="button" value="検索">
   </form>
   <div id="inputTextPv"></div>
   <div id="parent">
     <p>りんご</p>
     <p>みかん</p>
     <p>みかん</p>
     <p>りんご</p>
     <p>りんご</p>
     <p>パイナップル</p>
   </div>
 </div>
 <script>
   // リアルタイムで入力された文字列を取得
   function addValue(){
     var idname = "inputText";
     s = document.getElementById(idname).value;
     var pvname = idname + "Pv";
     document.getElementById(pvname).innerHTML = s;
   }
   // 比較するp要素を取得
   var parent = document.getElementById('parent');
   var child = parent.children;
   console.log(child);
   // 比較するp要素の文字列を取得 ※できない
   console.log(child.textContents); //undefind
   console.log(child.innerHTML); //undefind
   // 入力された文字列とp要素の文字列を比較する ※できない
   var result = child.search(search);
   console.log(result);
 </script>
</body>
/* container */
#container {
 width: 520px;
 margin: 100px auto;
}
/* form */
form {
 font-size: 0;
}
input {
 font-size: 1.4rem;
 appearance: none;
 height: 48px;
}
input:focus {
 outline: none;
}
input[type="text"] {
 width: 400px;
 padding: 0 10px;
}
input[type="submit"] {
 width: 80px;
 border: none;
}
input[type="submit"]:hover {
 opacity: 0.5;
}
/* リアルタイムで入力された文字を表示してみるエリア */
#inputTextPv {
 border: 1px solid red;
 height: 48px;
 line-height: 48px;
 padding: 0 10px;
}
/* p要素のエリア */
#parent {
 border: 1px solid blue;
 padding: 0 10px;
}


【2018/09/24の修正に関する質問】

【実現したいこと】
ページ内検索で、検索した文字を含むp要素のみを表示し、それ以外のp要素は非表示にしたいです。
また、「検索」のボタンを押さずとも、入力した時点ですでに上記の状態となるようにしたいです。
※なるべくjQueryは使わず、ネイティブJSで作れると嬉しいです。
【現状】
●できていること
・検索のテキストボックスに入力された文字の取得
・p要素の取得
●できていないこと
・p要素の文字列の取得(これができないと、入力された文字列との比較は不可能?)
p要素の文字列を取得できそうに思える、.textContents と .innerHTML を試しましたが、どちらもundefindでした。他の方法も探したのですが、見つけることができませんでした。
・入力された文字列と、p要素の文字列の比較
p要素の文字列が取得できていないので、この段階まで辿り着けていないのですが、search を使うと検索をして一致した位置を「数値」で返してくれるとのことなので、その数値を使ってp要素の表示/非表示を切り替えられるのではないかと考えています。
・該当p要素の表示と、それ以外のp要素の非表示
display: block / none; でできるのではないかと考えています。


【2018/12/01のコード】

<body>
<div id="container">

<form action="#">
 <input type="text" id="inputText" placeholder="文字を入力してください">
 <input type="button" value="検索">
</form>
<div id="inputTextPv" class="inputTextPv"></div>

   <div id="parent">
     <p>りんご</p>
     <p>みかん</p>
     <p>みかん</p>
     <p>りんご</p>
     <p>りんご</p>
     <p>パイナップル</p>
   </div>

 </div>
<script>
 (function () {
   // parentのテキストたちを取得
   const parent = document.getElementById('parent');
   const children = parent.children;
   for (var child = 0; child < children.length; child++) {
     // console.log(children[ child ].textContent);
     child.dataset.value = children[ child ].textContent;
   }
   // inputに入力されたテキストをリアルタイムで取得
   function addValue(e) {
     var inputText = document.getElementById("inputText");
     inputText.addEventListener('keyup', function () {
       var s = inputText.value;
       document.getElementById("inputTextPv").textContent = s;
     }, false);
   }
   // inputに入力されたテキストのdata-value属性に設定された値を検索
   function searchText(text) {
     return document.querySelectorAll(`[data-value="${text}"]`);
   }
   function getList() {
     const e = document.getElementById('inputText').addEventListener('input');
     addValue();
     const nodeList = searchText(e.target.value);
     // inputに入力されたテキストと同じテキストを持つparent内のp要素をConsoleに表示
     console.log(nodeList);
   }
 })();
</script>
</body>


【2018/12/01の修正に関する質問】

●parentのテキストたちを取得 について
ループでdata-value属性に自身のもつテキストノードの値を入れています。
IE11でも動作させたかったのでfor文を用いましたが、「value」に関してエラーが出ておりJSが動かない状態です。
どうすれば良いでしょうか?
エラー文:Uncaught TypeError: Cannot set property 'value' of undefined

●searchText について

function searchText(text) {


とありますが、この(text)は何を示しているのでしょうか?
この()は宣言した変数を入れる場所であると思っていたのですが、宣言していない何かも入れることが可能なのでしょうか?
また、

return document.querySelectorAll(`[data-value="${text}"]`);


の箇所でテンプレートリテラルを使用しておりますが、
このテンプレートリテラルを用いたdata-value属性を表す書き方を調べても、
同じ書き方が見つかりませんでした。
何かこのようなdata-value属性の書き方の、名称などはありますでしょうか?

●getList について
いただきましたアドバイスでは、アロー関数を使用されていましたが
よく分からなかったのでアロー関数ではない普通の書き方?にしてみました。
正しく書き換えられていますでしょうか?

●最後の行「 })();」 について
この行も、前述した「value」に関してのエラーの対象行のようです。
「JavaScriptは全体を即時関数で囲いつつ、
use strictキーワードで厳密なエラーチェックをすることが推奨されている。」
と知ったので、それも盛り込もうとしていますが、そのせいでしょうか?
こちらのエラーを解消するにはどうすれば良いでしょうか?

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • spookybird

    2018/09/30 09:28

    回答はついているんですが、なにか不満がありますか?

    キャンセル

  • _shizu

    2018/09/30 12:43

    大変申し訳ございません。 JSの基礎であるNodeの概念やその他専門用語あたりで盛大につまづいておりまして…。 大変恐れ入りますが、もう少し私の方で基礎から勉強し直して、お二人にいただきました回答をもとに、再度挑戦したいと思います。 JSというものは、様々なことが行われているのだと学ぶことができました!ご回答ありがとうございました!

    キャンセル

  • spookybird

    2018/09/30 20:33

    補足しておきますが、JSの基礎はNodeではありません。JavaScriptがあって、それをブラウザではない環境でも動かそうとしたのがNode.jsです。ブラウザで動かすJSを学ぶのにNodeの知識は一切不要です。

    キャンセル

  • _shizu

    2018/10/05 21:36

    Node.jsというものがあるのですね!わたしはこちらの「ノード」のをことを指していました。紛らわしくてすみませんっ!!! https://qiita.com/KDE_SPACE/items/e21bb31dd4d9c162c4a6

    キャンセル

回答 5

+3

.childrenが返すのはHTMLcollectionなので、配列で返されているはずです。
forなどでcollectionのlengthでループさせてひとつひとつ取り出すと良いです。
↑リンク先はリファレンスです。forで回すサンプルコードもあるので参考にしてください

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

テキストノードのままだと扱いづらいので、こんなことやってみると簡単に扱えると思います。

<script>
  (function() {
    const parent = document.getElementById('parent');
    // ここで取得できるのは parent 要素に含まれる子要素の「Nodeリスト」
    const children = parent.children;

    // Nodeリストをループするなら for...of が簡単
    // ただしIE11では動作しない
    for (let child of children) {
      // テキストノードのままだと扱いにくいので、いったん data-value 属性に自身のもつテキストノードの値を入れる
      child.dataset.value = child.textContent;
    }

    // リアルタイムで入力された文字列を取得
    function addValue(){
      const idname = "inputText";
      s = document.getElementById(idname).value;
      const pvname = idname + "Pv";
      document.getElementById(pvname).innerHTML = s;
    }

    // 受け取った文字列で data-value 属性に設定された値を検索
    function searchText(text) {
      return document.querySelectorAll(`[data-value="${text}"]`);
    }

    document.getElementById('inputText').addEventListener('input', e => {
      addValue();
      const nodeList = searchText(e.target.value);
      // ご所望のpタグのリストが取れてるはずです
      console.log(nodeList);
    });

  })();
</script>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

parentのテキストたちを取得 について

childは数値ですよ。

searchText について

仮引数です。
引数 - Wikipedia
属性セレクタです。
属性セレクター - CSS: カスケーディングスタイルシート | MDN

getList について

ダメだと思います。
e=>{}function(e){}です。

最後の行「 })();」 について

文法上の問題はないようです。
どのようなことについてお悩みですか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/09 18:53 編集

    ご回答ありがとうございます。

    最後の行に関しましては、parentのテキストたちを取得 について出ていたエラーを修正しましたら、
    最後の行に出ていたエラーも一緒に消えました。
    「childは数値」というご指摘が参考になりました。
    ありがとうございました!

    キャンセル

+1

変数名が、parentchildだと頭がこんがらがりそうですが、質問のコードにある変数名はそのままにしてあります。

  <script>
  // リアルタイムで入力された文字列を取得
  function addValue(){
    var idname = "inputText";
    searchText = document.getElementById(idname).value;
    // グローバルの配列 textArray から searchText と同じ文字列の場合のみ抽出して新たな配列 newArray に入れていく
    var newArray = textArray.filter(function(value){
      return value === searchText;
    });

    if(newArray.length!=0){//newArrayに中身があった場合の処理
      //いったん parentの中身を全て消す処理
      while (parent.firstChild) {//parentのfirstChildが存在すれば
        parent.removeChild(parent.firstChild);//parentのfirstChildを消す
      }
      //newArrayの中身の数だけ繰り返しながら 新しく p要素を追加
      for(var i = 0, len = newArray.length; i < len; ++i){
        var element = document.createElement('p');// 新しいp要素を作る
        element.innerText = newArray[i];//新しいpにテキストを入れる
        parent.appendChild(element);//parentに要素として追加
      }
    }
  }
  // 比較するp要素を取得
  var parent = document.getElementById('parent');
  var child = parent.getElementsByTagName('p');
  // p要素のinnerTextだけの配列を作る
  var textArray =[];
  for(var i = 0, len = child.length; i < len; ++i){
    textArray[i] = child[i].innerText;
  }
  </script>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/09 18:58 編集

    ご回答ありがとうございます。

    このようなやり方もあるのですね!
    勉強になります。
    ありがとうございます。

    キャンセル

check解決した方法

0

皆様、ご助言誠にありがとうございました。
以下のコードで実現できました。
(showクラスを外し忘れていただけでした)
皆様から教えていただいたやり方も、
少しずつ理解して行きたいと思います。

▼コード
CodePen

<div id="container">

  <form id="form" action="#">
    <input type="text" id="inputText" placeholder="文字を入力してください">
    <input type="button" value="検索">
  </form>

  <div id="wrapper">
    <p>りんご</p>
    <p>りんごかな</p>
    <p>みかん</p>
    <p>みかん</p>
    <p>りんご</p>
    <p>りんご</p>
    <p>パイナップル</p>
  </div>

</div>
.hidden {
  display: none;
}
  (function () {

  'use strict';

  inputText.addEventListener('keyup', function () {

    var s = inputText.value;
    console.log(s);

    const wrapper = document.getElementById('wrapper');
    const p = wrapper.children;

    for (var i = 0; i < p.length; i++) {
      p[i].classList.toggle("hidden", p[i].textContent.indexOf(s) === -1 );
    }
  }, false);

})();

参考サイト
Element.classList | MDN(条件によるクラスの追加または除去方法)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る