[HTML/CSS/Javascript]🐊🐊ユーザー入力値をもとにわにさんをプールに放つハンズオン🐊🐊[値取得/表示/DOM操作]

#目的

- ユーザーの入力値取得や表示ができるようになる。

#今日やること

- getElementByIdやaddEventListenerやinnerHTMLについて理解を深める
- CSSでマウスホバーやセレクタを正しく選択できるようにする。

#ゴールイメージ

テキストエリアに自然数をいれるとわにさんがプールに放たれる。

![ezgif.com-video-to-gif-2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665832/1e9f5d98-0fba-dc49-4337-f0ad55e56ccf.gif)


#HTML

このような感じでつくってみました。

```html:index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>わにわにわにさん</title>
    <link rel="stylesheet" href="gators.css">
</head>
<body>
    <form action="javascript:void(0)" method="post">
        <p>わにさん何匹放つ？</p>
        <input type="text" id="number">
        <input id = "id-submit" type="submit" value="Unleash gators">
    </form>
    <div>
        <p id ="gatorPool" ></p>
    </div>
    <script src="gators.js"></script>
</body>
</html>
```

##画面が一瞬消えるんだけど？（初見ホイホイ案件）

下記のようなコードの場合、submitした瞬間にaction="#"が呼ばれてしまう。

もう少し詳しくいうと、#はそのページの最上部を意味しているので、
index.htmlがリロードされ、その結果一瞬表示されるが最終的にはリフレッシュされた画面が表示される。


```html:index.html
...
   <form action="#" method="post">
        <p>わにさん何匹放つ？</p>
        <input type="text" id="number">
        <input id = "id-submit" type="submit" value="Unleash gators">
    </form>
...

```

###解決①  action="javascript:void(0)"とする　

- void 演算子は式を評価し、評価した結果必ず undefind 値を返します。
- action値に undefind 値を指定した場合には何も動作しません。

###解決② event.preventDefault()とする

ブラウザが持つデフォルトの動作をキャンセルします。

- フォーム送信して送信先のページに遷移する動作がキャンセルされます。

**でも、ブラウザのデフォルトの動作をキャンセルするなら逆に面倒かもしれない。**
この辺りの使い分けはまだわかっていません。ごめんなさい。

#Javascript

このような感じでつくってみました。

```Js:gatorPool.js

let sub = document.getElementById('id-submit')

sub.addEventListener("click", () => {
    const numberOfGators = document.getElementById('number').value;


    if (isNaN(numberOfGators)) {
        alert('数字のみを入力してください');
    }

    if(numberOfGators<=0 || Number.isInteger(numberOfGators)){
        alert('自然数で入力してください')
    }


    let addGators = "";
    for (let i = 0; i < numberOfGators; i++) {
        addGators += '🐊';
    }
    document.getElementById("gatorPool").innerHTML = addGators
})
```

<input id="submit"...>にクリックイベントが発生した際の動作を作り、その中の処理を書いていきます。

1:イベント発火させる記述を作るために、```<input id="submit"...>```を取得
2-1:イベント発火時の処理を書く：ユーザーの入力値を取得
2-2:イベント発火時の処理を書く：値を表示
2-3:イベント発火時の処理を書く：ユーザーに正しい入力値を促す

##ユーザーのイベント発火時の操作を作る。
イベント発火はこちらを使います。
**element.addEventListener(eventhadle,callback)**
>addEventListenerメソッドは、特定のイベントが対象に配信されるたびに呼び出される関数を設定します。 対象としてよくあるものは Element, Document, Window ですが、イベントに対応したあらゆるオブジェクトが対象になることができます (XMLHttpRequestなど)。引用：MDN

また、element:イベント発火するHTML要素を取得します。
eventhandle：どのイベント（ユーザーがWEB上でのクリックなどの操作）をしたときに反応するかを決めます。イベントハンドラの一覧は[こちら](https://phpjavascriptroom.com/?t=js&p=event)を参考にしてみてください。



###イベント発火するHTML要素を取得
イベントは```<input id="submit"...>```で起こるので、発火させるためにHTMLを取得します。
HTMLの取得は、**document.getElementById("")**を使います。
>Document の getElementById() メソッドは、id プロパティが指定された文字列に一致する要素を表す Element オブジェクトを返します。要素の ID は指定されていれば固有であることが求められているため、特定の要素にすばやくアクセスするには便利な方法です。引用：MDN

```js:gatorPool.js
let sub = document.getElementById('id-submit')
```

このsubを使って、クリックイベントで発火する処理を書きます。

```js:gatorPool.js
let sub = document.getElementById('id-submit')
sub.addEventListener("click", () => {
　　//この中に、clickしたときの処理を書く
}


```

####document.getElementByIdのNullの対処

####解決①　ID名は間違っていないか

指定されたIDが見つからなかった場合、Nullを返します。

####解決②　HTMLを見た時に、Jsファイルで扱うHTMLの前に、jsファイルを呼び込んでいないか

JSファイルは置かれる前までのHTML要素を探すので、
指定したIDが```<script src="gatorsPool.js"></script>```の後ろにある場合、Nullを返します。

```js:OK

    <input id = "submit">
...
    <script src="gatorsPool.js"></script> //subは<input id = "submit">

```


```js:NG

    <script src="gatorsPool.js"></script> //subがNull
...
    <input id = "submit">

　
```

###イベント発火時の処理を書く

####ユーザー入力値の取得
クリックで発火する関数は作れたので、発火時の処理を書いていきましょう。

ユーザー入力値を取得するには、こちらを使います。
**document.getElementById('id').value**

```js:gatorPool.js
let sub = document.getElementById('id-submit')
sub.addEventListener("click", () => {
　 const numberOfGators = document.getElementById('number').value;
}


```

入力値によってわにを放つ数を変更したいので、入力値に応じたわにの文字列を作ります。


```js:gatorPool.js
let sub = document.getElementById('id-submit')
sub.addEventListener("click", () => {
　 const numberOfGators = document.getElementById('number').value;
　  let addGators = "";
    for (let i = 0; i < numberOfGators; i++) {
        addGators += '🐊';
    }
}


```

####値を出力する

値をHTMLに出力するには、こちらを使います。
**element.innerHTML**
こちらもgetElementByIdと同様に、書き換えたいHTML要素が必要なので取得して貼り付けます。
今回は、subのように分割せずに、document.getElementByIdで取得したHTML要素をinnerHTMLに渡しています。

```js:gatorPool.js
let sub = document.getElementById('id-submit')

sub.addEventListener("click", () => {
    const numberOfGators = document.getElementById('number').value;
    let addGators = "";
    for (let i = 0; i < numberOfGators; i++) {
        addGators += '🐊';
    }
    document.getElementById("gatorPool").innerHTML = addGators
})

```

####ユーザに正しい入力を促す

残りは、正しい入力を促すための条件分岐を記載します。
０以下、英文字は弾けますが、小数点に対応できていません🙇‍♂️


```js:gatorPool.js
let sub = document.getElementById('id-submit')
sub.addEventListener("click", () => {
    const numberOfGators = document.getElementById('number').value;


    if (isNaN(numberOfGators)) {
        alert('数字のみを入力してください');
    }

    if(numberOfGators<=0 || Number.isInteger(numberOfGators)){
        alert('自然数で入力してください')
    }


    let addGators = "";
    for (let i = 0; i < numberOfGators; i++) {
        addGators += '🐊';
    }
    document.getElementById("gatorPool").innerHTML = addGators
})
```

おつかれさまです！
Javascriptはこちらで終了です。

##@vf8974　さまによりスマートな書き方を教えてきただきました！


###①ページ遷移しない場合は、inputではなく、buttonを使うとGOOD

```js:変更前
  <form action="javascript:void(0)" method="post">
        <p>わにさん何匹放つ？</p>
        <input type="text" id="number">
        <input id = "id-submit" type="submit" value="Unleash gators">
    </form>

```

```js:変更後
  <form>
        <p>わにさん何匹放つ？</p>
        <input type="text" id="number">
        <input id = "id-submit" type="button" value="Unleash gators">
    </form>
```

###②文字列の繰り返し処理は、 str.repeat(count)が便利！

```js:変更前
  let addGators = "";
    for (let i = 0; i < numberOfGators; i++) {
        addGators += '🐊';
    }
```

```js:変更後
    const addGators = '🐊'.repeat(numberOfGators);
```

おおー✨とてもシンプルで可読性が高いです！


##CSS

マウスを置いた際に表示を変えたい場合、```:hover```を使います。

```css:gatorPool.css
form {
    /* display: flex; */
    font-family:"游ゴシック","YuGothic";
    margin: 0 auto;
    background-color:#6FB98F;
    width: 200px;
    height:200px;
    text-align: center;
    border-radius: 4px;
}

p{
    padding:25px;
}

input{
    font-family:"游ゴシック","YuGothic";
    background-color:seashell;
    margin: 10px 0;
    border-bottom: solid 4px  salmon;
    border-right: solid 4px  sandybrown;
    border-radius: 4px;
}

input#id-submit:hover{
    font-family:"游ゴシック","YuGothic";
    background-color:snow;
    border-right:none; 
    border-bottom: none;
    transform: translate3d(0, 3px, 0);
    border-radius: 4px;
}


div {
    margin: 0 auto;
    background-color:cornflowerblue;
    width: 300px;
    border-radius: 4px;
}
```


#Tips　背景色を角丸にしてフォントを変えるとそれだけで画面にまとまりがでる気がします。

背景色角丸、フォント変更後

<img width="470" alt="Screen Shot 2020-07-22 at 11.31.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665832/3b46c8f2-ad61-ba04-6ffe-5e51ae83cf1c.png">


変更前
<img width="479" alt="Screen Shot 2020-07-22 at 11.32.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665832/9f4d48e5-50ac-d695-2734-cdedce8fafc3.png">