【第2回】 実際に使えるサイトを作ろう

今回はJavascriptを使ってサイトに動きをつけます。演習を通してブラウザ上で「計算機」を作ってみましょう。

Homeブログ一覧【第2回】 実際に使えるサイトを作ろう

JavaScriptとは

JavaScript(以降JS)は、HTMLとCSSとともにWebページを作るための言語です。 JSは、ユーザーの操作に応じてサイト上の要素を動かしたり、変更したりすることができます。 HTML/CSSはフォーマットを記述するだけで、それらだけで計算などのプログラム的な処理はできません。なので「マークアップ言語」と呼ばれます。 一方、JSはランタイムを持ち計算や条件分岐などの処理ができます。なので純粋なプログラミング言語です。

例えば

  • ボタンを押したら、画像を表示する
  • 数値を入力したら、その数値を2倍にして表示する
  • 文字を入力したら、それに関連する情報を表示する

などのリロードしなくても、ユーザーの操作に応じてサイト上の要素を動かしたり、変更したりする処理がある場合には、JSが必要になります。 また、より複雑な処理を行う場合には、JSを使うことで、より簡潔に実装することができます。

書いてみよう

いちいち手打ちしてると時間がかかるのでコードはコピぺして動作を確認してください。

コンソールに出力する

適当なサイト上で右クリックから検証ツールを開き、コンソールを開いてください。 ここが実はJSを実行できる場所になっています。

コンソールに以下のコードを入力してください。

console.log('Hello World!');

すると、コンソールに Hello World! と表示されるはずです。 C++ではcout << "Hello World!" << endl;と書くのがおなじみですが、JSではconsole.log()を使います。

お馴染みの四則演算もできます

console.log(1 + 1); // 2
console.log(1 - 1); // 0
console.log(2 * 2); // 4
console.log(4 / 2); // 2
console.log(5 % 2); // 1

Cではint型同士の除算は小数点以下が切り捨てられますが、JSは動的片付け言語のため、除算では小数点以下も計算されます。

console.log(5 / 2); // 2.5

ちなみに0で割った時はInfinityと表示されます。

console.log(1 / 0); // Infinity

変数を使う

変数宣言の方法が2つありますが、基本的にはletを使います。

let a = 1;
let b = 2;
console.log(a + b); // 3

お気づきの方もいるかもしれませんが、JSには型宣言がありません。これは、JSが動的型付け言語だからです。 動的型付け言語とは、変数の型を宣言する必要がない言語のことです。 その代わり実行時に型を推論するので、実行が遅くなります。 コンパイル型言語が速いのは静的型付け言語だからです。(はしょりすぎですが)

定数

変数と同じようにconstで定数を宣言できます。

const a = 1;
const b = 2;
console.log(a + b); // 3

a = 2; // エラー

定数なので、再代入はできません。aに2を代入しようとするとエラーになります。 基本は定数を使い、再代入が必要な場合に限って変数を使うようにしましょう。 熟練のJSエンジニアほどconstの使用頻度が高いイメージがあります(個人の感想です)。

条件分岐

比較演算

演算子意味
==等しい(キャストあり)
===厳密に等しい(キャストなし)
!=等しくない(キャストあり)
!==厳密に等しくない(キャストなし)
>より大きい
>=以上
<より小さい
<=以下
&&かつ
||または
!否定
console.log(1 == 1); // true
console.log(1 == '1'); // true
console.log(1 === '1'); // false
console.log(1 != 2); // true
console.log(1 !== '1'); // true
console.log(1 > 0); // true
console.log(1 >= 1); // true
console.log(1 < 2); // true
console.log(1 <= 1); // true
console.log(true && true); // true
console.log(true && false); // false
console.log(true || false); // true
console.log(false || false); // false
console.log(1 > 0 && 2 > 1); // true
console.log(1 < 0 || 2 > 1); // true
console.log(!false); // true

if文

const a = 1;
const b = 2;
if (a < b) {
  console.log('a < b');
} else if (a > b) {
  console.log('a > b');
} else {
  console.log('a = b');
}

スイッチ文

const text = "Mon";

switch (text) {
  case "Sun":
    console.log("日曜日");
    break;
  case "Mon":
    console.log("月曜日");
    break;
  case "Tue":
    console.log("火曜日");
    break;
  case "Wed":
    console.log("水曜日");
    break;
  case "Thu":
    console.log("木曜日");
    break;
  case "Fri":
    console.log("金曜日");
    break;
  case "Sat":
    console.log("土曜日");
    break;
  default:
    console.log("曜日ではありません");
    break;
}

繰り返し

for (let i = 0; i < 10; i++) {
  console.log(i);
}

関数

従来の関数

function add(a, b) {
  return a + b;
}
console.log(add(1, 2)); // 3

アロー関数

const add = (a, b) => {
  return a + b;
}
console.log(add(1, 2)); // 3

従来の関数とアロー関数は同じことができますが、アロー関数の方が短く書けたり、簡潔だったりします。 厳密には違いがありますが、今のうちは気にしなくて大丈夫です。

早期リターン

const add = (a, b) => {
  if (a < 0 || b < 0) {
    return;
  }
  return a + b;
}
console.log(add(1, 2)); // 3
console.log(add(-1, 2)); // undefined

関数の中でreturnを使うと、その時点で関数の処理が終了し、その後ろの処理は実行されません。 これを早期リターンと言います。

本当は

const add = (a, b) => {
  if (a < 0 || b < 0) {
    return;
  } else {
    return a + b;
  }
}

と書かなきゃいけないところを、elseを省略して書けるので、短く書けます。 これが綺麗なコードを書く時の基本になりますので、覚えておきましょう。 ※この技術はどの言語でも使えます。競プロでもよく使います。 特にオブジェクト指向言語(JavaやC#など)では必須な表現として紹介されることが多いです。

配列

const array = [1, 2, 3, 4, 5];
console.log(array[0]); // 1
console.log(array[1]); // 2
console.log(array[2]); // 3

console.log(array)

配列操作

JSで繰り返し処理を行う場合、for文を使うことはほとんどありません。 その代わり、配列操作を行います。配列操作を使いこなせるとJS力がとても上がります。 代表的な高階関数8個とその他メソッドを覚えておきましょう。(ほかにもありますが、とりあえずこれだけ覚えておけば大丈夫です)

全部覚える必要はありません、早見表を置いておくので、必要なときに見てください。

関数名・メソッド名説明出力例
map各要素を加工して新しい配列を作成する2倍する [1, 2, 3, 4, 5] -> [2, 4, 6, 8, 10]
forEach各要素に対して関数を実行する一つずつ表示する [1, 2, 3, 4, 5] -> 1, 2, 3, 4, 5
filter条件に当てはまる要素だけを新しい配列にして作成する偶数だけ取り出す [1, 2, 3, 4, 5] -> [2, 4]
find条件に当てはまる要素を最初の一つだけ取り出す偶数を一つだけ取り出す [1, 2, 3, 4, 5] -> 2
reduce各要素をどんどん加工して一つの値にする合計を求める [1, 2, 3, 4, 5] -> 15
some一つでも条件に当てはまる要素があるか偶数があるか [1, 2, 3, 4, 5] -> true
everyすべての要素が条件に当てはまるか偶数だけか [1, 2, 3, 4, 5] -> false
sort配列を並び替える降順に並び替える [1, 2, 3, 4, 5] -> [5, 4, 3, 2, 1]
includes配列に指定した要素が含まれているか3が含まれているか [1, 2, 3, 4, 5] -> true
indexOf配列に指定した要素が何番目にあるか3は何番目か [1, 2, 3, 4, 5] -> 2
join配列を指定した文字で結合する,で結合する [1, 2, 3, 4, 5] -> 1,2,3,4,5
split文字列を指定した文字で分割する,で分割する 1,2,3,4,5 -> [1, 2, 3, 4, 5]
slice配列の一部を取り出す2番目から4番目まで取り出す [1, 2, 3, 4, 5] -> [2, 3, 4]
length配列の要素数を取得する[1, 2, 3, 4, 5] -> 5

Map

Mapはその配列の要素一つ一つを加工して、新しい配列を作成します。

const array = [1, 2, 3, 4, 5];
// すべての要素を2倍する
const doubledArray = array.map((value) => {
  return value * 2;
});

console.log(doubledArray); // [2, 4, 6, 8, 10]

for文でいちいちindexを指定して要素を取り出すのは面倒なので、mapを使います。 mapは配列の要素を一つずつ取り出して、関数を実行します。 その結果を配列にして返します。

ForEach

ForEachはその配列の要素一つ一つに対して、関数を実行します。

const array = [1, 2, 3, 4, 5];
const log = (value) => {
  console.log("value: " + value);
}

array.forEach(log); // value: 1, value: 2, value: 3, value: 4, value: 5

mapと違って、forEachは新しい配列を作成しません。 その代わり各要素に対して関数を実行します。 今回はlogという関数を作成して、それをforEachに渡しています。

Filter

Filterはその配列の要素一つ一つに対して、関数を実行し、その結果がtrueの要素だけを取り出して、新しい配列を作成します。

const array = [1, 2, 3, 4, 5];
const isEven = (value) => {
  return value % 2 === 0;
}
const isOdd = (value) => {
  return value % 2 === 1;
}

const evenArray = array.filter(isEven);
const oddArray = array.filter(isOdd);
console.log(evenArray); // [2, 4]
console.log(oddArray); // [1, 3, 5]

Reduce

Reduceはその配列の要素一つ一つに対して、関数を実行し、その結果を次の要素に渡していきます。 最終的には一つの値を返します。

const array = [1, 2, 3, 4, 5];
const sum = (a, b) => {
  return a + b;
}

const result = array.reduce(sum);
console.log(result); // 15

Find

Findはその配列の要素一つ一つに対して、関数を実行し、その結果がtrueになった最初の要素を返します。

const array = [1, 2, 3, 4, 5];
const isEven = (value) => {
  return value % 2 === 0;
}

const result = array.find(isEven);
console.log(result); // 2

Filterと違って、findは最初に見つかった要素だけを返します。なので今回はindex0から線形探索をして初めて見つかった値2を返します。

Some

Someはその配列の要素一つ一つに対して、関数を実行し、その結果がtrueになった要素が一つでもあればtrueを返します。

const array = [1, 2, 3, 4, 5];
const isEven = (value) => {
  return value % 2 === 0;
}

const result = array.some(isEven);
console.log(result); // true

Every

Everyはその配列の要素一つ一つに対して、関数を実行し、その結果がtrueになった要素がすべてtrueならばtrueを返します。

const array = [1, 2, 3, 4, 5];
const isEven = (value) => {
  return value % 2 === 0;
}

const result = array.every(isEven);
console.log(result); // false

Sort

Sortはその配列の要素一つ一つに対して、関数を実行し、その結果を元にソートします。

const array = [1, 2, 3, 4, 5];
const compare = (a, b) => {
  if (a < b) {
    return 1;
  } else if (a > b) {
    return -1;
  } else {
    return 0;
  }
}

array.sort(compare);
console.log(array); // [5, 4, 3, 2, 1]

え、constなのにsortできるの?と思った方もいるかもしれません。 constは再代入できないだけで、配列の内部状態を変更することはできます。 (わからなくても大丈夫です。)

compare関数はabを比較して、aが大きければ1bが大きければ-1、同じなら0を返します。 sortは負なら要素を入れ替え、0ならそのまま、正なら要素を入れ替えないという3値論理を使ってソートを行います。

Includes

Includesはその配列の要素一つ一つに対して、引数に指定した値と同じかどうかを調べ、一つでも同じ値があればtrueを返します。

const array = [1, 2, 3, 4, 5];

const result = array.includes(3);
console.log(result); // true
const result2 = array.includes(6);
console.log(result2); // false

IndexOf

IndexOfはその配列の要素一つ一つに対して、引数に指定した値と同じかどうかを調べ、一つでも同じ値があればその要素のindexを返します。

const array = [1, 2, 3, 4, 5];

const result = array.indexOf(3);
console.log(result); // 2
const result2 = array.indexOf(6);
console.log(result2); // -1

Join

Joinはその配列の要素一つ一つを文字列に変換し、引数に指定した文字列で結合します。

const array = [1, 2, 3, 4, 5];

const result = array.join('-');
console.log(result); // 1-2-3-4-5

Split

Splitは引数に指定した文字列で配列を分割します。

const text = '1-2-3-4-5';

const result = text.split('-');
console.log(result); // ['1', '2', '3', '4', '5']

Slice

Sliceは引数に指定したindexから、引数に指定したindexまでの要素を取り出します。 sliceは左開右閉の半開区間で指定します。 例えば、slice(1, 3)とすると、indexが[1, 3)の要素を取り出します。

ちなみに自分も調べて知ったのですが、sliceが半開区間での指定である理由は空集合の表現が直感的にできるためと、slice(0, array.length)で配列のコピーができるためだそうです。 たしかに0-indexedだからこその理由なんですね。

const array = [1, 2, 3, 4, 5];

const result = array.slice(1, 3); // indexが1以上3未満の要素を取り出す
console.log(result); // [2, 3]

Length

Lengthはその配列の要素の数を返します。

const array = [1, 2, 3, 4, 5];

const result = array.length;
console.log(result); // 5

オブジェクト

オブジェクトは、プロパティと呼ばれる名前と値のペアを保持するデータ構造です。 オブジェクトは、{}で囲んだ中に、プロパティを記述することで作成できます。 オブジェクトのプロパティには、文字列や数値、真偽値、配列、オブジェクトなど、様々な値を設定することができます。

const object = {
  name: 'John',
  age: 20,
  isMale: true,
  favoriteFoods: ['sushi', 'pizza'],
  address: {
    country: 'Japan',
    city: 'Tokyo',
  },
};

console.log(object.name); // John
console.log(object.age); // 20
console.log(object.isMale); // true
console.log(object.favoriteFoods); // ['sushi', 'pizza']
console.log(object.favoriteFoods[0]); // sushi
console.log(object.address); // { country: 'Japan', city: 'Tokyo' }
console.log(object.address.country); // Japan

オブジェクトのプロパティにアクセスするには、ドット記法またはブラケット記法を使います。 ドット記法では、オブジェクトの変数名の後にドットを付け、その後にプロパティ名を記述します。 ブラケット記法では、オブジェクトの変数名の後にブラケットを付け、その中にプロパティ名を文字列で記述します。

特に

const object = {
    "1": "aaa",
    "with-hyphen": "bbb",
    "with space": "ccc"
};

console.log(object.1); // SyntaxError: Unexpected number
console.log(object.with-hyphen); // SyntaxError: Unexpected token -
console.log(object.with space); // SyntaxError: Unexpected identifier
console.log(object["1"]); // aaa
console.log(object["with-hyphen"]); // bbb
console.log(object["with space"]); // ccc

特にdotで繋げられない場合はブラケット記法を使う必要があります。

const object = {
  name: 'John',
  age: 20,
};

console.log(object.name); // John
console.log(object['name']); // John

オブジェクトのプロパティの追加・削除

オブジェクトのプロパティを追加するには、ドット記法またはブラケット記法を使います。 ドット記法では、オブジェクトの変数名の後にドットを付け、その後にプロパティ名を記述します。 ブラケット記法では、オブジェクトの変数名の後にブラケットを付け、その中にプロパティ名を文字列で記述します。 arrayと同様に、objectもconstで宣言された場合でもプロパティの追加・削除は可能です。 とにかくconstは変更を禁止するものではなく、constで宣言された物自体への再代入を禁止するものなのです。 ちなみにobjectarrayへの変更を禁止するにはObject.freezeObject.sealを使います。

const object = {
  name: 'John',
  age: 20,
};

object.isMale = true;
object['favoriteFoods'] = ['sushi', 'pizza'];

console.log(object)
// {
//   name: 'John',
//   age: 20,
//   isMale: true,
//   favoriteFoods: ['sushi', 'pizza'],
// }

オブジェクトのプロパティを削除するには、delete演算子を使います。

const object = {
  name: 'John',
  age: 20,
};

delete object.age;

console.log(object); // { name: 'John' }

オブジェクトのプロパティの存在確認

オブジェクトのプロパティが存在するかどうかを確認するには、in演算子を使います。

const object = {
  name: 'John',
  age: 20,
};

console.log('name' in object); // true

console.log('isMale' in object); // false

JSファイルを読み込む

CSSと同じように、JSファイルもHTMLファイルに読み込むことができます。 (もちろんHTML内に直接記述することもできますが、ファイルを分けておくことで、可読性が上がります。) workingディレクトリのWebken2というディレクトリを作成し、その中にindex.htmlmain.jsを作成してください。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>JSファイルを読み込む</title>
  </head>
  <body>
    <h1>JSファイルを読み込む</h1>
    <script src="./main.js"></script>
  </body>
</html>
console.log('Hello World');

こういうフォルダ構成になっていればOKです。

Webken
└── 2
    ├── index.html
    └── main.js

これで、index.htmlをブラウザで開くと、コンソールにHello Worldと表示されます。

(余談)Performance

<script>は実際に表示されるものじゃないから<head>の中で呼ぶんじゃないの?」と疑問に思った方がいるかもしれません。 <script>は実際に表示されるものではないので、<head>の中でも呼ぶことはできます。 ただし、<script>はロードし終わるまでHTMLの読み込みをブロックするので、<body>の最後に書くことが推奨されています。

じゃあ逆にcss<body>で呼ぶのはどうなの?」と疑問に思った方がいるかもしれません。 もちろん、<body>の中でも呼ぶことはできます。 じゃあなんで<head>で呼ぶのが推奨されているのかというと、<body>の中で呼ぶと、CSSが適用されるまで、ページが空白になってしまうため、ユーザーにとって見た目が悪いからです。 なので、CSSは<body>よりも前に呼ぶことが推奨されています。

状態

ユーザーがサイト上で実行するアクションによって変化する、サイトの内部状態を指します。 例えば、ユーザーがログインすると、サイトの状態は「ログイン済み」となります。また、ユーザーがショッピングカートに商品を追加すると、サイトの状態は「カートに商品が追加された」となります。

このように、ユーザーのアクションによって変化するサイトの内部状態を、状態と呼びます。

イベント

ユーザーがサイト上で実行するアクションのことを、イベントと呼びます。

例えば

イベント説明
クリックイベントユーザーがマウスで要素をクリックしたとき
キーダウンイベントユーザーがキーボードでキーを押したとき
マウスオーバーイベントユーザーがマウスで要素に乗ったとき
フォーム送信イベントユーザーがフォームを送信したとき
入力イベントユーザーがフォームに入力したとき
リサイズイベントユーザーがブラウザのウィンドウサイズを変更したとき

などがあります。(実際には把握しきれないほどたくさんあります)

イベントリスナー

イベントが発生したときに、実行する処理を指定することができます。 この処理を、イベントリスナーと呼びます。

例えば、ユーザーがボタンをクリックしたときに、色を替える処理を実行したい場合には、以下のように記述します。

// サイト上から <button id="change-color-btn">ボタン</button> を取得する
const button = document.getElementById('change-color-btn');

// 文字色を変えて表示する処理
function changeColor() {
    // サイト上から <p id="text">テキスト</p> を取得する
    const text = document.getElementById('text');
    // 画像を表示する
    text.style.color = 'red';
}

// ボタンをクリックしたときに、changeColor() 関数を実行する
button.addEventListener('click', changeColor);

.addEventListener() は、イベントリスナーを登録するメソッドです。 第1引数にイベント名、第2引数にイベントが発生したときに実行する関数を指定します。 今回は、ボタンをクリックしたときに、displayImage() 関数を実行するように指定しています。

では、実際にコードを書いてみましょう。

まずサイトにボタンを追加します。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>JSファイルを外部呼び出ししてみる</title>
  </head>
  <body>
    <button id="change-color-btn">ボタン</button>
    <p id="text">テキスト</p>
    <script src="./main.js"></script>
  </body>
</html>

次に、ボタンをクリックしたときに、文字色を変える処理を書きます。

function changeColor() {
    const text = document.getElementById('text');
    text.style.color = 'red';
}

function onLoaded() {
    const button = document.getElementById('change-color-btn');
    button.addEventListener('click', changeColor);
}

document.addEventListener('DOMContentLoaded', onLoaded);

functionをインラインで書く場合

changeColor()関数やonLoaded()関数は、インラインで書くこともできます。

document.addEventListener('DOMContentLoaded', function() {
    const button = document.getElementById('change-color-btn');
    const text = document.getElementById('text');

    button.addEventListener('click', function() {
        text.style.color = 'red';
    });
});

アロー関数を使う場合

アロー関数を使うとさらに綺麗にインラインで書くことができます。

document.addEventListener('DOMContentLoaded', () => {
    const button = document.getElementById('change-color-btn');
    const text = document.getElementById('text');

    button.addEventListener('click', () => {
        text.style.color = 'red';
    });
});

これで、index.htmlをブラウザで開くと、ボタンをクリックすると文字色が変わるようになります。

なぜDOMContentLoadedが必要なのか?

DOMContentLoadedは、HTMLの読み込みが完了したときに発生するイベントです。 今回は、DOMContentLoadedが発生したときに、ボタンをクリックしたときに実行する処理を登録しています。

もし、js<head>で呼んでたら、DOMContentLoadedが発生する前に、jsが読み込まれてしまうので、まだサイト上にボタンが存在しない状態で、ボタンを取得しようとしてエラーが発生してしまいます。 これが、DOMContentLoadedが必要な理由です。

学んだ知識を使ってみよう

今回は簡単な計算機を作ってみましょう。

要件

  • 数値を入力する2つの入力ボックスがある
  • 計算するボタンがある
  • ボタンが押されるとその2つの数値を足し算して、計算結果を表示する

HTML

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>JSファイルを外部呼び出ししてみる</title>
  </head>
  <body>
    <input type="text" id="num1" />
    <input type="text" id="num2" />
    <button id="calc-btn">計算する</button>
    <p id="result"></p>
    <script src="./main.js"></script>
  </body>
</html>

ヒント

  • 入力ボックスの値は、document.getElementById('テキストボックスのid').valueで取得できる
  • 文字列を数値に変換するには、parseInt()を使う
  • 計算結果を表示するには、document.getElementById('計算結果を表示する要素のid').textContentを使う

10分間くらいとるのでやってみましょう

拡張しよう - 演算拡張

追加要件

  • 引き算、掛け算、割り算もできるようにしよう
  • 選べるようにしよう

HTML

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>JSファイルを外部呼び出ししてみる</title>
  </head>
  <body>
    <input type="text" id="num1" />
    <!-- ここから追加 -->
    <select id="operator">
      <option value="plus">+</option>
      <option value="minus">-</option>
      <option value="multiply">×</option>
      <option value="divide">÷</option>
    </select>
    <!-- ここまで追加 -->
    <input type="text" id="num2" />
    <button id="calc-btn">計算する</button>
    <p id="result"></p>
    <script src="./main.js"></script>
  </body>
</html>

ヒント

  • 選択されている値は、document.getElementById('セレクトボックスのid').valueで取得できる

5分間くらいとるのでやってみましょう

拡張しよう - エラーハンドリング

追加要件

  • 数値以外が入力された場合は、「数値を入力してください」とエラーを表示しよう
  • 0で割ろうとした場合は、「0で割ることはできません」とエラーを表示しよう
  • 正しく計算できた場合は、エラーを消そう

HTML

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>JSファイルを外部呼び出ししてみる</title>
  </head>
  <body>
    <input type="text" id="num1" />
    <select id="operator">
      <option value="plus">+</option>
      <option value="minus">-</option>
      <option value="multiply">×</option>
      <option value="divide">÷</option>
    </select>
    <input type="text" id="num2" />
    <button id="calc-btn">計算する</button>
    <p id="result"></p>
    <!-- ここから追加 -->
    <p id="error"></p>
    <!-- ここまで追加 -->
    <script src="./main.js"></script>
  </body>
</html>

ヒント

  • エラーを表示するには、document.getElementById('エラーを表示する要素のid').textContentを使う
  • エラーを消すには、document.getElementById('エラーを表示する要素のid').textContent = ''を使う
    • 空文字を代入することで、エラーを実質消したことになる
  • 数字かどうかは、isNaN()を使う
    • parseIntは数字以外を入れるとNaNというNumber(JSのオブジェクトの一つ)を返すので、それかどうかをisNaNで判定する

10分間くらいとるのでやってみましょう

よりよくしてみよう - スタイリング

追加要件

  • 計算結果を表示する要素をめだたせよう
    • 例えば、<p>タグの背景色を黄色にしてみよう
  • エラーを表示する要素をめだたせよう
    • 例えば、<p>を赤色にしてみよう

外部からCSSを読み込む方法(前回やったやつ)を使ってみよう

HTML

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>JSファイルを外部呼び出ししてみる</title>
    <!-- ここから追加 -->
    <link rel="stylesheet" href="./style.css" />
    <!-- ここまで追加 -->
  </head>
  <body>
    <input type="text" id="num1" />
    <select id="operator">
      <option value="plus">+</option>
      <option value="minus">-</option>
      <option value="multiply">×</option>
      <option value="divide">÷</option>
    </select>
    <input type="text" id="num2" />
    <button id="calc-btn">計算する</button>
    <p id="result"></p>
    <p id="error"></p>
    <script src="./main.js"></script>
  </body>
</html>

ヒント

  • CSSでIDがついた要素を指定するには、#id名を使う
#nannkano-id {
    /* ここにスタイルを書く */
}
  • 背景色を変えるには、background-colorを使う
  • 文字色を変えるには、colorを使う

5分間くらいとるのでやってみましょう

事後学習

もし時間が余ったら、以下のことをやってみましょう

  • CSSをもっと書いてUIを整えてみよう
    • テキストボックスやセレクトボックスの大きさを変えてみよう
  • HTML構成を変えてみよう
    • 例えば、演算子を選ぶUIを4オプションのセレクトボックスではなく、4つのボタンにしてみよう(電卓のイメージ)
  • さらに演算を拡張してみよう
    • 例えば、剰余を計算できるようにしてみよう
    • (発展)入力ボックスや出力フィールドを拡張して、ベクトル演算や行列演算ができるようにしてみよう
    • (発展)入力ボックスや出力フィールドを拡張して、複素数演算ができるようにしてみよう
    • (発展)回転行列を計算できるようにしてみよう
  • (発展)入力オプションを作ろう
    • 入力ボックスの値を負数に切り替える+/-ボタンを作ってみよう