#はじめに
前回の「[Queryよくばりセット」が好評だったので、素のJs版も作ってみることにしました。
ちょうど同じタイミングで、Javascriptの学習で悩む声を現場で耳にしたので、それに関する記述もちょっぴり混ぜ込みました。
初めての人は「実践編」を、もう慣れてるよという人は「コード集」を参照のこと。
……あ、間違いとかあったら編集リクエストお願いしますね。
#実践例
まずは**「javascriptなんか触ったことねンだよぉ」という人向けに、そのままhtmlファイルにコピー&ペーストできる形でのコード例を用意しておいた。
いきなり?と思うかもしれないが理由は一応ある。
入門者にとって大事なのは完成形のコードに触れてみる**ことだからだ。
というわけなので、Javascriptを始めてみようと思う人(もしくは、jQueryなどのJsフレームワークを使ってみようと思う人)は、以下の2つの実践例を参考に、自分の手元にあるウェブサイトもしくはhtmlファイルに、ハンバーガーボタン、または選択式タブを作ってみよう。
筆者も実務2年のシロートなので大口は叩けないが、少なくとも以下のハンバーガーボタン&選択式タブをhtmlファイル上に実装できる実力があれば、Javascriptを最低限扱えるだけの能力はあるというのは体感的に感じている。
「どこまで学べばいいんだ」と悩んでいるのなら、これを基準にしてみてはいかがだろうか。
<div id="button">button</div>
<ul id="menu">
<li>contents</li>
<li>contents</li>
<li>contents</li>
<li>contents</li>
<li>contents</li>
</ul>
<script type="text/javascript">
(function(){
// ノード取得
var button = document.getElementById('button');
var menu = document.getElementById('menu');
// 初期状態なので、メニューを見えなくする
menu.style.display = 'none';
// ボタンを押したときの動作
button.addEventListener('click', function(){
// 現在、styleとして指定しているdisplayの値を取得
var currentstyle = menu.style.display;
// displayの値がnoneならメニューは閉じているので開き、blockなら開いているので閉じる処理
if( currentstyle == 'none'){
menu.style.display = 'block';
}
else{
menu.style.display = 'none';
}
}, false);
})();
</script>
<div id="changebutton">
<span class="off">01</span>
<span class="off">02</span>
<span class="off">03</span>
<span class="off">04</span>
</div>
<ul id="changingtab">
<li data-menutab="01">target_tab01</li>
<li data-menutab="02">target_tab02</li>
<li data-menutab="03">target_tab03</li>
<li data-menutab="04">target_tab04</li>
</ul>
<script type="text/javascript">
(function(){
var changebutton = document.getElementById('changebutton');
var button = changebutton.children;
var changingtab = document.getElementById('changingtab');
var menucontent = changingtab.children;
// menucontentは配列なので、for文を介して処理を適用する。ここでは透明度をマックスにして見えなくしている
for(var i = 0; i < menucontent.length; i++){
menucontent[i].style.opacity = 0;
}
for(var i = 0; i < button.length; i++){
button[i].addEventListener('click', function(){
// buttonのクラスを全リセット
for(var i =0; i < buttons.length; i++){
buttons[i].className = "off";
}
var currentbutton = this;
var content = currentbutton.innerText;
currentbutton.className = "on";
for(var j = 0; j < menucontent.length; j++){
var targettab = menucontent[j].dataset.menutab;
if(content == targettab){
menucontent[j].style.opacity = 1;
}
else{
menucontent[j].style.opacity = 0;
}
}
}, false);
}
})();
</script>
#コード集
<script type="text/javascript">
// 即時関数。処理をひとつの関数に囲むことで、グローバル変数を汚染しない。理由がなければ使うべし
(function(){
// 厳格モード。
// https://analogic.jp/use-strict/ ←こちらのページが詳しいが、とりあえずここでは「ほかの箇所で実行されるjavascriptに影響を及ぼさないようにするもの」と捉えておいてほしい。
'use strict';
// DOMオブジェクト(ノード)の取得
// ※HTMLを操作する(動かす)ためには、なによりもまずこの「ノード」を取得しないことにははじまらない!
// このノードを取得 → 取得したノードの中身を変更 → するとHTMLに変更が反映される!……というのがHTML操作の基本的な流れなのだ!
// IDがhogeのものを取得する。
// 単一のノードとして格納されるので、変数に代入したらそのまま使用できる。まずないだろうけど、万が一2つ以上あった場合は最初のひとつだけを取得。
var hoge = document.getElementById('hoge');
// クラス名がhogeのものをすべて取得する。
// 該当するものが1つであろうとなかろうと、変数には配列として格納されるので注意。
var hoge = document.getElementsByClassName('hoge');
// タグ名がh1のものをすべて取得する。
// 該当するものが1つであろうとなかろうと、変数には配列として格納されるので注意。
var hoge = document.getElementsByTagName('h1');
// name属性名がhogeのものをすべて取得する。
// 該当するものが1つであろうとなかろうと、変数には配列として格納されるので注意。
var hoge = document.getElementsByName('hoge');
// ()の条件に当てはまる要素をひとつ取得する。
// id、class、タグ、cssセレクタ、data属性などなど、幅広い条件で検索できるオールマイティなコードだ。
// 単一のノードとして格納されるので配列にはならないが、条件に当てはまるものが複数ある場合、最初の一つのみを取得することには注意。
var hoge = document.querySelector('#main .hoge div');
// ()の条件に当てはまる要素をひとつ取得する。
// id、class、タグ、cssセレクタ、data属性などなど、幅広い条件で検索できるオールマイティなコードだ。
// querySelectorとの違いとして、条件に当てはまるものが複数ある場合、当てはまるものすべてを取得する。このため該当するものが1つであろうとなかろうと、変数には配列として格納される。
var hoge = document.querySelectorAll('#main .hoge div');
// querySelector、querySelectorAllの取得方法例
// 基本的にはjQueryのそれと同じだ。
// タグがpの要素のうち最初の一つを取得。
var hogen = document.querySelector('p');
// タグがpの要素をすべて取得。
var hogen = document.querySelectorAll('p');
// クラス名がhogeの要素をすべて取得。
var hogen = document.querySelectorAll('.hoge');
// id名がhogeの要素をすべて取得。
var hogen = document.querySelectorAll('#hoge');
// data属性を参照して取得。ここでは、data-specialという属性のついている要素をその値にかかわらずすべて取得している。
var hogen = document.querySelectorAll('[data-special]');
// data属性を参照して取得。ここでは、data-specialという属性のついているdiv要素をその値にかかわらずすべて取得している。
var hogen = document.querySelectorAll('div[data-special]');
// data属性を参照して取得。ここでは、data-specialという属性がついていて、なおかつその値がactiveのものをすべて取得している。
var hogen = document.querySelectorAll('[data-special="active"]');
// data属性を参照して取得。ここでは、data-specialという属性がついていて、なおかつその値がactiveのものをすべて取得している。
var hogen = document.querySelectorAll('[data-special="active"]');
// data属性を参照して取得。ここでは、data-specialという属性がついていて、なおかつその値の先頭にactiveとついているものをすべて取得している。たとえば「active」、「active1」、「active2」は全部該当する
var hogen = document.querySelectorAll('[data-special^="active"]');
// data属性を参照して取得。ここでは、data-specialという属性がついていて、なおかつその値の末尾にsecとついているものをすべて取得している。
var hogen = document.querySelectorAll('[data-special$="sec"]');
// data属性を参照して取得。ここでは、data-specialという属性がついていて、なおかつその値にsecという文字列が含まれているものをすべて取得している。
var hogen = document.querySelectorAll('[data-special*="sec"]');
// data属性でなくとも利用可能。
var hogen = document.querySelectorAll('input[type="radio"]');
var hogen = document.querySelectorAll('input[name="yourname"]');
var hogen = document.querySelectorAll('span[class="tohide"]');
var hogen = document.querySelectorAll('ul[id="buttoncase"]');
var hogen = document.querySelectorAll('a[link^="lightbox"]');
// 複数指定する時はこうする
var hogen = document.querySelectorAll('input[type="checkbox"][value="1"][name="review"]');
// ~~複数の要素系~~
// idがhogaの要素の中にある、クラス名がhogeの要素をすべて取得。
var hogen = document.querySelectorAll('#hoga .hoge');
// idがhogaの要素の直下にある、クラス名がhogeの要素をすべて取得。
var hogen = document.querySelectorAll('#hoga > .hoge');
// idがhogaであるか、またはクラス名がhogeである、このいずれかに合致する要素をすべて取得。
var hogen = document.querySelectorAll('#hoga, .hoge');
// idがhoga、またはpiyoである、このいずれかに合致する要素をすべて取得。ちなみに、querySelectorでこれをやると先に書かれたほうだけを取得する
var hogen = document.querySelectorAll('#hoga, #piyo');
//クラスonがついているli要素をすべて取得。
var hogen = document.querySelectorAll('li.on');
// 実は、「document」という文字自体が今開いているページのhtml要素まるごと全てを指している。ようは、getElement系はその中から絞り込みをかけているだけなのだ。
// つまり応用として、以下のような書き方もしていいってこと。
var hogem = document.getElementById('hoge');
var hogem = hogem.getElementsByClassName('.piyo'); // ←hogeというidを持つ要素の中にある、piyoというクラスを持つ要素を取得
// この書き方でも結果は同じ。
var hogem = document.getElementById('hoge').getElementsByClassName('.piyo');
// また以下のように、あらかじめドキュメント全体を変数に入れて読み込み時間を短縮するなんて小ワザもある。何回もdocumentと書くなら使えるかも。
var doc = document;
var hogem = doc.getElementById('hoge');
// で、以下はこの技術を応用したもの。
// 下記に列挙するものは単一のノード(つまり、getElementByIdかquerySelectorで取得したもの)に対してしか使用できないことに注意しよう。
// 「配列で格納」と書いてあるものに対して使いたい場合、特殊な処理が必要になる。
// idがhogeの要素の親要素を取得。
var hogem = document.getElementById('hoge');
var hogera = hogem.parentNode;
// idがhogeの要素の子要素のうち、最初のものを取得。
var hogem = document.getElementById('hoge');
var hogera = hogem.firstElementChild;
// idがhogeの要素の子要素のうち、最後のものを取得。
var hogem = document.getElementById('hoge');
var hogera = hogem.lastElementChild;
// idがhogeの要素の子要素すべてを取得。孫要素は取得しないので、もし孫要素に干渉したいならさらにchildrenを使うか、hogem.childNodes;などで代用しよう。
// 子要素の数に関係なく、配列として格納されることに注意。
var hogem = document.getElementById('hoge');
var hogera = hogem.children;
// idがhogeの要素のひとつ前にある要素を取得。hoge要素の外側にあるってのがポイントだ。
var hogem = document.getElementById('hoge');
var hogera = hogem.previousElementSibling;
// idがhogeの要素の次にある要素を取得。hoge要素の外側にあるってのがポイントだ。
var hogem = document.getElementById('hoge');
var hogera = hogem.nextElementSibling;
// なお、上で「配列として格納」と書いてあるもの、または一つの変数内に2つ以上の要素が入っている変数に処理をかけるときは、以下のようにfor文を経由させる必要がある。
var hoget = document.querySelectorAll('#main .hoge div');
for(var i = 0; i < hoget.length; i++){
hoget[i].style.cssText = "display: none;";
}
// DOMオブジェクト(ノード)以外のデータの取得、設定、削除
// DOMオブジェクト(ノード)の取得が「idなどの属性を手掛かりに要素を取得」するものであったのに対し、こちらは「要素に付けられた属性やその値そのものを取得」する。別物なので混同しないように。
var hogara = document.getElementById('hogara');
// テキストの取得
var hotate = hogara.innerHTML;
// これもテキストの取得だが、innerHTMLと違ってhtmlタグに使われる特殊文字をエスケープするという違いがある(つまり、純粋に要素内のテキストだけを取得したい場合はこれを使うとよい)
var hotate = hogara.textContent;
// これもテキストの取得。IE8以下ではtextContentが作動しない為、これを使おう。
// なお、空白を削除しなかったtextContentに対してこちらは削除する、非表示のテキストを取得できるtextContentに対してinnerTextはできないなど、挙動に細かな違いがある。
var hotate = hogara.innerText;
// テキストの追加
// innerHTMLはエスケープを行わないので、以下のようにhtmlタグをそのままぶっこむことができる。
hogara.innerHTML = '<p>hogehoge</p>';
// こんなふうに、一気に属性まで指定してやってもいい。
hogara.innerHTML = '<a href="http://hogehoge.jp/" class="hoge">hoge</a>';
// HTMLテキストを挿入する。
// innerHTMLはすでに入っている要素を消してしまうので、それを残しつつクラスなどを持つ要素を追加したい場合はこちらを利用しよう、。
hogara.insertAdjacentHTML('beforeend', '<p class="testtext_desu">hogehoge</p>');
// ちなみに、この書き方は上記のinsertAdjacentHTMLと同じ内容。
var hogetest_0 = document.createElement('p');
hogetest_0.className = 'testtext_desu';
hogetest_0.innerHTML = 'hogehoge';
hogara.appendChild(hogetest_0);
// 要素内の先頭に追加することもできる。
hogara.insertAdjacentHTML('afterbegin', '<p class="testtext_desu">hogehoge</p>');
// 普通にテキストを入れたいときはこうする。
// 単純にテキストを入れるときはinnerTextではなくtextContentを使うのをお勧めしよう。後で見やすいので。
hogara.textContent = 'hoge';
hogara.innerText = 'hoge';
// 要素の全削除
hogara.innerHTML = '';
// idの取得、設定、削除
// ※ここで行う操作は「id値そのものを取得」であって、「idを手掛かりにノードを取得」していたgetElementByIdとは異なるので注意!
// idを取得
var hotate = hogara.id;
// これもOK
var hotate = hogara.getAttribute('id');
// idを設定。もし既にid値が存在する場合は上書きする。基本的にid属性を2つ以上設定するのはご法度なので気を付けよう。
hogara.id = 'shiokara';
// これもOK
hogara.setAttribute('id', 'shiokara');
// idを削除する。
hotata.removeAttribute('id');
// クラスの取得、設定、削除
// ※ここで行う操作は「クラス名そのものを取得」であって、「クラスを手掛かりにノードを取得」していたgetElementsByClassNameとは異なるので注意!
// クラスをまとめて取得
var hotate = hogara.className;
// これもOK
var hotate = hogara.getAttribute('class');
// 特定のクラスが付与されているかどうかをチェック。hotateにはtrueかfalseのいずれかが入る
var hotate = hogara.className.includes('hoge');
// クラスをひとつだけ設定。順番は一番最後になる。
hotata.setAttribute('class', 'takowasa');
// これもOK。既存のクラスを上書きする。
hogara.className = 'takowasa';
// クラスをまとめて設定。この処理の前にクラスがすでに付与されていた場合、それらはすべて上書きされてしまうので注意。
hogara.className = 'hoge ikageso takowasa';
// クラスをまとめて削除。
hotata.removeAttribute('class');
// クラスをひとつだけ削除。もし存在しない場合は無視してくれる。削除後にclassがなかった場合、空のclass属性が無意味に残ってしまうので見た目は悪いかも。
// 複数の場合はこうする
hogara.classList.remove('hoge', 'ikageso', 'takowasa');
// クラスをひとつだけ設定または削除。指定したクラスが存在するかどうかを自動でチェックし、存在するなら削除し、存在しないなら追加する。
hogara.classList.toggle('takowasa');
// cssの取得、設定、削除(要素に直接設定するやつ。スタイルシートとは関係ありません)
// ある要素に指定されているcssをまるごと取得。ただし、style="~~"の形で書かれているものでないと取得できない事には注意。
// 取得したい値がstyle="~~"の形で書かれていない場合は下記の「応用編」を参照しよう。
var hotate = hogara.cssText;
// ある要素に指定されている特定のcssひとつの値を取得。ただし、style="~~"の形で書かれているものでないと取得できない事には注意。
// 取得したい値がstyle="~~"の形で書かれていない場合は下記の「応用編」を参照しよう。
var hotate = hogara.style.color;
// background-colorの場合。
var hotate = hogara.style.backgroundColor = '#ff0000';
// cssのオプション名(ここで言うところの「backgroundColor」)の書き方は通常と異なるので注意。
// その書き方を端的に言えば、「ハイフンのあるcssを使うときは、ハイフン直後の文字を大文字にする」というもの。ここに気を付けてさえいれば大丈夫。
// たとえば、 z-index => zIndex、 font-size => fontSize、 max-height => maxHeight といった具合に変化する。
// こちらのサイト => http://alphasis.info/javascript/dom/styleobject/#javascript-dom-styleobject-display
//に、より詳しい内容が書いてあるので、必要なら参照しよう。
// cssをまるごと上書き設定。もともと付与されていたcssはすべて消えててしまうので注意。
hogara.style.cssText = "background-color: yellow; font-size: 20px;";
// cssをひとつだけ追加。ほかのcssを上書きしないので、基本的にはこちらを使うべし。
hogara.style.backgroundColor = '#ff0000';
// cssを全削除。
hogara.removeAttribute('style');
hogara.style.cssText = '';
// cssをひとつだけ削除。
hogara.style.backgroundColor = '';
// cssの取得、設定、削除ーーー応用編
// なんと、要素に現在適用されているcss設定を引っ張ってくるという荒業も可能(つまり、現在の色や幅や透過度などを取得できる)。要素の幅によって動的に操作したい場合に重宝するカモ。
var kaibashira = document.getElementById('kaibashira');
var hotate = window.getComputedStyle( kaibashira, null);
var color = hotate.getPropertyValue('color');
var marginleft = Number( hotate.getPropertyValue('margin-left').replace( /px/g , "" ) );
// 疑似要素にだって使えちゃう。
var hotate2 = window.getComputedStyle( kaibashira, '::before');
var content = hotate2.getPropertyValue('content');
// 属性値の取得、設定、削除
// data属性値を取得。数値を取得した場合でも文字列として格納されるので注意。 (存在しない場合はnullもしくは空文字を返す)
var hotate = hogara.getAttribute('data-tokubetsu');
// これでもOK。ただし、古いIEだと反応しないこともあり。数値を取得した場合でも文字列として格納されるので注意。
var hotate = hogara.dataset.tokubetsu;
// もしdata属性名が「data-tabun-tokubetu」のように、dataのすぐ後以外にハイフンが使われているものの場合、以下のように書くべし。これは、設定、削除のときでも同じ。数値を取得した場合でも文字列として格納されるので注意。
var hotate = hogara.dataset.tabunTokubetu;
var hotate = hogara.getAttribute('data-tabun-tokubetu');
// data属性値を設定
hogara.dataset.tokubetsu = 'hogehoge';
// data属性値を設定
hogara.setAttribute('data-tokubetsu', 'hogehoge');
// data属性値を削除
delete hogara.dataset.tokubetsu;
// data属性値を削除
hogara.removeAttribute('data-tokubetsu');
// なお、存在を確かめたいときはhasというパラメータもある
hotata.hasAttribute('data-tokubetsu');
// dataでなくとも利用できる
hotata.hasAttribute('href');
hotata.hasAttribute('name');
hotata.hasAttribute('class');
hotata.hasAttribute('id');
// 上のと同じ理屈で、data以外の属性も取得、設定、削除できる
// 取得(id) (存在しない場合はnullもしくは空文字を返す)
var hotata = hogara.getAttribute('id');
// 設定(id)
hotata.setAttribute('id', 'furyo');
// 削除(id)
hotata.removeAttribute('id');
// 取得(class) (存在しない場合はnullもしくは空文字を返す)
var hotata = hogara.getAttribute('class');
// 設定(class)
hotata.setAttribute('class', 'furyo');
// 削除(class)
hotata.removeAttribute('class');
// 取得いろいろ(存在しない場合はnullもしくは空文字を返す)
var hotata = hogara.getAttribute('href');
// 設定いろいろ
hotata.setAttribute('href', 'http://hoge.jp');
// 削除いろいろ
hotata.removeAttribute('href');
// 取得いろいろ(存在しない場合はnullもしくは空文字を返す)
var hotata = hogara.getAttribute('type');
// 設定いろいろ
hotata.setAttribute('type', 'text');
// 削除いろいろ
hotata.removeAttribute('type');
// 取得いろいろ(存在しない場合はnullもしくは空文字を返す)
var hotata = hogara.getAttribute('readonly');
// 設定いろいろ
hotata.setAttribute('readonly', true);
// 削除いろいろ
hotata.setAttribute('readonly', false);
// イベント(非同期関数)
var sakenotsumami = document.getElementById('tanonndenai');
// 基本形
sakenotsumami.addEventListener('click', function(){
// この部分にクリック時の動作を書く~
alert("「あんた今……クリック、したでしょ?」");
// ~この部分にクリック時の動作を書く
}, false);
// クリックしたとき、クリックした要素そのものを受け取り操作する。押したボタンごとに異なる動作をさせたいときに。
sakenotsumami.addEventListener('click', function(){
var target = this;
var content = target.innerText;
target.classList.add('clicked');
}, false);
// この書き方でも動作は上のやつとほぼ同じ。
// ただし、違いもある。
// thisを使ったクリックイベントは子要素をクリックしてもイベントが起動するが、こちらの書き方の場合、クリックイベントを付与した要素(今回の場合だと、id=tanonndenaiの要素)の子要素をクリックしたときにイベントが起動しないのだ。
sakenotsumami.addEventListener('click', function(hoge){
var tag = hoge.target;
var content = tag.innerText;
tag.classList.add('clicked');
}, false);
// クリックした位置の座標を取得
sakenotsumami.addEventListener('click', function(piyo){
var offsetX = piyo.offsetX; // =>要素左上からのx座標
var offsetY = piyo.offsetY; // =>要素左上からのy座標
var pageX = piyo.pageX; // =>ウィンドウ左上からのx座標
var pageY = piyo.pageY; // =>ウィンドウ左上からのy座標
var clientX = piyo.clientX; // =>ページ左上からのx座標
var clientY = piyo.clientY; // =>ページ左上からのy座標
}, false);
// 無効化系
var clears = document.querySelectorAll('a, button[type="submit"]');
for(var i = 0; i < clears.length; i++){
clears[i].addEventListener('click', function(e){
// aタグやsubmitなど、それ自体で特殊な動作をするhtmlタグの動作を無効化できる。たとえばコイツを使うと、「aタグをクリックしたのに別ページに移動しない」なんてことが可能。
e.preventDefault();
}, false);
}
// マウスが要素の上に乗った時の処理。cssのhoverと違い、乗った時、外れたとき両方の処理を書く必要あり
sakenotsumami.addEventListener('mouseenter', function(){
this.style.cursor = 'pointer';
}, false);
// 外れたとき
sakenotsumami.addEventListener('mouseleave', function(){
this.style.cursor = 'default';
}, false);
// 要素の中身が変更されたときに起動。inputなどvalue値をもつものに使う
// <input id="BB" value="" />
var sakenotsumami = document.querySelector('#BB');
sakenotsumami.addEventListener('change', function(hoge){
console.log('changeしました。新しいテキストは' + hoge.target.value + 'です。');
}, false);
// 画面のサイズが変わった時に起動
window.addEventListener('resize', function(){
var body = window.getComputedStyle( document.querySelector('body'), null);
console.log('横幅:' + body.getPropertyValue('width') + ' 高さ:' + body.getPropertyValue('height') );
}, false);
// formの中のsubmit(送信)を阻止する
// submitボタンを押したときに動くのは、送信ボタンではなくformタグ!間違えないように。
formbox.addEventListener('submit', function(e){
e.preventDefault;
}, false);
// 要素の作成と削除
// 要素の作成&変数への格納。(この時点ではHTML上に追加されない)
// ここで作られるのは空の要素(今回はdiv)なので、このあと必要に応じて中身や属性を追加していく必要がある
var hona = document.createElement('div');
hona.textContent = 'hogetxt';
var oya_element = document.querySelector('body');
// oya_elementの子要素のうち一番最後のものとして追加
oya_element.appendChild(hona);
// oya_elementの子要素から指定した要素(今回はhona)を削除
oya_element.removeChild(hona);
// 基本操作
// 「コンソール」という場所に、変数、または入力してある内容を表示する、デバッグの際にはこれを使う
console.log(hogehoge);
// 画面上にメッセージを表示。試してみるのが速いかも。
alert('hogehoge');
// alertのyes/noを選択させるバージョン。result変数に「はい」を選んだらtrue「いいえ」を選んだらfalseが入る
var result = confirm('hogehoge?');
// alertの文字を入力させるバージョン。resultに入力された文字列が入る。第二引(hoge!)数は初期値
var result = prompt('Please do hogehoge.', 'hoge!');
// 変数宣言
// 変数宣言。constを使って宣言した変数は後から書き換えられず、変数の中身を再代入で変えようとするとエラーが起こる。
// 逆に言えば勝手に書き換えられることもないので、一番安全。
// 出来る限りこれを使いたい。
const hora = 1;
// 変数宣言。letを使って宣言した変数は後から書き換え可能。
// 中身を後から書き換えることができるので、繰り返し中身を変えることを予測できる場合はこちら。
let hora = 1;
// 変数宣言。varを使って宣言した変数は後から書き換え可能。
// 「巻き上げ」という怪現象(くわしくはググったほうが早いかも)が起こるので、多くのプログラマには蛇蝎のごとく嫌われている。
// しかし、「あらゆる環境で動く」というメリットもある。たとえば、IEなどの古いバージョンのブラウザではconstやletが動かないことも多い。
// 高齢者を対象にしたホームページなど、閲覧者のPCがヤバい可能性を考慮するならこれを使う。同じ理由でここでもvarを用いている。
var hora = 1;
})();
</script>
#参考文献
即時関数
http://blog.tojiru.net/article/197270788.html
Strictモード
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Strict_mode
https://analogic.jp/use-strict/
DOM操作
https://qiita.com/mizu16/items/76d72bdeca706e04ca43
https://qiita.com/kouh/items/dfc14d25ccb4e50afe89
https://lab.syncer.jp/Web/JavaScript/Snippet/76/
https://qiita.com/Yuki-Kurita/items/6f94c3814d7c3694f4ba
https://itsakura.com/js-createelement#s8
https://qiita.com/KDE_SPACE/items/e21bb31dd4d9c162c4a6 ←おすすめ
https://qiita.com/KDE_SPACE/items/3c4b52d077b8eabbe670 ←おすすめ
http://cly7796.net/wp/javascript/get-parent-and-sibling-elements-with-javascript/
CSS
https://www.imamura.biz/blog/27524
http://alphasis.info/javascript/dom/styleobject/#javascript-dom-styleobject-display ←おすすめ
http://alphasis.info/javascript/dom/styleobject/#javascript-dom-styleobject-text ←おすすめ
data属性
https://ginpen.com/2015/12/22/dataset/
イベント
https://ja.stackoverflow.com/questions/8628/addeventlistener%E3%81%A7-%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%E3%81%97%E3%81%9F%E8%A6%81%E7%B4%A0%E3%81%9D%E3%81%AE%E3%82%82%E3%81%AE%E3%82%92%E5%8F%97%E3%81%91%E5%8F%96%E3%82%8A%E3%81%9F%E3%81%84
https://tech-dig.jp/javascript-click-position/
https://qiita.com/KDE_SPACE/items/e75076ffc4d1eac0aedc
https://naruhodo.repop.jp/javascript-mouse-hover-event/
https://memorva.jp/memo/html/javascript_link_a_href_void0_preventdefault.php