inputタグのスライダーについて

今回は、HTMLの「form」タグ等でたまに使用する、
「input」タグについてやっていきたいと思います。
それではまずはHTMLに記述していきます。

_HTMLコード_
```
<body>
  <input type="range">
</body>
```
![１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521240/eb83981b-4df0-34f7-88ad-45fda928f455.png)
HTMLに「input」タグを、typeには「range」を入れることで、
上記画像のようなユーザー側で動かすスライダーが出現しました。

このスライダーに対して

_CSSコード_
```
input{
  width: 400px;
}
```
![２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521240/4aef37f5-4462-9413-d7d4-f435ccede8a8.png)
幅をCSSで設定すると、画像のようにスライダーが横に長くなります。

HTML内で設定できるものは、「input」タグ内の属性で記述します。

_HTMLコード_
```
<body>
  <input type="range" min="#" max="#" step="#" value="#">
</body>
```
属性はこのように記述します。属性の意味はそれぞれ

「min」→「最小値」
（スライダーを左端に移動させた時の値）
「max」→「最大値」
（スライダーを右端に移動させた時の値）
「step」→「移動幅」
（スライダーを移動させた時の移動単位（最小値「0」、最大値「10」で移動幅を「2」に設定した時、スライダーは5段階に分けて「2」ずつ値が変化していく））
「value」→「初期値」
（ブラウザを表示させた時の最初の状態での値）

という意味で、属性を設定していないデフォルトの状態ではそれぞれ

「min」→「0」
「max」→「100」
「step」→「1」
「value」→「50」

となっており、上記コード内の「＃」の値を変更することでそれぞれ属性値を変更することができます。
例えば「value」を「0」にすると
![３.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521240/7fbb865b-1d98-8e17-e115-7d1e3389b42b.png)
このように初期値が一番左にいきました。
これは、左端の値が「0」、右端の値が「100」のスライダーで初期値が「0」と設定したため、
このようになったということです。

このスライダーの値というのは何も設定しなければブラウザ上で表示することができず、
「input」タグのtypeが「submit」のもの等で活用することができます。

次はこのスライダーの値を表示していきます。
この値を表示するためにはJavaScriptを使います。

_HTMLコード_
```
<body>
  <input type="range" min="1" max="10" step="1" value="1" id="iptJS">
  <span id="valueJS">1</span>
</body>
```
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521240/520bf0ec-8278-2174-accb-bebb57bb554e.png)
まずJSを使用する事前準備として、「input」タグに対してJSで使用する「id」を設定し、
JSで値を表示させるので、表示させる土台として「span」タグを記述します。
この時の「span」タグには「input」タグの「value」属性の値を書いておきます。
すると４画像のようになりました。
この出現した数値は今はただの不可変の数値なのでスライダーをいくら動かしても変化しませんが、
この数値「span」とスライダー「input」をJSで連動させて、数値を変更していくということをやります。
それではコードを記述していきますが、今回は短いコードなのでHTMLの「script」タグ内で記述していきます。

_HTMLコード_
```
<body>

  <input type="range" min="1" max="10" step="1" value="1" id="iptJS">
  <span id="valueJS">1</span>
  
  <script>
    let ipt=document.getElementById("iptJS"); //1
    let spn=document.getElementById("spnJS"); //2
    let rangeValue=function(ipt,spn){         
      return function(){                      
        spn.innerHTML=ipt.value;              //3
      }
    }
    ipt.addEventListener("input",rangeValue(ipt,spn));  //4
    </script>

</body>
```
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521240/fb0afe86-4a08-8607-96ba-12fc29bf477b.png)
こんな感じでコードを記述し、スライダーの値により数値を変更しています。
JS部分を上から説明していくと、
１、idが「iptJS」である「input」を取得し、変数「ipt」へ代入。
２、idが「spnJS」である「span」を取得し、変数「spn」へ代入。
３、関数「rangeValue」を作成し、引数も設定、「spn.innerHTML」により「span」タグ内の文字を、「ipt.value」により「input」タグの値に変更、その変更した値を戻り値として設定。
４、「ipt」要素に対して「addEventListener」を使用し、inputイベント（「input」「select」「textarea」の各要素の「value」が変更されたとき）で「rangeValue」関数を行うよう設定。

この記述を一回書くと、次からは「rangeValue」は使い回せるので、

_HTMLコード_
```
<body>

  <input type="range" min="1" max="10" step="1" value="1" id="iptJS">
  <span id="spnJS">1</span>

  <input type="range" min="1" max="10" step="1" value="1" id="iptJS2">
  <span id="spnJS2">1</span>　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　//追加
  
  <script>
    let ipt=document.getElementById("iptJS");
    let spn=document.getElementById("spnJS");
    let rangeValue=function(ipt,spn){
      return function(){
        spn.innerHTML=ipt.value;
      }
    }
    ipt.addEventListener("input",rangeValue(ipt,spn));

    let ipt2=document.getElementById("iptJS2");            //追加
    let spn2=document.getElementById("spnJS2");            //追加
    ipt2.addEventListener("input",rangeValue(ipt2,spn2));  //追加
    </script>

</body>
```
![スクリーンショット 2022-04-22 16.48.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521240/e9294c87-9791-3e9d-dfd0-1f4aa5ca5e53.png)
この追加記述のように、新しく「input」タグでスライダーを作成しても、JavaScript側は関数を使い回して使用することができます。

ですがこのスライダーが10個も20個もあったらJavascriptの行が30行にも60行にもなります。
そこでfor文を使用して１つのコードブロックで全てのスライダーに適用できるようにしていきます。

_HTMLコード_
```
<body>
  <div class="rangeGroup">   //1
    <input type="range" min="1" max="10" step="1" value="1" id="iptJS">
    <span id="spnJS">1</span>
  </div>
  <div class="rangeGroup">   //1
    <input type="range" min="1" max="10" step="1" value="1" id="iptJS2">
    <span id="spnJS2">1</span>
  </div>
  <div class="rangeGroup">   //1
    <input type="range" min="1" max="10" step="1" value="1" id="iptJS3">
    <span id="spnJS3">1</span>
  </div>
  
  <script>

    let rangeValue=function(ipt,spn){
      return function(){
        spn.innerHTML=ipt.value;
      }
    }   //2
    let rangeG=document.getElementsByClassName("rangeGroup");   //3
    for(let i=0;i<rangeG.length;i++){   //4
      var ipt=rangeG[i].getElementsByTagName("input")[0];   //5
      var spn=rangeG[i].getElementsByTagName("span")[0];   //6
      ipt.addEventListener("input",rangeValue(ipt,spn))   //7
    }

    </script>

</body>
```
![スクリーンショット 2022-04-22 17.03.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521240/01aca313-342d-77a7-4a17-71ce4a97f1a6.png)
１、まず今まで作成してきた「input」「span」を１つのまとまりとして「div」で囲い、「rangeGroup」とクラス名をつけます。（今回は３つスライダーを設置しています。）
２、前回作成したような、「span」タグの文字列に対して文字を変更する関数を作成。この引数「ipt」には「input」タグの情報、「spn」には「span」タグの情報がそれぞれ入るようになります。
３、次に先ほどクラス名を付与した「rangeGroup」を取得、変数「rangeG」に代入します。
４、ここでfor文を作成、「i」の数は「rangeGroup」クラス数とします。（今回クラス数は３つ）
５、クラス「rangeG」（インデックス番号に[i]を追加することで、for文により0から指定の数まで繰り返す）に対し、「getElementsByTagName」により「input」タグを取得（("input")[0]とすることでクラス「rangeG」内の最初の「input」を取得という意味になる）、それを変数「ipt」に代入します。
６、クラス「rangeG」に対し、「getElementsByTagName」により「span」タグを取得、それを変数「spn」に代入します。
７、変数「ipt」に対して「addEventListener」を使用し、inputイベントで「rangeValue」関数を行うよう設定。この文をfor文内に入れてしまうことでクラス数だけイベント処理が繰り返され、この時の「rangeValue」関数の受け渡し変数は「ipt」と「spn」にすることで、ただ繰り返すだけではなくクラス「rangeG」を記述の上から１つずつ適用していくことになります。

このように記述することで上記画像のように、１つのコードブロックで全てのスライダーに適用することができました。
ちなみになぜ今回はスライダーが横並びではなく縦並びになっているかというと、
前回の横並び状態の時は、「input」タグも「span」タグもインライン要素であり、今回囲っている「div」タグはブロック要素であるため、このような違いになります。

今回はここまでです。
ご購読ありがとうございました！