JSでスタイル操作,フォーム処理

##スタイルの操作

* class名の変更（className, classList）
* styleのプロパティ変更
* スタイルシートそのものを入れ替え


####1. className

```js:js
const foo = document.getElementById('foo');
foo.className = 'is-class';
//クラス名を付与
```

####2. classList

```js:js
const foo = document.getElementById('foo');
//クラス名を付与
foo.classList.add('is-class');

//クラス名を着脱
foo.classList.toggle('is-class');
```

####3. プロパティを変更（styleを利用）

```js:js
const foo = document.getElementById('foo');
//色を変更
foo.style.color = 'white';
```

####4. スタイルシートを変更
* disabled属性を利用し、input要素が変化したときに切り替えるようにする。

```html:html
<!doctype html>
<html lang="ja">
<head>
  <link rel="stylesheet" href="./style-a.css" id="style-a" disabled="true">
  <link rel="stylesheet" href="./style-b.css" id="style-b" disabled="true">
</head>
<body>
  <div id="foo">hello world</div>
  <input type="checkbox" onchange="change('style-a', this.checked)">
  <input type="checkbox" onchange="change('style-b', this.checked)">
  <script>
    function change(id, flag) {
      document.getElementById(id).disabled = !flag;
    };
  </script>
</body>
</html>
```

###位置の取得

* スクリーン座標・・・ディスプレイの座標。ほぼ使わない。
* ウィンドウ座標・・・ブラウザの表示領域。ページ途中でも見えている部分のTOpが０。clientX,clientY。
* ドキュメント座標・・・ドキュメント全体の位置。pageX,pageY。headerのtopが0。
* Element.getBoundingClientRect()・・・要素の相対位置を取得する。

#####ウィンドウ座標

```js:js
window.onload=function(){
  document.body.addEventListener("click", function(e){
  //座標を取得する
  let X = e.pageX;  //X座標
  let Y = e.pageY;  //Y座標
  console.log(X, Y);
  });
}
```

#####相対座標

```js:js
window.onload = function() {
  var element = document.getElementById('foo');
  var rect = element.getBoundingClientRect();
  console.log(rect.left);   // x座標(絶対座標)
  console.log(rect.top);    // y座標(絶対座標)
  console.log(rect.width);  // 幅
  console.log(rect.height); // 高さ
}
```


##アニメーション
CSS3で表現するほうが良いが、JSで制御するアニメーション例を書いておく。
要素が1秒ごとに10px移動するアニメーション。


```js:js
const elem = document.getElementById('foo')
let frame = 0;

setInterval(function() {
  frame += 1;
  elem.style.left = frame * 10 + 'px';
}, 1000);
```

##フォームの操作

フォームは主にユーザー登録など、データをサーバに送信して登録する処理利用される。ユーザ登録などのいろいろな情報をまとめてサーバに送るときに利用する。しかし、以下の問題点もある。

* submitをするとページ遷移が生じる

Ajaxはページ遷移を発生させずにページを書き換える技術。フォームはこの思想と相反する部分がある。

###フォームのプロパティ
* formはname属性を設定できる
* name属性は、その値で参照することができる。つまり`document.user`でform要素を取得できる。

```html:htnl
<body>
  <form action="URL" method="post" name="user">　//actionは送信先のURL　methodは送信方法
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="email" name="email">
  </form>
</body>
```

```js:js
const form = document.user;
const name = document.user.username;

form.elements[0] === name //true
form.length //3
form.name //user
form.action //URL

form.target //サブミット後どのウィンドウに表示するか
form.submit(); //サブミット処理をおこなう
form.reset(); //リセット処理を行う
```


###フォームコントロール要素

* input要素
* select要素
* button要素
* textarea要素


利用できるプロパティは以下の通り

```js:js
const form = document.user;
const name = document.user.username;

name.form //form要素を参照
name.disabled //false trueにすることで無効化できる
name.type //text
name.value //"入力値"
name.focus(); //フォーカスを当てる
name.blue(); //フォーカスをはずす
```

##フォームの検証

入力項目が正しく入力されているかどうかのチェックはサーバ側でもするが、JS側でもチェックすることで利点がいくつかある。

1. クライアントサイドだけでチェックが完了するため、サーバ側との通信によるタイムロスがない
2. 明らかに間違ったデータをサーバ側に渡すことを防ぎ、サーバの負担を軽減する。

####検証するタイミング

* submitボタンが押されたとき
    * 不備のあるデータが見つかれば、falseを返しデータをキャンセル
* データが入力された直後
    * 文字数制限を超えたとき、背景色変更など

#####検証に利用できるイベント

| イベント               | 理由                                                         |
| ---------------------- | ------------------------------------------------------------ |
| submit                 | submitイベントのイベントハンドラのみが送信をキャンセルできる。formのsubmitメソッドはイベントは発火せず、そのまま送信される。 |
| focus, blur            | 操作している要素の背景色を変更。要素が外れたら入力値を検証するなど。 |
| change                 | チェックボックスやラジオボタンなど。値が変更したときに検証。textボックスではフォーカスが外れた時に発火するのでinputを利用する。 |
| Keydown,keyup,keypress | キーボード入力があるたびに発火。キーボードの挙動はブラウザごとに異なることに注意 |
| input                  | input要素になにかあるたびに発火する。textなら、1文字入力ごと。 |

##フォームを使ってページ遷移させない方法

1. iframeを利用する
2. 幅、高さ０のiframeを作成し、formのtargetプロパティにiframeのnameを指定する。
3. 結果ページに、親ページを操作する処理を書く。（window.parentで、親ページ参照ができる）