javascript　基本その3 HTML呼出とイベント

本日もjavascriptについて書き込みこみます。
今日はHTMLを指定して画面上の表示を帰る方法です。


# DOM
DOMとはDocument Object Model(ドキュメントオブジェクトモデル)の略です。
HTMLを解析し、データを作成する仕組みです。

ユーザーが画面をみる仕組みは

1,HTMLを解析、DOM(WEBページ)に変換
2,CSS,javascriptを読み込み装飾
3,ユーザーが画面をみる。

という工程です。
要はCSSのように装飾を担当するのがjavascriptの役目です。

HTMLは階層構造になっていることが特徴です。
DOMによって解析されたHTMLは、階層構造のあるデータとなります。
これを、DOMツリーやドキュメントツリーと呼びます。

## DOMツリー
基本的に各タグがネスト(入れ子構造になっていて)
ツリーのようになっている感覚です。

body
|
--header--p
    |
    --main--p
    |
    --footer--p

簡単に書くとこのようになります。

# ノード
HTML1つ1つのタグが、DOMツリーの中ではノードと呼ばれます。

例として
body,header,fooder,main,など

下記にHTMLの取得方法について紹介します。

## document
documentは、開いているWebページのDOMツリーが入っているオブジェクトです。
documentに対していくつかのメソッドを利用することで
DOMツリーに含まれる要素を抽出して取得することができます。

大文字小文字
単数形、複数形に注意してください。

## ID要素取得
document.getElementById("id名");

.getElementById("id名")はDOMツリーから特定の要素を取得するためのメソッドの1つです。
引数に渡したidを持つ要素を取得します。

```js:IDの場合
document.getElementById("id名");
```
## Class要素取得
document.getElementsByClassName("class名");

classを指定して取得する際はこちらを利用します。
ここで気をつけたいのは
getElementsと複数形になっていることです。

id名はhtml上に必ず一つしか存在しないのに対して
class名を指定するgetElementsByClassName("class名")の場合は
同じclassを持つ要素を全て取得することが可能です。

```js:クラスの場合
document.getElementsByClassName("クラス名");
```

## セレクタ要素取得
document.querySelector("セレクタ名");

セレクタ名とは、CSSでスタイルを適用するために指定している要素です。
セレクタ名を指定してDOMを取得する場合
querySelectorメソッドを使用します。

HTML上から、引数で指定したセレクタに合致するもののうち一番最初に見つかった要素1つを取得します。

```js:セレクタの場合
document.querySelector("セレクタ名");
```

```css:セレクタの例
p.menu{  /*p.menuがセレクタにあたります*/
color:red
}
```

querySelectorメソッドでは、複雑なセレクタも指定できます。

```js:複雑な例
document.querySelector("button#Button2"); // idがButton2のbuttonタグ要素
document.querySelector("footer a.next"); // footerタグ要素の中の、クラスがnextのaタグ要素
```

# イベント
JavaScriptにおけるイベントとは、HTMLの要素に対して行われた処理要求のことをいいます。
例えば

* 「ユーザーがブラウザ上のボタンをクリックした」
* 「テキストフィールドでキー入力をした」
* 「要素の上にマウスカーソルを乗せた」

などがいずれもイベントです。

また、イベントを起こすのはユーザーだけでなく

* 「ドキュメントの読み込みが終わった」

などブラウザが発生させるものもあります。

## イベント駆動
JavaScriptはイベント駆動という概念に基づいて設計されています。
これは、「イベント」が発生したら、それをきっかけにコードが実行される仕組みです。

イベントを取得するためには、先に取得したノードに対して処理を書きます。

## addEventListener
addEventListenerメソッドはノードオブジェクトのメソッドです。

この記述の読み込み以降で「ノードオブジェクト」に「イベント」が起きた時
「関数」を実行するようになります。

一つのイベントと一つの関数を紐付ける仕組みのことを

イベントリスナと呼びます。

一つのイベントに複数の関数を紐付ける場合は、関数の数だけイベントリスナが存在します。

```js:addEventListenerメソッド
(ノードオブジェクト).addEventListener("イベント名", 関数);
```

上記よりコードを書いていくと下記のようになりますが。
これ単体だとnullというエラーがおきます。

```js:基本使用方法の間違い
let btn = document.querySelector("button");
// ボタンをノードオブジェクトとして取得し、変数btnに代入する

function printHello() {
  console.log("Hello world");
}
// printHello関数を定義

btn.addEventListener("click", printHello);
// ボタンのノードオブジェクトであるbtnに対して、
// clickイベントとprintHello関数を紐付ける仕組みであるイベントリスナを追加する
```

ブラウザは上から順に実行をするので、このJavaScriptのコードを読み込む時
まだhtmlファイルのheadタグ内までしか読み込まれておらず

bodyタグ内にあるbuttonタグは読み込まれていなかったのです。

```html:基本HTMLコード
<head>

<script ~ ></script>
<!--ここまでしか読み混まれないのでbuttonタグまで到達せずエラーが起きます。-->

</head>

<body>

<button ~ >< /button >
<!--ここまで読み込みたい-->

<body>
```

これを解決するため全て読み込んでから実行する
下記のような実行が必要です。

### ページの読み込みをするwindow.onloadを使おう。
ページの読み込みは、以下2つの記述方法があります。

```js:その1,onload
window.onload = function() { 処理 };
```

```js:その2,addEventListener
window.addEventListener('load', function() { 処理 });
```
その2を踏まえてコードを書いていくと

```js:基本使用方法の正解
function printHelloWithButton() {
  let btn = document.querySelector("button");

  function printHello() {
    console.log("Hello world");
  }
  // 関数内で定義された関数は、関数の中でしか呼び出せない性質があるだけで、
  // 通常の関数同様に呼び出せる

  btn.addEventListener("click", printHello);
}
// 一連の処理をまとめた関数を作る

window.addEventListener("load", printHelloWithButton);
```

# コードの改善
今まで書いたことは三つの改善方法があるので書いて行きます。

先に結論だけ行って仕舞えば
addEventListenerの第二引数にfunctionを持ってくるポイントと
考えてください。

## 第二引数に置換

```js:改善前
function func() {}
// 何もしないfunc関数

btn.addEventListener("click", func);
```

第二引数に内容をそのまま写して

```js:改善後1
btn.addEventListener("click", function func() {});
```

## 関数名の省略

第二引数に置かれたため、関数名を省略することができます。

```js:改善後2
btn.addEventListener("click", function() {});
```

## コードを複数行書く
処理がある場合（殆どの場合）は一般に改行を用いて以下のように書きます。

```js:改善後3
btn.addEventListener("click", function() {
  // 処理
});
```

## 上三つを踏まえた改善例

```js:sample改善前
window.addEventListener("load", function() {
  let btn = document.querySelector("button"); //処理1 ノード取り出し変数宣言

  function printHello() {      //処理2 関数宣言
    console.log("Hello world");
  }

  btn.addEventListener("click", printHello); //処理3 イベントリスナ
});
```

```js:sampleの改善後
window.addEventListener("load", function() {
  let btn = document.querySelector("button"); //処理1 ノード取り出し変数宣言

  btn.addEventListener("click", function() { //処理2 + 処理3
    console.log("Hello world");
  });
});
```
# 格HTMLの処理方法

## HTML要素の中身を書き換え
innerHTML
innerHTMLを使用するとHTML要素の中身を書き換えることができます。

```js:書換例
// テキストの要素を取得し、変数で定義
let btn = document.querySelector("#Button");
let changeText = document.querySelector("p");

// ボタン2をクリックしたらテキストが置換される
btn.addEventListener("click", function() {
  changeText.innerHTML = '変更されました';
});
```

## クラス追加
classList.add
クラス追加するメソッドです。

```js:クラス追加
// Button3を取得して、変数で定義
let btn3 = document.querySelector("#Button3");

// クラス追加を押したらredクラスが追加される
btn3.addEventListener("click", function() {
  changeText.classList.add("red");
  console.log(changeText.classList); // ここに追加
});
```
## クラス削除
classList.remove
クラス削除するメソッドです。

```js:クラス削除
// Button4を取得して、変数で定義
let btn4 = document.querySelector("#Button4");

// div要素を取得して、変数で定義
let obj = document.querySelector("div");

// クラス削除を押したらblueクラスが削除される
btn4.addEventListener("click", function() {
  obj.classList.remove("blue");
});
```

## 小まとめ

```js:まとめ
window.addEventListener("load", function() {
  let btn = document.querySelector("button#Button");

  btn.addEventListener("click", function() {
    console.log("Hello world");
  });

  // テキストの要素を取得し、変数で定義
  let btn2 = document.querySelector("button#Button2");
  let changeText = document.querySelector("p");

  // ボタン2をクリックしたらテキストが置換される
  btn2.addEventListener("click", function() {
    changeText.innerHTML = '変更されました';
  });

  // Button3を取得して、変数で定義
  let btn3 = document.querySelector("#Button3");

  // クラス追加を押したらredクラスが追加される
  btn3.addEventListener("click", function() {
    changeText.classList.add("red");
  });

  // Button4を取得して、変数で定義
  let btn4 = document.querySelector("#Button4");
  // div要素を取得して、変数で定義
  let obj = document.querySelector("div");

  // クラス削除を押したらblueクラスが削除される
  btn4.addEventListener("click", function() {
    obj.classList.remove("blue");
  });
});
```