はじめに
この文書はWeb開発の入門ガイドです。 Web開発を進めていくための助けになれば幸いです。
目次
- はじめに
- Web開発入門
- Web
- JavaScript
- Webサイトを公開する
- Google Apps Script (GAS) で作るWebアプリ
- Raspberry Piで温度センサーのデータの送信
- Raspberry Piからスマートフォンにデータを送信する
- 質問・提案・問題の報告
― この文書は © 2023 MDN Web Docsプロジェクト協力者 クリエイティブ・コモンズ CC BY SA 2.5 ライセンスのもとに利用を許諾されています。 元の文書: https://developer.mozilla.org/ja/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like
Web開発入門
Web開発を始める前に考えておかなければいけないことがあります。Webサイトは様々なことができます。しかし複雑なものを開発するとしても、はじめはできるだけ単純なものから少しずつ理解を深めていくべきでしょう。
まずは、見出し、画像、段落のある単純なWebページを作ることから始めましょう。
- 何についてのWebページ? 犬、ニューヨーク、それともパックマン?
- どんな情報? タイトルといくつかの段落、それからページに表示させたい画像を考えます。
- どんな見た目? 簡単で大まかな言葉で言うと?背景色は?適切なフォントはフォーマル?漫画?太字で派手?繊細?
デザインをスケッチする
次に、ペンと紙を取ってサイトの見た目をどういう風にしたいのか大まかに描き出します。はじめてのシンプルなWebページでは、描き出すものもあまりないかもしれませんが、作る上での習慣にしましょう。(ヴァン・ゴッホのようになる必要はありません)
Note 現実の複雑なWebサイトの場合でも、デザインチームは普通、ラフスケッチを描くことから始めます。その後、グラフィックエディターや Web の技術を使って、デジタルのモックアップを作るのです。
多くの場合、Webの開発チームには、グラフィックデザイナーとユーザーエクスペリエンス (UX) デザイナーがいます。グラフィックデザイナーは、Webサイトの見た目を作り上げます。 UX デザイナーは、もう少し抽象的な役割を持っていて、サイトを訪れるユーザーがWebサイトでどういう経験をし、どのように操作するかということを考えます。
この時点で、Webページについて、どう表現したいかをまとめ始めていきましょう。
テキストエディター
Visual Studio Codeなどのテキストエディターを使用して忘れないようにメモしておきましょう。
- オンライン版 https://vscode.dev/
フォルダー
フォルダーは簡単に見つけることができる場所、たとえばデスクトップ上、ホームフォルダーの中、Cドライブのルートなどに置きましょう。
- Webサイトプロジェクトを保存する場所を選択してください。ここでは
web-projects
(またはそのようなもの)という新しいフォルダーを作成します。これはWebサイトのプロジェクト全体を保存するところです。 - フォルダーの中に、最初のWebサイトを格納する別のフォルダーを作成します。それを
test-site
と呼びましょう(もっとユニークなものでもOK)。
コンテンツ
- タイトル: Mozilla is cool (例)
- 内容: Mozilla is cool (例)
テーマカラー
色を選ぶときは、「カラー選択ツール」と検索し、好みの色を見つけましょう。色をクリックすると、 #fcba03
のような "#" + 6 桁の奇妙なコードが出てきます。これはヘキサコード(16 進数コード、0, 1, 2, ..., 9, a, b, ..., f までの16種類の数字を使うコード)と呼ばれ、選んだ色を表します。このコードはあとで使うのでコピーしておきましょう。
画像
画像を探すには、Google 画像検索にアクセスし、ぴったりなものを探しましょう。
- 欲しい画像が見つかったら、クリックして拡大表示にします。
- 画像を右クリック(Mac では Ctrl +クリック)し、[名前を付けて画像を保存...] を選択して、画像を安全に保存する場所を選択します。または、後で使用するためにブラウザーのアドレスバーから画像のWebアドレスをコピーします。
なお、Web上のほとんどの画像には、 Google 画像検索にあるものも含め、著作権があります。あなたが著作権を侵害してしまうことを防ぐために、 Google のライセンスフィルターを使うと良いでしょう。 [ツール] ボタンをクリックすると、 [ライセンス] オプションが下に表示されます。「クリエイティブ・コモンズ ライセンス」などの選択肢を選択してください。
Note
クリエイティブ・コモンズ・ライセンス (CCライセンス) とはCCライセンスとはインターネット時代のための新しい著作権ルールで、作品を公開する作者が「この条件を守れば私の作品を自由に使って構いません。」という意思表示をするためのツールです。
CCライセンスを利用することで、作者は著作権を保持したまま作品を自由に流通させることができ、受け手はライセンス条件の範囲内で再配布やリミックスなどをすることができます。
― この文書は © 2023 MDN Web Docsプロジェクト協力者 クリエイティブ・コモンズ CC BY SA 2.5 ライセンスのもとに利用を許諾されています。 元の文書: https://developer.mozilla.org/ja/docs/Learn/Getting_started_with_the_web/Dealing_with_files
ファイルの扱い
Webサイトは、テキストコンテンツ、コード、スタイルシート、メディアコンテンツなど、多くのファイルで構成されています。ここでは注意すべきいくつかの点を説明します。
コンピューター上でWebサイトがあるべき場所
コンピューター上のWebサイトの開発作業している時もWebサイトのファイルとフォルダーの構造は実際のWebサイトと同じようにしましょう。
フォルダーは簡単に見つけることができる場所、たとえばデスクトップ上、ホームフォルダーの中、Cドライブのルートなどに置きましょう。
- Webサイトプロジェクトを保存する場所を選択してください。ここでは
web-projects
(またはそのようなもの)という新しいフォルダーを作成します。これはWebサイトのプロジェクト全体を保存するところです。 - フォルダーの中に、最初のWebサイトを格納する別のフォルダーを作成します。それを
test-site
と呼びましょう(もっとユニークなものでもOK)。
ファイル名・フォルダー名には日本語・大文字・空白を使わない
この文書ではフォルダーやファイルに空白のない全て半角小文字の名前を付けるよう求めています。理由は次の通りです。
- 多くのコンピューター、特にWebサーバーでは、大文字と小文字が区別されます。例えば、Webサイトの
test-site/MyImage.jpg
に画像を置いて、別のファイルから画像をtest-site/myimage.jpg
として呼び出そうとすると、動作しないかもしれません。 - ブラウザー間、Webサーバー間、プログラミング言語間で、空白の扱いが一貫していません。例えば、ファイル名に空白を使用すると、システムによってはそのファイル名を 2 つのファイル名として扱うことがあります。サーバーによっては、ファイル名の空白を "%20" (URL の空白の文字コード)に置き換えるので、リンクが壊れてしまう結果になります。
my_file.html
のように単語をアンダースコアで区切るよりは、my-file.html
のようにハイフンで区切った方がよいでしょう。
Webサイトはどのような構成にするべきか
Webサイトプロジェクトで最も一般的なフォルダー構成は、(1) 目次の HTML ファイル、(2) 画像ファイル、(3) スタイルシート (見た目に関するコード)、(4) スクリプトファイル (JavaScriptのコード) を入れるフォルダーです。作成してみましょう。
index.html
: このファイルには、一般的にあなたのホームページの内容、つまりあなたが最初にあなたのサイトに行ったときに見るテキストと画像が含まれています。テキストエディターを使用して、index.html
という名前の新しいファイルを作成し、test-site
フォルダー内に保存します。images
フォルダー: このフォルダーにはサイトで使用するすべての画像を入れます。test-site
フォルダーの中にimages
という名前のフォルダーを作成します。styles
フォルダー: このフォルダーには、コンテンツのスタイルを設定するための CSS コード(例えばテキストと背景色の設定など)を入れます。styles
というフォルダーをtest-site
のフォルダーの中に作成します。scripts
フォルダー: このフォルダーには、サイトに対話機能を追加するために使用されるすべての JavaScript コード(クリックされたときにデータを読み込むボタンなど)が含まれます。scripts
というフォルダーをtest-site
のフォルダーの中に作成します。
Note Windows では、既定で有効になっている既知のファイルの種類の拡張子を表示しないというオプションがあるため、ファイル名の表示に問題が発生することがあります。一般に、 Windows エクスプローラーで [フォルダーオプション...] オプションを選択し、[登録されている拡張子は表示しない] チェックボックスをオフにし、 [OK] をクリックすることで、これをオフにすることができます。お使いの Windows のバージョンに関する詳細な情報については、Webで検索してください。
ファイルパス
ファイルをお互いに呼び出すためには、ファイルパスを提供する必要があります。
画像ファイルは既存の画像を自由に選択して、以下の手順で使用することができます。
-
以前に選択した画像を
images
フォルダーにコピーします。 -
index.html
ファイルを開き、次のコードをファイルに挿入します。それが今のところ何を意味するのか気にしないでください。シリーズの後半で構造を詳しく見ていきます。<!doctype html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>テストページ</title> </head> <body> <img src="" alt="テスト画像" /> </body> </html>
-
<img src="" alt="テスト画像">
という行は、ページに画像を挿入する HTML コードです。画像がどこにあるのかを HTML に伝える必要があります。画像は images ディレクトリー内にあり、index.html
と同じディレクトリーにあります。ファイル構造の中でindex.html
からその画像に移動するのに必要なファイルパスはimages/your-image-filename
です。例えば、私たちの画像はfirefox-icon.png
と呼ばれており、ファイルパスはimages/firefox-icon.png
になります。 -
src=""
コードの二重引用符の間の HTML コードにファイルパスを挿入してください。 -
alt
属性の内容を入れようとしている画像の説明に変更してください。今回は、alt="Firefoxのロゴ"
とします。 -
HTML ファイルを保存し、Webブラウザーに読み込みます(ファイルをダブルクリックします)。新しいWebページに画像が表示されます。
ファイルパスの一般的なルールは次の通りです。
- 呼び出し元の HTML ファイルと同じディレクトリーにある対象ファイルにリンクするには、ファイル名を使用します。例えば
my-image.jpg
。 - サブディレクトリー内のファイルを参照するには、パスの前にディレクトリー名とスラッシュを入力します。例えば
subdirectory/my-image.jpg
。 - 呼び出し元の HTML ファイルの上階層のディレクトリー内にある対象ファイルにリンクするには、2 つのドットを記述します。例えば、
index.html
がtest-site
のサブフォルダー内にあり、my-image.jpg
がtest-site
内にある場合、../my-image.jpg
を使用してindex.html
からmy-image.jpg
を参照できます。 - 例えば
../subdirectory/another-subdirectory/my-image.jpg
など、好きなだけ組み合わせることができます。
Note Windows のファイルシステムでは、スラッシュ (/) ではなくバックスラッシュまたは¥記号を使用します(例 :
C:\Windows
)。これは HTML では使用できません。Windows でWebサイトを開発している場合でも、コード内ではスラッシュを使用する必要があります。
他にするべきこと
今のところは以上です。フォルダー構造は次のようになります。
― この文書は © 2023 MDN Web Docsプロジェクト協力者 クリエイティブ・コモンズ CC BY SA 2.5 ライセンスのもとに利用を許諾されています。 元の文書: https://developer.mozilla.org/ja/docs/Learn/Getting_started_with_the_web/HTML_basics
HTMLの基本
HTML (HyperText Markup Language)は、Webページの構造を記述するための言語です。例えば、コンテンツは段落、箇条書きのリスト、画像の使用、データテーブルなどの組み合わせで構成されています。
HTML は一連の 要素 で構成されており、これらの要素がコンテンツのさまざまな部分を囲み、一定の表示や動作をさせることができます。タグで囲むと、単語や画像をどこかにハイパーリンクさせたり、単語を斜体にしたり、フォントを大きくしたり小さくしたりすることができます。 例えば、次のようなコンテンツがあるとします。
My cat is very grumpy
行を独立させたい場合は、段落タグで囲んで段落であることを指定することができます。
<p>My cat is very grumpy</p>
HTML 要素の中身
この段落要素についてもう少し詳しく見ていきましょう。
要素は主に以下のようなもので構成されています。
- 開始タグ (opening tag): これは、要素の名前(この場合は p)を山括弧で囲んだものです。どこから要素が始まっているのか、どこから効果が始まるのかを表します。 — 今回の場合どこから段落が始まるかを表しています。
- 終了タグ (closing tag): これは、要素名の前にスラッシュが入っていることを除いて開始タグと同じです。どこで要素が終わるのかを表しています。 — この場合は、段落が終わる場所を表します。終了タグの書き忘れは、初心者のよくある間違いで、おかしな結果になることがあります。
- コンテンツ (content): 要素の内容です。今回の場合はただのテキストです。
- 要素 (element): 開始タグ、終了タグ、コンテンツで要素を構成します。
要素には属性 (attribute) を設定することができます。このような感じです。
属性には、実際のコンテンツには表示させたくない、要素に関する追加情報が含まれています。ここでは、 class
が属性の名前で、 editor-note
が属性の値です。 class
属性では、要素に一意ではない識別子を与えることができ、それを使って要素(および同じ class
値を持つ他の要素)にスタイル情報などのターゲットを設定することができます。
一部の属性、たとえば required
には値がありません。
値を設定する属性は常に次のような形式になります。
- 要素名(すでにいくつか属性がある場合はひとつ前の属性)との間の空白
- 属性名とそれに続く等号
- 引用符で囲まれた属性の値
Note ASCII のホワイトスペース(または
"
'
`
=
<
>
のいずれかの文字)を含まない単純な属性値は引用符を省略することができますが、コードを一貫性のあるものにし、理解を容易にするため、すべての属性値を引用符で囲むことをお勧めします。
要素の入れ子
要素の中に他の要素を入れることもできます。これをネスト(または入れ子)と言います。もしあなたの猫が「とっても」機嫌が悪いことを表したいとしたら、「とっても」という単語を <strong> 要素に入れて、単語の強調を表すことができます。
<p>My cat is <strong>very</strong> grumpy.</p>
しかしながら要素は正しく入れ子にしなければなりません。上記の例では、まず始めに <p> 要素が開始され、その次に <strong> 要素が開始されています。その場合は、必ず <strong> 要素、 <p> 要素の順で終了しなければなりません。次の例は間違いです。
<p>My cat is <strong>very grumpy.</p></strong>
要素は確実に他の要素の中もしくは外で開始し、終了する必要があります。上記の例のように要素が重複してしまうと、Webブラウザーは言おうとしていることを推測してもっとも良いと思われる解釈をするため、予期せぬ結果になることがあります。そうならないよう気を付けましょう!
空要素
コンテンツを持たない要素もあります。そのような要素を 空要素 (void element) と呼びます。すでに HTML ページにある <img> 要素を例に見ていきましょう。
<img src="images/firefox-icon.png" alt="テスト画像" />
この要素は 2 つの属性を持っていますが、終了タグ </img>
がありませんし、内部にコンテンツもありません。これは画像要素は、その機能を果たすためにコンテンツを囲むものではないからです。画像要素の目的は、画像を HTML ページの表示させたいところに埋め込むことです。
HTML 文書の構造
ここまでは HTML 要素について見てきましたが、しかし、要素単体ではあまり役には立ちません。ここからはどのようにしてそれぞれの要素を組み合わせ、 HTML ページ全体を作っていくのかを勉強していきましょう。ファイルの扱いで出てきた index.html
に書いてあるコードをもう一度見てみましょう。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>テストページ</title>
</head>
<body>
<img src="images/firefox-icon.png" alt="テスト画像" />
</body>
</html>
この中にあるものは以下の通りです。
<!DOCTYPE html>
— 文書型宣言です。これは必須の前置きです。昔々、 HTML がまだ出来たばかりの頃(1991 ~ 2 年)、文書型宣言は HTML ページが正しい HTML と見なされるために従わなければならない、一連のルールへのリンクとして機能することを意味していました。つまり、自動エラーチェックなどの有益なものを表すことができました。しかし、最近ではあまり機能しておらず、文書が正しく動作するために必要なだけです。今はこれだけ知っていれば大丈夫です。<html></html>
— <html> 要素です。この要素は、このページのすべてのコンテンツを囲み、ルート要素と呼ばれることもあります。ここでは文書の主要な言語を設定するlang
属性も指定します。<head></head>
— <head> 要素です。この要素は、ページの閲覧者に向けて表示するためのコンテンツではない、 HTML ページに含めたいものをすべて収めるための入れ物です。検索エンジン向けの キーワード やページのディスクリプション(説明書き)、ページの見た目を変更するための CSS、文字コードの宣言などを含みます。<meta charset="utf-8">
— この要素は、大部分の書き言葉の文字のほとんどを含む UTF-8 を文書で使用するように設定しています。基本的には、文書はどんなテキストコンテンツでも扱えるようになります。これを設定しない理由はありませんし、後でいくつかの問題を回避するのに役立ちます。<title></title>
— <title> 要素です。ページのタイトルを指定しています。このタイトルはページが読み込まれた時にブラウザーのタブに表示されます。また、ブックマークやお気に入りに登録した時の説明にも使われます。<meta name="viewport" content="width=device-width">
— このビューポート属性は、このページがある幅のビューポートで描画されることを保証し、モバイルブラウザーがビューポートより広い幅でページを描画した上で縮小して表示するのを防止します。<body></body>
— <body> 要素です。これには、テキスト、画像、ビデオ、ゲーム、再生可能な音声トラックなど、ページを訪れたWebの利用者に表示したいすべてのコンテンツが含まれます。
画像
もう一度 <img> 要素について見ていくことにしましょう。
<img src="images/firefox-icon.png" alt="テスト画像" />
前に説明したように、ページのこれが現れたところに画像を埋め込みます。画像ファイルのパスを値に持つ src
(source) 属性を指定することによってその画像を表示できます。
また、 alt
(alternative; 代替) 属性も指定しています。 alt
属性は、以下のような理由で画像を見られない人に向けて説明するテキストを指定するものです。
- 目が不自由な人。著しく目の不自由な人はよくスクリーンリーダーと呼ばれるツールを使っていて、それが画像の
alt
属性の内容を読み上げます。 - 何らかの理由で画像の表示に失敗した場合。例えば、
src
属性の中のパスをわざと正しくないものに変更してみてください。ページを保存したり再読み込みしたりすると、画像の場所に下記のようなものが表示されるでしょう。
alt テキストのキーワードは「説明文」です。 alt テキストは、その画像が何を伝えているのかを読者が十分に理解できるような情報を提供する必要があります。この例では、現在のテキストである「テスト画像」は全く意味がありません。 Firefox のロゴであれば、「Firefox のロゴ: 地球の周りを燃えるような狐が囲んでいる。」の方がずっと良いでしょう。
画像に良い代替文字列を付けてみましょう。
Note アクセシビリティについて詳しくは MDN のアクセシビリティのページを参照してください。
テキストのマークアップ
この節では、文字列をマークアップするために使用する基本的な HTML 要素をいくつか見ていきます。
見出し
見出し要素により、コンテンツの特定の部分を見出し、または小見出しとして指定することができます。本にメインタイトル、章立て、サブタイトルがあるように、 HTML 文書にも見出しがあります。 HTML には <Heading_Elements", "<h1> - <h6>> の 6 段階の見出しがありますが、よく使うのはせいぜい 3 から 4 まででしょう。
<!-- 4 段階の見出し -->
<h1>メインタイトル</h1>
<h2>最上位の見出し</h2>
<h3>小見出し</h3>
<h4>孫見出し</h4>
Note HTML の中で
<!--
と-->
の間にあるものは、すべて HTML コメントです。ブラウザーは、コードを表示する際にコメントを無視します。つまり、コメントはページ上では表示されず、コードの中に表示されるだけです。 HTMLコメントは、コードやロジックに関する有用なメモを書き込むためのものです。
それでは、あなたの HTML の <img> 要素の上に適切なタイトルを付けてみましょう。
Note 見出しレベル 1 には、暗黙のスタイルがあることがわかりますね。テキストを大きくしたり、太くしたりするために見出し要素を使用しないでください。見出し要素はアクセシビリティや SEO などの理由で使用されているからです。段階を飛ばすことなく、意味のある見出しの並びをページ上に作るようにしてください。
段落
先に説明したように、 <p> 要素は段落を示しています。通常の文章を書くときにはこの要素を頻繁に使うことになるでしょう。
<p>This is a single paragraph</p>
サンプルテキストを (「Webサイトをどんな外見にするか」から持ってきてください) 1 つまたは複数の段落に入れ、 <img> 要素のすぐ下に配置してください。
リスト
Webのコンテンツの多くはリストであり、 HTML にはリストのための特別な要素があります。リストのマークアップは、常に 2 つ以上の要素で構成されています。最も一般的なリストの種類は、順序付きリストと順序なしリストです。
- 順序なしリストは、お買い物リストのようにアイテムの順番が特に関係ない時に使います。順序なしリストは <ul> 要素で囲みます。
- 順序付きリストは料理のレシピのようにアイテムの順番が関係ある時に使います。順序付きリストは <ol> 要素で囲みます。
リストの中に入るそれぞれのアイテムは <li> (list item) 要素の中に書きます。
例えば、次の段落の一部をリストにしたい場合、
<p>
At Mozilla, we're a global community of technologists, thinkers, and builders
working together…
</p>
以下のようにマークアップします。
<p>At Mozilla, we're a global community of</p>
<ul>
<li>technologists</li>
<li>thinkers</li>
<li>builders</li>
</ul>
<p>working together…</p>
ページに番号付きリストと番号なしリストを追加してみましょう。
リンク
リンクはとても重要です。これがWebをWebたらしめているものです。リンクを追加するには、シンプルな要素 <a> を使う必要があります。 a
は "anchor" を省略したものです。段落中の文字をリンクにするには次の手順で行います。
-
リンクにしたい文字を選びます。今回は "Mozilla Manifesto" を選びました。
-
選んだ文字を <a> 要素で囲みます。
<a>Mozilla Manifesto</a>
-
このように <a> 要素に
href
属性を追加します。<a href="">Mozilla Manifesto</a>
このリンクのリンク先になるWebアドレスを、この属性の値に書き込みます。
<a href="https://www.mozilla.org/en-US/about/manifesto/"> Mozilla Manifesto </a>
アドレスの先頭にある https://
や http://
の部分(プロトコルと言います)を書き忘れると、予期せぬ結果となってしまうかもしれません。リンクを作ったら、ちゃんとそれが遷移したいところに行ってくれるかを確かめましょう。
Note
href
は属性名として変に思うかもしれません。覚えにくかったら、href
は hypertext reference を表しているということを覚えておきましょう。
もしまだやってないのなら、ページにリンクを追加してみましょう。
まとめ
説明に沿ってやってきたら以下のようなページが出来上がっているかと思います (もちろん画像やテキストの内容はみなさんの自由です)。
もし途中で行き詰まってしまったら、「サンプルコード」と見比べてみましょう。
― この文書は © 2023 MDN Web Docsプロジェクト協力者 クリエイティブ・コモンズ CC BY SA 2.5 ライセンスのもとに利用を許諾されています。 元の文書: https://developer.mozilla.org/ja/docs/Learn/Getting_started_with_the_web/CSS_basics
CSSの基本
CSS (Cascading Style Sheets) は、Webページのスタイルを設定するコードです。ここでは、始めるのに必要なものを紹介します。ここでは、テキストを赤くするにはどうすればいいのか?コンテンツを(Webページの)レイアウトの中で特定の場所に表示するにはどうすればいいのか?背景画像と色を使って Webページをどのように飾るのか?というような疑問に答えていきます。
例えば、この CSS は段落のテキストを選択し、色を赤に設定しています。
p {
color: red;
}
それでは試してみましょう。テキストエディターを使用して、(上記の) 3 行の CSS 新しいファイルに貼り付けてください。そのファイルを style.css
として styles
という名前のディレクトリーに保存してください。
コードを働かせるには、この(上記の) CSS を HTML 文書に適用する必要があります。そうしないと、このスタイルはブラウザーの HTML 文書の表示に影響しません。
-
index.html
ファイルを開き、先頭(<head> タグと</head>
タグの間)に以下の行を貼り付けてください。<link href="styles/style.css" rel="stylesheet" />
-
index.html
を保存し、ブラウザーで読み込んでください。次のように表示されるはずです。
段落のテキストが赤くなっていれば、おめでとう! CSS が動作しています。
CSS ルールセットの構造
赤い段落テキストの CSS コードを分解して、その仕組みを理解してみましょう。
全体の構造はルールセットと呼びます (ルールセットという語はよく、単にルールとも呼ばれます)。それぞれの部分の名前にも注意してください。
- セレクター (Selector)
- : これはルールセットの先頭にある HTML 要素名です。これはスタイルを設定する要素 (この例の場合は <p> 要素) を定義します。別の要素をスタイル付けするには、セレクターを変更してください。
- 宣言 (Declaration)
- :
color: red;
のような単一のルールです。これは要素のプロパティのうち、スタイル付けしたいものを指定します。
- :
- プロパティ (Property)
- : これらは、 HTML 要素をスタイル付けするための方法です。 (この例では、
color
は <p> 要素のプロパティです。) CSS では、ルールの中で影響を与えたいプロパティを選択します。
- : これらは、 HTML 要素をスタイル付けするための方法です。 (この例では、
- プロパティ値 (Property value)
- : プロパティの右側には—コロンの後に—プロパティ値があります。与えられたプロパティの多くの外観から 1 つを選択します。 (例えば、
color
の値はred
以外にもたくさんあります。)
- : プロパティの右側には—コロンの後に—プロパティ値があります。与えられたプロパティの多くの外観から 1 つを選択します。 (例えば、
構文の他の重要な部分に注意してください。
- セレクターを除き、それぞれのルールセットは中括弧 (
{}
) で囲む必要があります。 - それぞれの宣言内では、コロン (
:
) を使用してプロパティと値を分離する必要があります。 - それぞれのルールセット内でセミコロン (
;
) を使用して、それぞれの宣言と次のルールを区切る必要があります。
一つのルールセットで複数のプロパティ値を変更するには、次のようにセミコロンで区切って書いてください。
p {
color: red;
width: 500px;
border: 1px solid black;
}
複数の要素の選択
複数の要素を選択して、そのすべてに一つのルールセットを適用することもできます。複数のセレクターはカンマで区切ります。たとえば、以下のようになります。
p,
li,
h1 {
color: red;
}
さまざまな種類のセレクター
セレクターにはさまざまな種類があります。上記の例では、要素セレクターを使用しており、特定の種類の要素をすべて選択しています。しかし、もっと特定の要素を選択することもできます。ここでは、より一般的なセレクターの種類を紹介します。
セレクター名 | 選択するもの | 例 |
---|---|---|
要素セレクター(タグまたは型セレクターと呼ばれることもあります) | 指定された型のすべての HTML 要素。 | p <p> を選択 |
ID セレクター | 指定された ID を持つページ上の要素です。指定された HTML ページでは、各 id 値は一意でなければなりません。 |
#my-id <p id="my-id"> または
<a id="my-id"> を選択
|
クラスセレクター | 指定されたクラスを持つページ上の要素です。同じクラスの複数のインスタンスが 1 つのページに現れることがあります。 |
.my-class <p class="my-class"> および
<a class="my-class"> を選択
|
属性セレクター | 指定された属性を持つページ上の要素です。 |
img[src] <img src="myimage.png"> は選択するが
<img> は選択しない
|
擬似クラスセレクター | 指定された要素が指定された状態にあるとき。(例えば、マウスポインターが上に乗っている(ホバー)状態。) |
a:hover <a> を、マウスポインターがリンク上にあるときのみ選択。
|
他にも様々なセレクターがあります。詳しくは、 MDN のセレクターガイドをご覧ください。
フォントとテキスト
CSS の基本をいくつか勉強しましたので、style.css
ファイルにいくつかのルールと情報を追加して、この例を見栄え良くしましょう。
HTML 本文内にテキストを配置する要素 (<h1>, <li>, <p>) のフォントの大きさを設定します。また、見出しを中央揃えにします。最後に、 2 つ目のルールセット (下記) を展開して、行の高さや文字の間隔などの設定を行い、本文のコンテンツを読みやすくしましょう。
h1 {
font-size: 60px; /* px は「ピクセル」 (pixels) の意味。60 ピクセルの高さのフォントになります */
text-align: center;
}
p,
li {
font-size: 16px;
line-height: 2;
letter-spacing: 1px;
}
px
の値はお好みで調整してください。進行中の作品は、このようになるはずです。
CSS: ボックスのすべて
CSS を書いていて気づくことがあります。それは、その多くがボックスに関するものだということです。これには、サイズ、色、位置の設定が含まれます。ページ上のほとんどの HTML 要素は、他の箱の上に置かれた箱と考えることができます。
Photo from https://www.geograph.org.uk/photo/3418115 Copyright © Jim Barton cc-by-sa/2.0
CSS のレイアウトは、主にボックスモデルに基づいています。ページ上のスペースを占める各ボックスには、次のようなプロパティがあります。
padding
: コンテンツの周囲のスペースです。以下の例では、段落テキストの周りのスペースです。border
:padding
のすぐ外側にある実線margin
: 要素の外側の周りの空間
この節では次のものを使用します。
width
(要素の幅)background-color
: 要素の内容と padding の背後にある色color
: 要素のコンテンツ (通常はテキスト) の色text-shadow
: 要素内のテキストに影を設定しますdisplay
: 要素の表示モードを設定します (これについてはまだ心配しないでください)
続けて、さらに CSS を追加していきましょう。 style.css
の一番下に、これらの新しいルールを追加し続けます。値を変えてどうなるか実験してみましょう。
ページの色を変更する
html {
background-color: #00539f;
}
このルールはページ全体の背景色に設定を行います。上記のカラーコードを、Webサイトをどんな外見にするかで選んだ色に変更しましょう。
本文のスタイル付け
body {
width: 600px;
margin: 0 auto;
background-color: #ff9500;
padding: 0 20px 20px 20px;
border: 5px solid black;
}
次は <body> 要素です。ここにはいくつかの宣言がありますので、 1 行ずつ見て行きましょう。
width: 600px;
— これにより body は常に 600 ピクセルの幅になります。margin: 0 auto;
—margin
やpadding
などのプロパティに 2 つの値を設定すると、最初の値は要素の上下の辺に影響します(この場合は0
になります)。2 番目の値は左右に影響します(ここでauto
は残った水平方向の余白を左右に均等に配分する特別な値です)。 margin の構文で説明しているように、 1 つ、2 つ、3 つ、4 つの値を使用することもできます。background-color: #FF9500;
— これは要素の背景色を設定します。このプロジェクトでは body の背景色に明るいオレンジ色を使用して、 <html> 要素の暗い青とは対照的にしました。(気軽に試してみてください。)padding: 0 20px 20px 20px;
— これはパディングに 4 つの値を設定します。これは、コンテンツの周りに少しのスペースを確保するためです。今回は body の上にパディングを設定せず、左・下・右に 20 ピクセルを設定します。値は上・右・下・左の順に設定されます。margin
と同様、 padding の構文で説明されているように、 1 つ、 2 つ、または 3 つの値を使用することもできます。border: 5px solid black;
— これは境界の太さ、スタイル、色の値を設定します。この場合は、 body の全側面に 5 ピクセルの太さの黒ベタの境界線を設定します。
メインページのタイトルの配置とスタイル付け
h1 {
margin: 0;
padding: 20px 0;
color: #00539f;
text-shadow: 3px 3px 1px black;
}
body の上部にひどい隙間があることに気づいたかもしれません。これは CSS をまったく適用していなくても、ブラウザーが(他のものの中で) <Heading_Elements", "h1> 要素に既定のスタイルを適用するためです。それは悪い考えのように見えるかもしれませんが、スタイルのないページにも一定の読みやすさを求めるためのものです。隙間をなくすために、 margin: 0;
を設定して既定のスタイルを上書きします。
次に見出しの上下のパディングを 20 ピクセルに設定します。
続いて、見出しテキストが HTML の背景色と同じ色になるように設定します。
最後に、 text-shadow
は要素のテキストコンテンツに影を適用します。 4 つの値は次のとおりです。
- 最初はピクセル値で、影のテキストからの水平オフセット、どれだけ横に移動するかを設定します。
- 2 番目はピクセル値で、影のテキストから垂直オフセット、どれだけ下に移動するかを設定します。
- 3 番目のピクセル値で、影をぼかす半径を設定します。値が大きいほどぼやけた影を生成します。
- 4 番目の値は、影の基本色を設定します。
いろいろな値を試して、表示方法の変化を確認してみてください。
画像のセンタリング
img {
display: block;
margin: 0 auto;
}
次に、画像を中央に配置して見栄えを良くします。本文のときと同じように、 margin: 0 auto
のトリックを使うこともできます。しかし、 CSS を機能させるために追加の設定が必要になる違いがあります。
<body> はブロック要素であるため、ページの中でスペースを占めます。ブロック要素は、マージンやその他の余白を開ける値を適用することができます。一方、画像はインライン要素です。インライン要素にマージンやその他の余白を開ける値を適用することはできません。画像にマージンを適用するには、display: block;
を使用して画像にブロックレベルの動作を指定する必要があります。
Note 上記の手順は、本体に設定されている幅 (600 ピクセル) よりも小さい画像を使用していることを前提としています。画像が大きい場合、それは本文をあふれ、ページの残りの部分にはみ出します。これを修正するには、1) 画像編集ソフトを使用して画像の幅を縮小するか、2) CSS を使用して、
width
プロパティでより小さな値を<img>
要素に設定し、画像の大きさを変更します。
Note
display: block;
や、ブロックレベル/インラインの区別がまだ理解できなくても心配しないでください。 CSS の勉強を続けていくうちに意味が分かってくるはずです。さまざまな display の値の違いについて詳しくは、 MDN の display のリファレンスページを参照してください。
まとめ
完成すると次のようなページが表示されます。
もし途中で行き詰まってしまったら、「サンプルコード」と見比べてみましょう。
― この文書は © 2023 MDN Web Docsプロジェクト協力者 クリエイティブ・コモンズ CC BY SA 2.5 ライセンスのもとに利用を許諾されています。 元の文書: https://developer.mozilla.org/ja/docs/Learn/Getting_started_with_the_web/JavaScript_basics
JavaScriptの基本
JavaScriptは世界で最も普及しているプログラミング言語です1。
JavaScriptは強力なプログラミング言語であり、Webサイトに対話操作を追加することができます。 ブレンダン・アイク (Brendan Eich) によって考案されました。
JavaScript は汎用性が高く、初心者にもやさしいものです。経験を積めば、ゲーム、 2D や 3D のアニメーション、包括的なデータベース駆動型のアプリなどが作れるようになります。
JavaScript は比較的コンパクトですが、一方でとても柔軟性があります。開発者は JavaScript 言語のコアをベースに多種多様なツールを作成し、最小限の労力で膨大な様々な機能を利用できるようにしました。例えば以下のようなものがあります。
- ブラウザーのアプリケーションプログラミングインターフェイス (API)。Webブラウザーに組み込まれた API により、動的な HTML の作成、 CSS スタイルの設定、ユーザーのWebカメラからの動画ストリームの収集や操作、三次元グラフィックや音声サンプルの生成などの機能を提供します。
- 開発者が他のコンテンツプロバイダーのサイト(Twitter や Facebook など)から機能を組み込むことを可能にする、サードパーティの API。
- すばやくサイトやアプリケーションを構築することができ、 HTML に組み込み可能なサードパーティのフレームワークやライブラリー。
コアの JavaScript 言語が上記のツールとどのように違うのか、その詳細を紹介することは、 JavaScript の軽い入門者向けの書籍であるこの記事の範囲外です。詳細は MDN の JavaScript 学習領域や、 MDN の他の部分で詳しく学ぶことができます。
以下では、コア言語のいくつかの側面について紹介します。またブラウザーの API 機能についてもいくつか説明します。楽しみましょう!
JetBrainsのレポート https://www.jetbrains.com/ja-jp/lp/devecosystem-2023/javascript/
"Hello world!" の例
JavaScript は、最も人気のある現代のWeb技術のひとつです。 JavaScript のスキルが上がれば、Webサイトのパワーと創造性は新たな次元に入るでしょう。
しかし、 JavaScript を使いこなせるようになるのは HTML や CSS よりも少し難しいです。小さなものから始め、小さく確実な手順で作業を続ける必要があるかもしれません。始めるにあたって、"hello world!" を表示する例(基本的なプログラミング例の標準)を作りながら、基本的な JavaScript をページに追加する方法を紹介しましょう。
-
最初にテストサイトに行き、
scripts
という名前の新しいフォルダーを作成してください。それから、この scripts フォルダーの中にmain.js
という新しいファイルを作成して保存してください。 -
index.html
ファイルの</body>
終了タグの直前に新しい行で、以下の新しい要素を追加してください。<script src="scripts/main.js"></script>
-
これは CSS の <link> 要素の時の作業と基本的に同じです。これは JavaScript をページに適用するので、(CSS の時と同じく、ページ上の何に対しても) HTML に影響を与えることができます。
-
main.js
ファイルに次のコードを追加してください。const myHeading = document.querySelector("h1"); myHeading.textContent = "Hello world!";
-
最後に、 HTML と JavaScript を書いたファイルを保存したことを確認し、ブラウザーで
index.html
を読み込んでください。
Note 上記の説明で
<script>
要素を HTML ファイルの末尾付近に置いたのは、ブラウザーがファイルに現れる順番でコードを読み込むからです。JavaScript が先に読み込まれ、まだ読み込まれていない HTML に影響を与えることになると、問題が生じる可能性があります。 JavaScript を HTML ページの下部に配置することは、この依存関係に対応する一つの方法です。その他の方法については、スクリプトの読み込み方針をご覧ください。
何が起きたのか
JavaScript を使用して、見出しの文字列が Hello world! に変更されました。最初に document.querySelector() 関数を使用して見出しを選択し、 myHeading
と呼ばれる変数に格納しています。これは CSS のセレクターを使用するのととてもよく似ています。要素に対して何かをしたくなったら、まずその要素を選択する必要があります。
その後、 myHeading
変数の textContent プロパティ(見出しの内容を表す)の値を Hello world! に設定します。
Note 上の例で使用した機能はどちらもドキュメントオブジェクトモデル (DOM) API の一部であり、これを使って文書を操作することができます。
言語の短期集中コース
どのように動作するかをよりよく理解できるように、 JavaScript 言語の基本機能のいくつかを説明しましょう。これらの機能はすべてのプログラミング言語に共通しているので、これらの基本をマスターすれば、ほとんど何でもプログラムできるようになります!
Note この記事では、 JavaScript コンソールにサンプルコードを入力して、何が起こるのかを確認してみます。 JavaScript コンソールの詳細については、開発者ツールに慣れる (Firefoxの場合は ブラウザー開発ツールを探る)を参照しましょう。
変数
変数は、値を格納できる入れ物です。まず、 let
というキーワードと、その後に任意の名前を指定することで、変数を宣言します。
let myVariable;
Note 行末のセミコロンは文が終わる場所を示します。単一の行で複数の文を区切る場合には絶対に必要です。しかし、個々の文の末尾に置くことが良い習慣だと信じている人もいます。使用する場面と使用しない場合については他のルールもあります。詳しくは Your Guide to Semicolons in JavaScript を参照してください。
Note 変数にはほとんど何でも名前を付けることができますが、いくらかの制約があります(変数の命名規則についてはこの記事を参照してください)。自信がない場合は、有効かどうか変数名を調べることができます。
Note JavaScript は大文字と小文字を区別します。
myVariable
はmyvariable
とは異なる変数です。コードで問題が発生している場合は、大文字・小文字をチェックしてください。
変数を宣言したら、以下のように値を割り当てることができます。
myVariable = "Bob";
好みに応じて、両方の操作を同一の行で行うことができます。
let myVariable = "Bob";
変数の値は、名前で呼び出すだけで取得することができます。
myVariable;
変数に値を代入した後で、変更することもできます。
let myVariable = "Bob";
myVariable = "Steve";
なお、変数は様々なデータ型の値を保持することもできます。
変数 | 説明 | 例 |
---|---|---|
文字列 | 一連のテキストで、文字列と呼ばれます。値が文字列であることを示すには、単一引用符または二重引用符で囲む必要があります。 | let myVariable = 'Bob'; または let myVariable = "Bob"; |
数値 | 数値です。数値は引用符で囲みません。 | let myVariable = 10; |
論理型 |
論理値です。これは真か偽かの値です。 true と false は特別なキーワードで、引用符は必要ありません。
|
let myVariable = true; |
配列 | 単一の参照で複数の値を格納できる構造です。 |
let myVariable = [1,'Bob','Steve',10]; 配列の各メンバーは次のように参照します。 myVariable[0] ,
myVariable[1] , など。
|
オブジェクト | 基本的には何でも格納できます。 JavaScript のすべてがオブジェクトであり、変数に格納することができます。学ぶ際にはこれを覚えておいてください。 |
let myVariable = document.querySelector('h1'); 上記のすべての例も同様です。 |
ではなぜ変数が必要なのでしょうか。何か面白いプログラミングをするには変数が必要です。値が変更できなければ、挨拶のメッセージをパーソナライズしたり、画像ギャラリーに表示されている画像を変更するなどの動的な操作ができないのです。
コメント
コメントは、ブラウザーから無視される、コードの間に入れられた短いテキストスニペットです。CSS と同じように、JavaScript のコードではコメントを付けることができます。
/*
挟まれているすべてがコメントです。
*/
コメントに改行が含まれていない場合、次のように 2 つのスラッシュの後ろに記載する方が簡単です。
// これはコメントです
演算子
演算子は、2 つの値 (または変数) に基づいて結果を生成する数学的な記号です。次の表では、JavaScript コンソールで試してみるいくつかの例とともに、最も単純な演算子をいくつか見ることができます。
演算子 | 説明 | 記号 | 例 |
---|---|---|---|
加算 | 2 つの数値を足し合わせたり、 2 つの文字列を結合したりします。 | + |
6 + 9;
|
減算、乗算、除算 | 基本的な数学の計算を実施します。 | - , * , / |
9 - 3;
|
代入 | すでに出てきました。変数に値を割り当てます。 | = |
let myVariable = 'Bob'; |
厳密等価 |
これは、2 つの値が等しく、かつデータ型が同じであるかどうかを調べます。
true /false (論理値)の結果を返します。
|
=== |
let myVariable = 3;
|
否定、非等価 |
その後にあるものと論理的に反対の値を返します。たとえば true を false に換えます。等価演算子と一緒に使用されると、否定演算子は 2 つの値が等しくないかどうかを調べます。
|
! , !== |
「否定」の場合は次の通りです。基本の式が
「非等価」は異なる構文ですが、基本的に同じ結果になります。ここでは「
|
他にも演算子はもっとたくさんありますが、今のところはこれで十分です。全体の一覧については、式と演算子を参照してください。
Note データ型を混在させると、計算を実行するときに奇妙な結果になる可能性があるため、変数を正しく参照し、期待通りの結果を得るように注意してください。例えばコンソールに
'35' + '25'
と入力してみてください。期待通りの結果にならないのはなぜでしょうか。引用符は数字を文字列に変換するので、数字を加算するのではなく、文字列を連結する結果になったのです。35 + 25
を入力すれば、正しい結果が得られます。
条件分岐
条件分岐は、ある式が true を返すかどうかをテストし、その結果次第でそれぞれのコードを実行するコード構造です。条件分岐のよくある形は if...else
文です。例えば以下の通りです。
let iceCream = "チョコレート";
if (iceCream === "チョコレート") {
alert("やった!チョコレートアイス大好き!");
} else {
alert("あれれ、でもチョコレートが好きなのに......");
}
if ()
の中の式が条件です。ここでは等価演算子を使用して、変数 iceCream
とチョコレート
という文字列を比較し、2 つが等しいかどうかを調べています。この比較が true
を返した場合、コードの最初のブロックが実行されます。比較が真でない場合、最初のブロックはスキップされ、 else
文の後にある 2 番目のコードブロックが代わりに実行されます。
関数
関数は、再利用したい機能をパッケージ化する方法です。プロシージャが必要なときは、毎回コード全体を書くのではなく関数名を使って関数を呼び出すことができます。すでにいくつかの関数の仕様を見てきました。例えば次のようなものです。
let myVariable = document.querySelector("h1");
alert("hello!");
これらの関数、 document.querySelector
と alert
は、必要なときにいつでも使えるようブラウザーに組み込まれています。
もし変数名に見えるものがあったとしても、その後に括弧 ()
が付いていれば、おそらくそれは関数です。関数は普通、仕事をするのに必要な小さなデータである引数を取ります。引数は括弧の中に入れ、複数の引数がある場合はカンマで区切ります。
例えば、 alert()
関数はブラウザーのウィンドウにポップアップボックスを表示しますが、ポップアップボックスに何を書き込むかを関数に指示するために、文字列を引数として渡す必要があります。
嬉しいことに、自分で関数を定義することができます。次の例では、引数として 2 つの数値をとり、それらを乗算するという単純な関数を記載します。
function multiply(num1, num2) {
let result = num1 * num2;
return result;
}
上記の関数をコンソールで実行し、いくつかの引数を指定してテストしてみてください。例えば次のようなものです。
multiply(4, 7);
multiply(20, 20);
multiply(0.5, 3);
Note
return
文はresult
の値を関数内から関数の外に戻すことをブラウザーに指示し、それを利用できるようにします。これが必要な理由は、関数内で定義された変数が、その関数内でしか利用できないためです。これは変数のスコープと呼ばれています(変数のスコープのより詳しい説明をお読みください)。
イベント
Webサイトを本当にインタラクティブにするには、イベントが必要です。イベントは、ブラウザーの中で起きていることを検出し、その応答としてコードを実行するコード構造です。最も分かりやすい例は click イベントで、マウスで何かをクリックするとブラウザーによって発行されるものです。これを実行するには、コンソールに以下のように入力してから、現在のWebページ上をクリックしてください。
document.querySelector("html").addEventListener("click", function () {
alert("痛っ! つつかないで!");
});
要素にイベントハンドラーを取り付ける方法はいくつもあります。ここでは <html> 要素を選択しています。そして、addEventListener()
関数を呼び出し、待ち受けるイベントの名前 ('click'
) とイベントが発生したときに実行する関数を渡します。
先ほど addEventListener()
に渡した関数は、名前を持たないので無名関数と呼ばれます。無名関数の書き方として、アロー関数と呼ばれるものがあります。アロー関数は () =>
を function ()
の代わりに使用します。
document.querySelector("html").addEventListener("click", () => {
alert("痛っ! つつかないで!");
});
Webサイトの例を膨らませる
さて、 JavaScript の基本のおさらいが終わったところで、例題のサイトに新しい機能を追加してみましょう。
先に進む前に、 main.js
ファイルの現在の内容を削除して、空のファイルを保存してください。そうしないと、 "Hello world!" の例で使用した既存のコードが、これから追加する新しいコードと衝突してしまいます。
画像の切り替えの追加
このセクションでは、 DOM API 機能をもっと使用して、サイトに画像を追加しましょう。画像をクリックすると JavaScript を使用して 2 つの画像を切り替えることができます。
-
まずサイトに掲載したいと思う別な画像を見つけてください。最初の画像と同じサイズか、できるだけ近いものを使用してください。
-
この画像を
images
フォルダーに保存してください。 -
この画像の名前を firefox2.png に変更してください。
-
main.js
ファイルに次の JavaScript を入力してください。const myImage = document.querySelector("img"); myImage.onclick = () => { const mySrc = myImage.getAttribute("src"); if (mySrc === "images/firefox-icon.png") { myImage.setAttribute("src", "images/firefox2.png"); } else { myImage.setAttribute("src", "images/firefox-icon.png"); } };
-
index.html
をブラウザーに読み込みます。画像をクリックすると、もう一方の画像に変わるでしょう。
何が起こったのでしょうか。<img> 要素への参照を変数 myImage
に格納しました。次に、この変数の onclick
イベントハンドラープロパティに、名前のない関数(「無名」関数)を代入しました。そうすれば、この要素がクリックされるたびに次の動きをします。
-
画像の
src
属性の値を取得します。 -
条件分岐を使って、
src
の値が元の画像のパスと等しいかどうかをチェックします。- そうであれば、
src
の値を 2 番目の画像へのパスに変更し、もう一方の画像が強制的に <img> 要素の中に読み込まれるようにします。 - そうでない(すでに変更されている)場合、
src
の値を元の画像のパスに戻して、元の状態に戻ります。
- そうであれば、
パーソナライズされた挨拶メッセージの追加
次に、もう 1 つの小さなコードを追加し、ユーザーがサイトにアクセスしたときに、ページの表題をパーソナライズされた挨拶メッセージに変更してみましょう。この挨拶メッセージは、ユーザーがサイトを離れて後で戻った時にも保存されるようにします。Web Storage API を使用して保存しましょう。したがって、必要な時にいつでもユーザーと挨拶メッセージを変更できるオプションも用意しましょう。
-
index.html
では、 <script> 要素の直前に次の行を追加します。<button>ユーザーを変更</button>
-
main.js
では、次のコードを下記のとおりにファイルの最後に配置します。これは新しいボタンと見出しへの参照を変数に格納します。let myButton = document.querySelector("button"); let myHeading = document.querySelector("h1");
-
パーソナライズされた挨拶を設定する以下の関数を追加しましょう。まだ何も起こりませんが、すぐに修正します。
function setUserName() { const myName = prompt("あなたの名前を入力してください。"); localStorage.setItem("name", myName); myHeading.textContent = `Mozilla is Cool, ${myName}`; }
setUserName()
関数では、prompt()
関数を使用して、alert()
のようにダイアログボックスを表示しています。しかし、prompt()
はalert()
とは異なり、ユーザーにデータを入力するよう求め、ユーザーが OK を押した後に変数にそのデータを格納します。この場合、ユーザーに名前を入力するよう求めます。次に、localStorage
と呼ばれる API を呼び出すことで、ブラウザーにデータを格納して後で受け取ることができます。 localStorage のsetItem()
関数を使って、'name'
と呼ばれるデータを作成し、myName
に入っているユーザーから入力されたデータを格納します。最後に、見出しのtextContent
に文字列と新しく格納されたユーザーの名前を設定します。 -
以下のような条件ブロックを追加します。最初に読み込んだときにアプリを構造化するので、これを初期化コードと呼ぶこともできます。
if (!localStorage.getItem("name")) { setUserName(); } else { const storedName = localStorage.getItem("name"); myHeading.textContent = `Mozilla is Cool, ${storedName}`; }
このブロックでは、最初に
name
のデータが存在しているかどうかをチェックするために否定演算子(!
で表される論理否定)を使用しています。存在しない場合は、作成するためにsetUserName()
関数が実行されます。存在する場合は(つまり、以前の訪問時にユーザーが設定した場合)、getItem()
を使用して格納された名前を受け取り、setUserName()
の中で行ったのと同様に、見出しのtextContent
に文字列とユーザーの名前を設定します。 -
最後に、以下の
onclick
イベントハンドラーをボタンに設定します。クリックすると、setUserName()
関数が実行されます。これでユーザーがボタンを押すことで、好きな時に新しい名前を設定できるようになります。myButton.onclick = () => { setUserName(); };
ユーザー名か null か
この例を実行してユーザー名を入力するダイアログボックスが出たとき、キャンセルボタンを押してみてください。結果として "Mozilla is cool, null" というタイトルが表示されるでしょう。これはプロンプトをキャンセルしたときに、値が null
、つまり値がないことを示す JavaScript の特殊な値に設定されるためです。
また何も入れずに OK を押してみてください。結果として "Mozilla is cool," というタイトルが表示され、これは理由が明白です。
この問題を避けるには、ユーザーが null
や空白の名前を入力していないかチェックするよう、setUserName()
関数を書き換えます。
function setUserName() {
const myName = prompt("あなたの名前を入力してください。");
if (!myName) {
setUserName();
} else {
localStorage.setItem("name", myName);
myHeading.textContent = `Mozilla is Cool, ${myName}`;
}
}
人間の言葉で言うと、 myName
に値がない場合や、null
の場合、 最初から setUserName()
を実行します。値がない場合(上記の式が真でない場合)には、localStorage
に値を設定して、見出しのテキストにも設定します。
まとめ
最後までこの記事の手順に従った場合は、最終的に次のようなページが表示されているでしょう。
もし途中で行き詰まってしまったら、「サンプルコード」と見比べてみましょう。
Web
WebとWebブラウザーについてまとめます。といっても、仕組みがわかると面白いかも、くらいの気持ちで気楽にいきましょう。
Webとは
"This is for everyone"
Webは情報共有とコミュニケーションのためのプラットフォームです。 Web上ではソーシャルメディア、ビデオストリーミング、オンラインショッピングなど様々な活動が行われます。(便利ですよね。)
World Wide Web
― 画像: https://worldwideweb.cern.ch/browser/ より
これは世界初のWebブラウザーWorldWideWebの画像です。
World Wide Web (Web) は、1989年に分散型ハイパーテキストシステム (distributed hypertext system)としてティム・バーナーズ・リーによって提案されたアイデアが元になっています。世界中に張り巡らされた蜘蛛の巣を連想して名付けられました。
Note
中央集権型 (centralized) と 非中央集権型 (decentralized) と 分散型 (distributed)
― 画像: ポール・バラン (1964) On Distributed Communications Networks よりWebは分散型のシステムです。中央集権型のシステムではありません。Web上で何か活動するとき、中央の機関からの許諾は一切必要ありません。いつでも、どこでも、誰でも自由に使うことができます。
Webブラウザー
Webブラウザーは、Webページの取得・描画を行うソフトウェアです。
代表的なWebブラウザーとしては、Google Chrome、Safari、Mozilla Firefox、Microsoft Edgeなどが挙げられます。
Webの標準化
主に3つの標準化団体が関わっています。
- IETF (Internet Engineering Task Force)
- W3C (The World Wide Web Consortium)
- WHATWG (Web Hypertext Application Technology Working Group)
IETFはインターネットに関する全般的な技術、約束事、コミュニティで共有すべき事柄の管理を担っています。それらは RFC (Request for Comments) と呼ばれる形式で記録されています。
W3CとWHATWGはWebに関する仕様の管理を担っています。具体的にはW3CはCSSなど、WHATWGはHTML関連の仕様などを発行しています。 WHATWGの発行している仕様はIETFやW3Cの仕様とは異なり内容が確定することはありません。HTML Living Standardはその時点が常に最新版の標準仕様となっており、継続的に更新され続けています。
いずれの仕様もWeb上で公開されており、無償で閲覧可能、誰でも参加可能、自由に実装可能です。
ポイント
- Web … 分散型ハイパーテキストシステム
- Webブラウザー … Webページの取得・描画を行うソフトウェア
- Webの標準化 … 無償で閲覧可能、誰でも参加可能、自由に実装可能
Webの仕組み
Webの誕生から現在に至るまでWeb上で出来ることやその役割は大きく変わりました。 しかし、それを支える基本的な仕組みと構成要素は実はあまり変わっていません。
Webはこれらの要素に支えられています。
Note
変わり続けるルール多くのルールを覚えることは決して重要ではありません。 なぜなら現実の問題は複雑でそれに合わせてルールも変わり続けていくものだからです。 大切なのは解決したい問題への理解を深めていくことなのです。 何を解決するためのルールなのか一緒に考えていきましょう。(この後も退屈な説明が続きますがどうかお付き合いください。)
例えばこれらの仕様はいずれも常に最新版の標準仕様となっており継続的に更新され続けています。
Webページ
― 画像: JavaScript とは - Web開発を学ぶ | MDN より
Webページはこれらの要素に支えられています。
- HTML … Webページの構造を記述するための言語
- CSS … Webページの見た目を記述するための言語
- JavaScript … プログラミング言語
ポイント
- Web … URL/HTTP/コンテンツ
- Webページ … HTML/CSS/JavaScript
参考文献
- 太田 良典、中村 直樹「HTML解体新書」
- HTMLの基本概念の説明を参考にしています
- 渋川よしき「Real World HTTP 第2版」
- HTTPの技術的な説明の参考にしています
- 渋川よしき「Real World HTTP ミニ版」は無料で読めるのでお手軽です
- Dev.Opera — HTTP — an Application-Level Protocol
- HTTPの概要を説明するために参考にしています
- 米内貴志「Webブラウザセキュリティ」
- Webブラウザーのセキリティ機構の説明を参考にしています
URL - Uniform Resource Locator
URLはインターネット上のリソースの位置を特定するための文字列です。 住所と似ています。
URLの仕様からいくつか具体例を挙げます。
例:
https://example.com/
https://localhost:8000/search?q=text#hello
urn:isbn:9780307476463
file:///ada/Analytical%20Engine/README.md
これらはいずれもURLです。
URLを使ってリンクさせることができます。
ユニフォーム (uniform) と名前にあるのは、統一的なルールがあります、ということです。 Web上で「〇〇にアクセスしたい」と思ったときみんなで使える同じ表現があったほうが便利というわけですね。
ではURLにはどういうルールがあるのか詳しく見ていきましょう。
スキーム (Scheme)
URLの種別や性質を意味します。
https://example.com/
この例でいうと、先頭から :
までの文字列 https
が「スキーム」です。住所の例で言うと、郵便を表す記号「〒」の役割と似ています。URLはスキームごとにその書式が異なります。
Note
インターネット上で利用可能なURLスキームの一覧Uniform Resource Identifier (URI) Schemes
インターネット上で利用可能なURLスキームの一覧はIANA (Internet Assigned Numbers Authority)によって管理されています。
https
スキームは Hypertext Transfer Protocol Secure (RFC 9110) を意味します。その後に文字列 ://
が続きます。
https
スキームのURLの場合は、その後に「ホスト (Host)」「ポート (Port)」「パス (Path)」「クエリー (Query)」「フラグメント (Fragment)」と続きます。
Note
http
とhttps
前者は "Hypertext Transfer Protocol"、後者は "Hypertext Transfer Protocol Secure" を意味するスキームです。 "Secure" と付いているのは、必ず TLS (Transport Layer Security) の上でやり取りを行います、という意味です。 最近
http://...
から始まるURLはあまり見かけないかと思います。 これはHTTPのセキュリティとプライバシーの問題が広く知られ、代わりにHTTP over TLSが使われるようになったためです。 TLSを使うことによってクライアント・サーバー間の通信が暗号化され、もし仮に傍受されても第三者による改ざんや解析は以前より難しくなりました。
ホスト (Host)
郵便番号と住所みたいなものです。「ポスト」じゃないですよ。
https://example.com/
この例でいうと、example.com
の部分が「ホスト」です。
ホストはドメイン名またはIPアドレスです。
ドメイン名を見かけることが多いかと思います。
Note
ドメイン名インターネットに接続しているすべてのコンピューターにはIPアドレスが割り当てられています。 ドメイン名はそうしたIPアドレスに人間が読めるように別の名前を付けたものです。 ドメイン名は Domain Name System (DNS) によって支えられています。 Internet Corporation for Assigned Names and Numbers (ICANN) を中心とした複数のドメイン管理事業者によって管理されており、世界中で使うことができるようになっています。
例: Google Public DNS に
example.com
を問い合わせる例"Answer": [ { "name": "example.com.", "type": 28 /* AAAA */, "TTL": 13460, "data": "2606:2800:220:1:248:1893:25c8:1946" } ]
ドメイン名
example.com
はIPアドレス[2606:2800:220:1:248:1893:25c8:1946]
の別名ですよ、という意味です。
ポート (Port)
「ポート」が書いてあるURLは普段あまり見かけないかもしれませんね。 でもインターネット上で通信するとき必ず登場します。存在するからには一応紹介しておきます。
ホストの後にはポートを書くことができます。
ホストと :
文字の後にポート番号を書きます。
省略すると https
スキームの場合は 443
が割り当てられています。
例えばこれらのURLは同じ意味です。
https://example.com/
https://example.com:443/
この場合どちらも 443
ポートを意味します。
オリジン (Origin)
スキーム・ホスト・ポートをまとめて扱うことがあります。 具体的にはセキュリティ上の理由から送信元の同一性を判定するケースです。 このとき使われるのが「オリジン」です。
https://localhost:8000/search?q=text#hello
例えばこの例では (https
, localhost
, 8000
) の3つの組がオリジンです。
オリジンは https://localhost:8000
のように表現します。
JavaScriptでは location.origin
でオリジンを取得できます。
Note
Webブラウザーのセキリティ機構Webブラウザーには同一オリジンポリシーと呼ばれる保護機構があり、オリジン間のアクセスは原則禁止されています。 異なるオリジン間でのアクセスを許可するには、オリジン間リソース共有 (Cross-Origin Resource Sharing, CORS) の仕組みを使います。 CORSはリソースを提供する人が同一オリジンポリシーを緩和しオリジン間のアクセスを許可するための仕組みです。
パス (Path)
/
文字で区切られた文字列が続きます。これが「パス」です。ホストの中のリソースの場所を意味します。
/
は日本語でいう「の」みたいなものです。
階層構造を表現します。
https://example.com/
この場合パスは /
です。
https://example.com/foo/bar
この場合パスは /for/bar
です。
ちなみにJavaScriptでは location.pathname
でパスを取得できます。
クエリー (Query)
?
文字で区切られた文字列が続くことがあります。場合によっては =
や &
が含まれます。これは「クエリー」です。
https://localhost:8000/search?q=text#hello
例えばこの例では q=text
がクエリーです。
=
は日本語でいう「は」みたいなものです。
Google検索の例: https://www.google.com/search?q=answer+to+life+the+universe+and+everything
この場合クエリーは q=answer+to+life+the+universe+and+everything
です。
q
は "answer to life the universe and everything" ですよ、という意味です。
JavaScriptでは location.search
でクエリーを取得できます。
フラグメント (Fragment)
#
文字で区切られた文字列が続くことがあります。これは「フラグメント」です。
URLの末尾にフラグメントがあるとき、そのリソースの中の一部分を意味します。
HTMLの場合はフラグメントと id
属性の名前が一致するときその箇所を指定することができます。
https://localhost:8000/search?q=text#hello
例えばこの例では hello
がフラグメントです。
JavaScriptでは location.hash
でフラグメントを取得できます。
ポイント
- URLはインターネット上のリソースの位置を特定するための識別子
https://
から始まるURLはhttps
スキームのURLhttps
スキームのURLの構成要素 … ホスト、ポート、パス、クエリー、フラグメント
HTTP - Hypertext Transfer Protocol
HTTPはWebの転送用のプロトコルです。
URLがあればそのリソースがWeb上の「どこに」あるか知ることができます。 ではそのリソースには「どのように」アクセスしたらよいのでしょうか。
https
スキームや http
スキームのURLに対応するリソースにアクセスする手順、それがHTTPです。
プロトコル
― この画像は © 2012 Karl Dubost クリエイティブ・コモンズ CC BY 3.0 ライセンスのもとに利用を許諾されています。
二者間でのコミュニケーションが成立するためには3つの要素が含まれています。
- シンタックス (コードの文法)
- セマンティクス (コードの意味)
- タイミング (速度合わせと順序付け)
「挨拶」を例に考えてみましょう。 腰を曲げるジェスチャー、これはお辞儀のためのシンタックスです。日本ではそういう慣習ですね。お辞儀をすることで「どうも、こんにちは」という意味づけが行われます。これはセマンティクスです。二者間で特定のタイミングでこれらが発生したとき、一連の出来事として成立します。どちらもお辞儀をし、お互いに理解することによって「挨拶」として成立した、となるわけです。
Web上でのやり取りも同じです。 HTTPはサーバー・クライアントの二者関係で行われます。 クライアントはサーバーに対して要求を送り、クライアントからの要求を受け取るとサーバーは応答を返します。
HTTPの仕様にある具体例を挙げます。 次のようなコードの送受信を行います。
クライアントリクエスト (クライアント側からサーバー側への送信):
GET /hello.txt HTTP/1.1
User-Agent: curl/7.64.1
Host: www.example.com
Accept-Language: en, mi
サーバーレスポンス (サーバー側からクライアント側への送信):
HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain
Hello World! My content includes a trailing CRLF.
構成要素は4つ。
- リクエストライン (Request Line)
- フィールド (Fields)
- ステータスコード (Status Codes)
- コンテンツ (Content)
詳しく見ていきましょう。
リクエストライン (Request Line)
クライアントリクエストの1行目の GET /hello.txt HTTP/1.1
の部分は、リクエストライン (Request Line) と呼ばれます。どこに、どのような方法でアクセスしたい、とサーバーに伝えるためのものです。
クライアントリクエスト:
GET /hello.txt HTTP/1.1
この例はURL http://www.example.com/hello.txt
にアクセスするためのクライアントリクエストです。GET
メソッドでパス /hello.txt
へのアクセスを要求しています。
GET
メソッドは取得するために使われる最も基本的なメソッドで、リンクをクリックしたときやWebブラウザーのアドレスバーにURLを入力したとき送信されます。Webでのやり取りはこのリクエストラインで始まる文字列をWebサーバーに伝えるところから始まります。
Note
HTTP/1.1 と HTTP/2HTTP/1.1は1995年に公開され、2022年に最新版に改定されました。 HTTP/1.1は現在も使われ続けています。 一方、HTTP/2は2022年に公開されました。 HTTP/2はHTTP/1.1とは異なり複数のメッセージを同時に扱える、コンピューターにとってより効率的な形式のシンタックスが特徴の新しい仕様です。 HTTP/2ではリクエストラインの代わりに一貫してフィールドを使うなどHTTP/1.1と文法が大きく異なりますがその意味は全く変わりません。
GET /resource HTTP/1.1 HEADERS Host: example.org ==> + END_STREAM Accept: image/jpeg + END_HEADERS :method = GET :scheme = https :authority = example.org :path = /resource host = example.org accept = image/jpeg
フィールド (Fields)
:
文字で区切られた行が続きます。これは「フィールド (Fields)」です。リクエストとレスポンスに関連する付帯情報を意味します。
Host: www.example.com
例えばこの場合、送信先 Host
(ホスト) は www.example.com
ですよ、という意味です。
ステータスコード (Status Codes)
― 画像: HTTP Cats より
「ステータスコード (Status Codes)」はそのリソースの存在やアクセス可否などをサーバーが伝えるためのものです。 サーバーはレスポンスを返すとき、最初にステータスコードを返します。
サーバーレスポンス:
HTTP/1.1 200 OK
この例ではステータスコード 200
を返しています。
ステータスコードは100〜599までの3桁の整数で表されます。
レスポンスはステータスコードの100の位で大きく分類されます。
- 1xx (情報): リクエストを受信しました。プロセスを続行します。
- 2xx (成功): リクエストは正常に受信、理解され、受け入れられました。
- 3xx (リダイレクト): リクエストを完了するにはさらにアクションを実行する必要があります。
- 4xx (クライアントエラー): リクエストに不正な構文が含まれているか、リクエストを実行できません。
- 5xx (サーバーエラー): サーバーは有効なリクエストを実行できません。
Note
418 I'm a teapot私はティーポットなのでコーヒーを入れることを拒否しました、という意味のステータスコードです。 1998年のエイプリルフールに公開されました。 現在でもステータスコード
418
は IANA HTTP Status Code Registry によって管理されています。
コンテンツ (Content)
フィールドが終わり「コンテンツ (Content)」が続きます。 コンテンツはHTML、画像、動画、あらゆるデータです。
ポイント
- HTTPはWebの転送用のプロトコル
- HTTPはクライアントからのリクエストとサーバーからのレスポンスによってやり取りを行う
- HTTPの構成要素 … リクエストライン/フィールド/ステータスコード/コンテンツ
HTML
HTMLはWebページの構造を記述するための言語です。
「どこに」「どのように」アクセスするかというと、Webでは「URLに」「HTTPで」アクセスするわけですね。 では一体「何を」Webブラウザーは見せているのでしょうか。 それは「HTML」です。(この入門ガイドもそうですよ。)
もともとHTMLは主に科学文書の意味や構造を正確に記述するための言語として設計されました。 現在では、あらゆる文書やアプリの記述に応用されています。
文法と意味
HTMLはマークアップ言語 (Markup Language)と呼ばれるカテゴリーの言語です。 HTMLの仕様から具体的なコードの例を挙げます。
例:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Sample page</title>
</head>
<body>
<h1>Sample page</h1>
<p>This is a <a href="demo.html">simple</a> sample.</p>
<!-- this is a comment -->
</body>
</html>
「タグ (Tag)」と呼ばれる印でコンテンツのかたまりを囲みます。 このかたまりは「要素 (Element)」と呼ばれます。
― 画像: 「HTML の基本」より
要素の中に別の要素を含めることもあります。
<p>This is a <a href="demo.html">simple</a> sample.</p>
この例では<p>: 段落要素の中に<a>: アンカー要素が含まれています。 リンクが含まれている文、その文を含む段落、という構造なわけです。
やってみよう!
基本的なルールが分かってきたところで、さっそく遊んでみましょう!
<p>ここは段落なのですよ。</p> <p>HTMLを使えばインターネット上のあらゆるコンテンツに<a href="https://kou029w.github.io/intro-to-web-dev/web/html.html">リンク</a>できるのです。</p>
MDNで調べてみよう
MDN (MDN Web Docs) は、HTML、CSS、JavaScriptなどWeb技術に関するあらゆる文書を網羅的にまとめているサイトです。オープンソースで提供されており、誰でも自由に貢献することができます。MDNにアクセスすればWebブラウザーに組み込まれているあらゆるAPIの仕様やその機能を調べることができます。
Googleなどの検索エンジンで「MDN [調べたいキーワード]」または「site:developer.mozilla.org [調べたいキーワード]」を検索してみましょう。
ポイント
- MDN … Webブラウザーに組み込まれているAPIの仕様や機能を調べることができる
API - Application Programming Interface
システムには情報やエネルギーなど外部とのやりとりするための境界面があり、それを「インターフェース」と呼びます。
API (Application Programming Interface) とは、アプリケーションソフトウェアのインターフェースを指す概念です。
家電製品を例に考えてみましょう。 家電製品はそのシステムの外部から供給された電力を消費して仕事をします。 このとき外部との境界には外部から電力を供給するためのインターフェースが存在します。 それはコンセントですね。 コンセントには定格電圧や形状など規格があります。 インターフェースとはそういったルールのことです。 家電製品にはコンセントがあるので専門的な技能が無くても手軽に電気的エネルギーにアクセスできるのです。 これは物理的な例ですが、外部との境界にインターフェースがあるのはWebも同じです。 JavaScriptから簡単に外部と情報をやりとりしたり、外部のサービスの機能を使うためにAPIがあります。
参考文献
- Web API の紹介 - Web開発を学ぶ | MDN
- APIの基本的な概念の説明を参考にしています
開発者ツールに慣れる
Webブラウザーには開発者ツールが内蔵されています。 これを使うことでWebブラウザーが表示しているHTMLの状態を調べたり、どのリソース (URL) に、どのようにアクセスしているのか (HTTPメッセージの内容) 知ることができます。
ここではGoogle ChromeやMicrosoft EdgeなどChromium系ブラウザーの開発者ツールの基本的な使い方を説明します。
開発者ツールの起動方法
開発者ツールを起動するにはいくつかの方法があります。
- 右クリック > [検証] を選択
- [その他のツール] > [デベロッパー ツール] を選択
- Windows/Linuxの場合:
Ctrl
+Shift
+I
- macOSの場合:
⌘ (Command)
+⌥ (Option)
+I
どの方法でもOKです。
Note
開発者ツールの翻訳
はじめて開発者ツールを起動したとき、メニューがすべて英語で表示されることがあります。 開発者ツールのメニューを翻訳するには開発者ツール上部の [Always match Chrome's language] を選択しましょう。
実際に手元のWebブラウザーから開発者ツールを起動してみましょう。
要素 (Elements)
画面上に表示されているHTML要素とその状態を知ること、一時的に編集することができます。
コンソール (Console)
JavaScriptの実行と、エラーメッセージなど実行しているコードを解析するための情報を知ることができます。
ソース (Sources)
実行しているコードの表示と一時停止 (ブレークポイントの設定)、そのコードを解析することができます。
ネットワーク (Network)
WebブラウザーがアクセスしているURLとそのHTTPメッセージの内容知ることができます。
- 上側のペイン: タイムライン
- 左側のペイン: リクエストの一覧
- 右側のペイン: (リクエストの一覧から選択) リクエストヘッダー・プレビュー・レスポンスなどHTTPメッセージの詳細
ヘッダー
URLとリクエストのメソッド、レスポンスのステータスコードなどHTTPメッセージの基本的な情報を知ることができます。
プレビュー
(表示可能であれば) そのコンテンツを表示します。
レスポンス
そのコンテンツの生のデータを表示します。
ポイント
- 開発者ツール … Webブラウザーが表示しているHTMLの状態を調べたり、どのリソースに、どのようにアクセスしているのか知ることができる
やってみよう!
- 実際に手元のWebブラウザーで開発者ツールを起動していくつかのWebページにアクセスしてみよう
JavaScript
JavaScript Primer > 基本文法 > JavaScriptとは
JavaScriptを学びはじめる前に、まずJavaScriptとはどのようなプログラミング言語なのかを紹介します。
JavaScriptは主にWebブラウザーの中で動くプログラミング言語です。 ウェブサイトで操作をしたら表示が書き換わったり、ウェブサイトのサーバーと通信してデータを取得したりと現在のウェブサイトには欠かせないプログラミング言語です。 このようなJavaScriptを活用してアプリケーションのように操作できるウェブサイトをWebアプリとも言います。
JavaScriptはWebブラウザーだけではなく、Node.jsというサーバー側のアプリケーションを作る仕組みでも利用されています。 また、デスクトップアプリやスマートフォンアプリ、IoT(Internet of Things)デバイスでもJavaScriptを使って動かせるものがあります。 このように、JavaScriptはかなり幅広い環境で動いているプログラミング言語で、さまざまな種類のアプリケーションを作成できます。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > JavaScriptとは を参照しましょう。
歴史
JavaScriptは、1995年にブレンダン・アイクによって、当初Netscape Navigatorのためのスクリプト言語として開発されました。当時のWebは非常にシンプルで静的なものであり、動的なユーザーインタラクションはほとんどありませんでした。
そんな中、当時Netscape Communicationsで働いていたブレンダン・アイクは上司から新しいスクリプト言語を開発するよう依頼され、C、Java、Self、Schemeなどの既存のプログラミング言語の概念を取り入れつつ、わずか10日間で初期バージョンのJavaScriptを開発しました。
動的なユーザーインタラクションやサーバーへの非同期通信(Ajax)など現在では当たり前となっている多くの機能が初めてWebブラウザー上で可能となり、またその後のWebブラウザー以外の技術の発展にも大きな影響を与えました。
ポイント
- ECMAScript仕様による標準化
- 仕様は毎年更新されている
値の評価と表示
JavaScript Primer > 基本文法 > 値の評価と表示
値の評価とは、入力した値を評価してその結果を返すことを示しています。 たとえば、次のような値の評価があります。
1 + 1
という式を評価したら2
という結果を返すbookTitle
という変数を評価したら、変数に代入されている値を返すconst x = 1;
という文を評価することで変数を定義するが、この文には返り値はない
この値の評価方法を確認するために、Webブラウザー(以下ブラウザ)を使ってJavaScriptを実行する方法を見ていきます。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > 値の評価と表示 を参照しましょう。
ポイント
- Webブラウザーの開発者ツールのコンソール上でJavaScriptコードを評価する方法
やってみよう!
- 実際に手元のWebブラウザーでJavaScriptを実行してみよう
変数と宣言
JavaScript Primer > 基本文法 > 変数と宣言
プログラミング言語には、文字列や数値などのデータに名前をつけることで、繰り返し利用できるようにする変数という機能があります。
JavaScriptには「これは変数です」という宣言をするキーワードとして、
const
、let
、var
の3つがあります。
var
はもっとも古くからある変数宣言のキーワードですが、意図しない動作を作りやすい問題が知られています。
そのためECMAScript 2015で、var
の問題を改善するためにconst
とlet
という新しいキーワードが導入されました。
この章ではconst
、let
、var
の順に、それぞれの方法で宣言した変数の違いについて見ていきます。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > 変数と宣言 を参照しましょう。
ポイント
const
は、再代入できない変数を宣言できるlet
は、再代入ができる変数を宣言できる
やってみよう!
// 真空の光速度 (m/s) const c = 299792458; // 時間 (s) let t = 0; // 光の速度は変わらない // c = 42; // 時間は変わる t = 0.001; document.body.textContent = `${t} 秒間に光の進む距離: ${c * t} m`;
データ型とリテラル
JavaScript Primer > 基本文法 > データ型とリテラル
JavaScriptは動的型付け言語に分類される言語であるため、静的型付け言語のような変数の型はありません。 しかし、文字列、数値、真偽値といった値の型は存在します。 これらの値の型のことをデータ型と呼びます。
データ型を大きく分けると、プリミティブ型とオブジェクトの2つに分類されます。
プリミティブ型(基本型)は、真偽値や数値などの基本的な値の型のことです。 プリミティブ型の値は、一度作成したらその値自体を変更できないというイミュータブル(immutable)の特性を持ちます。 JavaScriptでは、文字列も一度作成したら変更できないイミュータブルの特性を持ち、プリミティブ型の一種として扱われます。
一方、プリミティブ型ではないものをオブジェクト(複合型)と呼び、 オブジェクトは複数のプリミティブ型の値またはオブジェクトからなる集合です。 オブジェクトは、一度作成した後もその値自体を変更できるためミュータブル(mutable)の特性を持ちます。 オブジェクトは、値そのものではなく値への参照を経由して操作されるため、参照型のデータとも言います。
データ型を細かく見ていくと、7つのプリミティブ型とオブジェクトからなります。
- プリミティブ型(基本型)
- 真偽値(Boolean):
true
またはfalse
のデータ型 - 数値(Number):
42
や3.14159
などの数値のデータ型 - 巨大な整数(BigInt): ES2020から追加された
9007199254740992n
などの任意精度の整数のデータ型 - 文字列(String):
"JavaScript"
などの文字列のデータ型 - undefined: 値が未定義であることを意味するデータ型
- null: 値が存在しないことを意味するデータ型
- シンボル(Symbol): ES2015から追加された一意で不変な値のデータ型
- 真偽値(Boolean):
- オブジェクト(複合型)
- プリミティブ型以外のデータ
- オブジェクト、配列、関数、クラス、正規表現、Dateなど
プリミティブ型でないものは、オブジェクトであると覚えていれば問題ありません。
typeof
演算子を使うことで、次のようにデータ型を調べることができます。
console.log(typeof true); // => "boolean"
console.log(typeof 42); // => "number"
console.log(typeof 9007199254740992n); // => "bigint"
console.log(typeof "JavaScript"); // => "string"
console.log(typeof Symbol("シンボル")); // => "symbol"
console.log(typeof undefined); // => "undefined"
console.log(typeof null); // => "object"
console.log(typeof ["配列"]); // => "object"
console.log(typeof { key: "value" }); // => "object"
console.log(typeof function () {}); // => "function"
プリミティブ型の値は、それぞれtypeof
演算子の評価結果として、その値のデータ型を返します。
一方で、オブジェクトに分類される値は"object"
となります。
配列([]
)とオブジェクト({}
)は、どちらも"object"
という判定結果になります。
そのため、typeof
演算子ではオブジェクトの詳細な種類を正しく判定することはできません。
ただし、関数はオブジェクトの中でも特別扱いされているため、typeof
演算子の評価結果は"function"
となります。
また、typeof null
が"object"
となるのは、歴史的経緯のある仕様のバグ[^1]です。
このことからもわかるようにtypeof
演算子は、プリミティブ型またはオブジェクトかを判別するものです。
typeof
演算子では、オブジェクトの詳細な種類を判定できないことは、覚えておくとよいでしょう。
各オブジェクトの判定方法については、それぞれのオブジェクトの章で見ていきます。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > データ型とリテラル を参照しましょう。
ポイント
- プリミティブ型とオブジェクトがある
- リテラルはデータ型の値を直接記述できる構文として定義されたもの
- プリミティブ型リテラル
- 真偽値 …
true
false
- 数値 …
42
3.14159
など - 文字列 …
"JavaScript"
など - BigInt …
9007199254740992n
など - null …
null
- 真偽値 …
コメント
JavaScript Primer > 基本文法 > コメント
コメントはプログラムとして評価されないため、ソースコードの説明を書くために利用されています。 この書籍でも、JavaScriptのソースコードを解説するためにコメントを使っていきます。
コメントの書き方には、一行コメントと複数行コメントの2種類があります。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > コメント を参照しましょう。
ポイント
//
以降から行末までが一行コメント/*
と*/
で囲まれた範囲が複数行コメント
やってみよう!
// これは一行コメント /* これは 複数行 コメント */ // JavaScriptを使えば… // 自由にテキストを書き換えることもできます! document.body.textContent = "JavaScriptの世界からこんにちは!✨";
演算子
JavaScript Primer > 基本文法 > 演算子
演算子はよく利用する演算処理を記号などで表現したものです。
たとえば、足し算をする +
も演算子の一種です。これ以外にも演算子には多くの種類があります。
演算子は演算する対象を持ちます。この演算子の対象のことを被演算子(オペランド)と呼びます。
次のコードでは、+
演算子が値同士を足し算する加算演算を行っています。
このとき、+
演算子の対象となっている1
と2
という2つの値がオペランドです。
1 + 2;
このコードでは+
演算子に対して、前後に合計2つのオペランドがあります。
このように、2つのオペランドを取る演算子を二項演算子と呼びます。
// 二項演算子とオペランドの関係
左オペランド 演算子 右オペランド
また、1つの演算子に対して1つのオペランドだけを取るものもあります。
たとえば、数値をインクリメントする++
演算子は、次のように前後どちらか一方にオペランドを置きます。
let num = 1;
num++;
// または
++num;
このように、1つのオペランドを取る演算子を単項演算子と呼びます。 単項演算子と二項演算子で同じ記号を使うことがあるため、呼び方を変えています。
この章では、演算子ごとにそれぞれの処理について学んでいきます。 また、演算子の中でも比較演算子は、JavaScriptでも特に挙動が理解しにくい暗黙的な型変換という問題と密接な関係があります。 そのため、演算子をひととおり見た後に、暗黙的な型変換と明示的な型変換について学んでいきます。
演算子の種類は多いため、すべての演算子の動作をここで覚える必要はありません。 必要となったタイミングで、改めてその演算子の動作を見るのがよいでしょう。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > 演算子 を参照しましょう。
ポイント
- 演算子はよく利用する演算処理を記号などで表現したもの
- 四則演算や論理演算などさまざまな種類の演算子がある
- 演算子には優先順位が定義されており、グループ化演算子で明示できる
条件分岐
JavaScript Primer > 基本文法 > 条件分岐
この章ではif文やswitch文を使った条件分岐について学んでいきます。 条件分岐を使うことで、特定の条件を満たすかどうかで行う処理を変更できます。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > 条件分岐 を参照しましょう。
ポイント
- if文
やってみよう!
let color = "white"; if (Math.random() < 0.5) { color = "green"; } document.body.style.backgroundColor = color; document.body.textContent = `今日のラッキーカラー: ${color}`;
- Math - JavaScript | MDN
Math.random()
は0
以上1
未満の疑似乱数を返します。
関数と宣言
JavaScript Primer > 基本文法 > 関数と宣言
関数とは、ある一連の手続き(文の集まり)を1つの処理としてまとめる機能です。 関数を利用することで、同じ処理を毎回書くのではなく、一度定義した関数を呼び出すことで同じ処理を実行できます。
これまで利用してきたコンソール表示をするConsole APIも関数です。
console.log
は「受け取った値をコンソールへ出力する」という処理をまとめた関数です。
この章では、関数の定義方法や呼び出し方について見ていきます。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > 関数と宣言 を参照しましょう。
ポイント
- 関数の宣言方法
やってみよう!
function 円の面積(r) { return Math.PI * r * r; } const r1 = 1; const r2 = 3; document.body.textContent = ` 半径 ${r1} m の円の面積: ${円の面積(r1)} m² 半径 ${r2} m の円の面積: ${円の面積(r2)} m² `;
Math.PI
は円周率(およそ3.14159
)を表すMath
オブジェクトの静的プロパティです。
ループと反復処理
JavaScript Primer > 基本文法 > ループと反復処理
この章では、while文やfor文などの基本的な反復処理と制御文について学んでいきます。
プログラミングにおいて、同じ処理を繰り返すために同じコードを繰り返し書く必要はありません。 ループやイテレータなどを使い、反復処理として同じ処理を繰り返し実行できます。
また、for文などのような構文だけではなく、配列のメソッドを利用して反復処理を行う方法もあります。 配列のメソッドを使った反復処理もよく利用されるため、合わせて見ていきます。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > ループと反復処理 を参照しましょう。
ポイント
- while文
- for文
やってみよう!
const text = "いろはにほへと"; for (const c of text) { document.body.textContent += `【${c}】`; }
非同期処理
JavaScript Primer > 基本文法 > 非同期処理:Promise/Async Function
この章ではJavaScriptの非同期処理について学んでいきます。 非同期処理はJavaScriptにおけるとても重要な概念です。 また、ブラウザやNode.jsなどのAPIには非同期処理でしか扱えないものもあるため、非同期処理を避けることはできません。 JavaScriptには非同期処理を扱うためのPromiseというビルトインオブジェクト、さらにはAsync Functionと呼ばれる構文的なサポートがあります。
この章では非同期処理とはどのようなものかという話から、非同期処理での例外処理、非同期処理の扱い方を見ていきます。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > 非同期処理:Promise/Async Function を参照しましょう。
ポイント
- 非同期処理はその処理が終わるのを待つ前に次の処理を評価すること
await
式- 書式:
await 関数()
- 意味:
await
式は Async Function関数()
が完了するまで待つ
- 書式:
- Async Function …
async function 関数() { <awaitの含まれる文>; }
- 非同期処理を行う関数
await
式は Async Function の中で利用できる
一定時間待機
一定時間待機するAsync Function sleep()
の作り方を解説します。
setTimeout(<コールバック関数>, <ミリ秒>)
関数は指定されたミリ秒後にコールバック関数を実行するための関数です。コールバック関数とは、簡単に言うと「後で使うために渡しておく関数」です。
次のコードは「3秒後にメッセージを表示する」という処理のプログラムです。メッセージの表示処理を resolve()
関数として宣言し、その関数名をコールバック関数として書きます。
function resolve() {
console.log("3秒!");
}
setTimeout(resolve, 3000); // 3秒 = 3,000ミリ秒
実行すると3秒後にメッセージ"3秒!"が表示されたかと思います。 これでも十分短いコードですが、今度はPromiseとawaitを使って書き換えてみます。
await new Promise((resolve) => setTimeout(resolve, 3000));
console.log("3秒!");
こうすることで上から下へと順番に実行する処理順で書けます。 これにより時間がかかるようなプログラムをもっと簡単に読みやすく書くことができます。
Note
現実世界と非同期処理コンピューターの上ではどのようなタイミングで何を行うかプログラマーが自由に決めることができますが、現実の世界では同じ時刻でも様々な事象が常に起こっています。 私たちの日常生活は多くの非同期的なイベントで構成されていると言えます。 非同期処理の概念を理解しておくことは現実の問題をコンピューターの上で扱うのにとても役に立ちます。
関数を使用して指定されたミリ秒(ms)だけ待つように一般化してみましょう。
ここで await
式は通常の関数のなかでは利用できず、代わりにAsync Functionの中で利用できるという点に注意しましょう。
まとめるとこのようになります:
async function sleep(ms) {
await new Promise((resolve) => setTimeout(resolve, ms));
}
使用方法:
await sleep(ミリ秒);
インターネットからのデータの取得
インターネットからデータを取得する際にも、その処理が完了するまで待つ必要があります。
書式:
let res = await fetch(取得するURL);
let data = await res.json();
最初の await
式でAPIからの応答を待ち、次に res.json()
の処理の完了を待ちます。
このようにしてデータが完全に取得されるまでコードの実行が一時停止し、データが利用可能になると処理を再開します。
やってみよう!
const button = document.createElement("button"); button.textContent = "スタート"; document.body.append(button); async function sleep(ms) { await new Promise(resolve => setTimeout(resolve, ms)); } button.addEventListener("click", async function () { await sleep(3000); // クリックしてから3秒待つ document.body.append("3秒!"); });
暗黙的な型変換
JavaScript Primer > 基本文法 > 暗黙的な型変換
この章では、明示的な型変換と暗黙的な型変換について学んでいきます。
「演算子」の章にて、 等価演算子(==
)ではなく厳密等価演算子(===
)の利用を推奨していました。
これは厳密等価演算子(===
)が暗黙的な型変換をせずに、値同士を比較できるためです。
厳密等価演算子(===
)では異なるデータ型を比較した場合に、その比較結果は必ずfalse
となります。
次のコードは、数値の1
と文字列の"1"
という異なるデータ型を比較しているので、結果はfalse
となります。
// `===`では、異なるデータ型の比較結果はfalse
console.log(1 === "1"); // => false
しかし、等価演算子(==
)では異なるデータ型を比較した場合に、同じ型となるように暗黙的な型変換をしてから比較します。
次のコードでは、数値の1
と文字列の"1"
の比較結果がtrue
となっています。
これは、等価演算子(==
)は右辺の文字列"1"
を数値の1
へと暗黙的な型変換をしてから、比較するためです。
// `==`では、異なるデータ型は暗黙的な型変換をしてから比較される
// 暗黙的な型変換によって 1 == 1 のように変換されてから比較される
console.log(1 == "1"); // => true
このように、暗黙的な型変換によって意図しない結果となるため、比較には厳密等価演算子(===
)を使うべきです。
別の暗黙的な型変換の例として、数値と真偽値の加算を見てみましょう。 多くの言語では、数値と真偽値の加算のような異なるデータ型同士の加算はエラーとなります。 しかし、JavaScriptでは暗黙的な型変換が行われてから加算されるため、エラーなく処理されます。
次のコードでは、真偽値のtrue
が数値の1
へと暗黙的に変換されてから加算処理が行われます。
// 暗黙的な型変換が行われ、数値の加算として計算される
1 + true; // => 2
// 次のように暗黙的に変換されてから計算される
1 + 1; // => 2
JavaScriptでは、エラーが発生するのではなく、暗黙的な型変換が行われてしまうケースが多くあります。 暗黙的に変換が行われた場合、プログラムは例外を投げずに処理が進むため、バグの発見が難しくなります。 このように、暗黙的な型変換はできる限り避けるべき挙動です。
この章では、次のことについて学んでいきます。
- 暗黙的な型変換とはどのようなものなのか
- 暗黙的ではない明示的な型変換の方法
- 明示的な変換だけでは解決しないこと
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > 暗黙的な型変換 を参照しましょう。
ポイント
- 暗黙的な型変換がある
- できるだけ
===
での比較や明示的な型変換をしたほうが読みやすい
文と式
JavaScript Primer > 基本文法 > 文と式
本格的に基本文法について学ぶ前に、JavaScriptというプログラミング言語がどのような要素からできているかを見ていきましょう。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > 文と式 を参照しましょう。
ポイント
- JavaScriptは文(Statement)と式(Expression)から構成される
- 式は値を生成し、変数に代入できるもの
- 文は処理の単位
- 文の末尾にはセミコロン
;
をつける
オブジェクト
JavaScript Primer > 基本文法 > オブジェクト
オブジェクトはプロパティの集合です。プロパティとは名前(キー)と値(バリュー)が対になったものです。
プロパティのキーには文字列またはSymbol
が利用でき、値には任意のデータを指定できます。
また、1つのオブジェクトは複数のプロパティを持てるため、1つのオブジェクトで多種多様な値を表現できます。
今までも登場してきた、配列や関数などもオブジェクトの一種です。
JavaScriptには、あらゆるオブジェクトの元となるObject
というビルトインオブジェクトがあります。
ビルトインオブジェクトは、実行環境にあらかじめ定義されているオブジェクトのことです。
Object
というビルトインオブジェクトはECMAScriptの仕様で定義されているため、あらゆるJavaScriptの実行環境で利用できます。
この章では、オブジェクトの作成や扱い方、Object
というビルトインオブジェクトについて見ていきます。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > オブジェクト を参照しましょう。
ポイント
- オブジェクトはプロパティの集合
{}
(オブジェクトリテラル)でのオブジェクトの作成や更新方法
配列
配列はJavaScriptの中でもよく使われるオブジェクトです。
配列とは値に順序をつけて格納できるオブジェクトです。
配列に格納したそれぞれの値のことを要素、それぞれの要素の位置のことをインデックス(index
)と呼びます。
インデックスは先頭の要素から0
、1
、2
のように0
からはじまる連番となります。
またJavaScriptにおける配列は可変長です。 そのため配列を作成後に配列へ要素を追加したり、配列から要素を削除できます。
この章では、配列の基本的な操作と配列を扱う場合においてのパターンについて学びます。
― この文章は © 2023 jsprimer project クリエイティブ・コモンズ CC BY 4.0 ライセンスのもとに利用を許諾されています。
続きは JavaScript Primer > 基本文法 > 配列 を参照しましょう。
ポイント
- 配列は値に順序をつけて格納できるオブジェクト
[]
(配列リテラル)での配列の作成や更新方法
やってみよう!
function drawFortune() { const fortunes = ["大吉", "中吉", "吉", "小吉", "凶", "大凶"]; const i = Math.floor(Math.random() * fortunes.length); document.body.textContent = `あなたの運勢は... ${fortunes[i]}です!`; } drawFortune();
- Math - JavaScript | MDN
Math.floor(x)
はx
以下の最大の整数を返します。Math.random()
は0
以上1
未満の疑似乱数を返します。
Webサイトを公開する
作成したWebサイトをインターネット上に公開する方法を説明します。
公開する方法
Webサイトを公開する方法にはいくつもありますが、ここでは無料で公開できる2つの方法を紹介します。
方法1: Glitchを使う (短時間)
Glitch https://glitch.com を使うと短い時間でWebサイトを公開できます (ただし無料版では限られた時間しかアクセスできないので注意しましょう)。
Webページを公開する流れ:
- https://glitch.com にアクセス
- Basic website > [Remix] を選択
- ファイルを編集
Webブラウザーに表示された画面の「index.html」のコードを編集することですぐにWebサイトとして公開されます。
編集画面の下の 🔍 [PREVIEW] > [Preview in a new Window] から公開したWebサイトにアクセスします。
方法2: GitHubを使う
GitHub https://github.com を使うことでより本格的にWebサイトを公開できます (このガイドもそうです)。
GitHubを使うにはアカウントの作成が必要です。まずGitHubの無料アカウントを作成しましょう。
Webページを公開する流れ:
自分に合った方法でWebサイトを公開してみましょう!
GitHubでのアカウントの作成
GitHub Pagesサイトの作成
Google Apps Script (GAS) で作るWebアプリ
Webブラウザー上で動作するアプリの作り方を紹介します。地図を表示するためのサードパーティAPI、Google Apps Script、そしてWebブラウザーの位置情報APIの使い方を説明します。
地図上に位置を表示する
地図を表示するためのサードパーティAPI (Leaflet) を使用し、地図上に位置を表示します。
書式
地図:
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet"></script>
<script type="module">
const map = L.map("map").setView([36, 138], 15);
// OpenStreetMapのデータはOpen Database Licenseのもとに利用を許諾されています。
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: `© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors`,
}).addTo(map);
</script>
<h1>位置情報メモ</h1>
<div id="map" style="width: 500px; height: 500px"></div>
現在地の取得:
async function getLatLng() {
const position = await new Promise((resolve, reject) =>
navigator.geolocation.getCurrentPosition(resolve, reject),
);
return [position.coords.latitude, position.coords.longitude];
}
// [<緯度>, <経度>]
const here = await getLatLng();
丸いマーカーの表示:
L.circleMarker([<緯度>, <経度>]).addTo(map);
地図の移動:
map.flyTo([<緯度>, <経度>]);
サンプルコード (全体)
<!doctype html>
<meta charset="UTF-8" />
<title>GASで作るWebアプリ - 位置情報メモ</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet"></script>
<script type="module">
/** 経緯度の取得 */
async function getLatLng() {
const position = await new Promise((resolve, reject) =>
navigator.geolocation.getCurrentPosition(resolve, reject),
);
return [position.coords.latitude, position.coords.longitude];
}
const map = L.map("map").setView([36, 138], 15);
// OpenStreetMapのデータはOpen Database Licenseのもとに利用を許諾されています。
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: `© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors`,
}).addTo(map);
// 現在地
const here = await getLatLng();
// 現在地にマーカーを表示
L.circleMarker(here).addTo(map);
// 現在地に移動
map.flyTo(here);
</script>
<h1>位置情報メモ</h1>
<div id="map" style="width: 500px; height: 500px"></div>
Note
[36, 138]
は日本の地理的中心、北緯36度東経138度、長野県上伊那郡辰野町の区有林。
位置情報API (Geolocation API) を使用すると、自分の位置情報をWebアプリから取得することができます。 位置情報APIの初回使用時には、位置情報の許可を求められるので[許可]を選択します。
位置情報が地図上に表示されることを確認してみましょう。
スプレッドシートの作成
Googleスプレッドシートを作成し、Google Apps Scriptのプロジェクトを作成します。
事前準備
- Googleアカウント
スプレッドシートの作成
https://sheet.new にアクセス、または「スプレッドシートのホーム画面」を開き、+をクリックします。
参考: Google スプレッドシートの使い方 - パソコン - Google ドキュメント エディタ ヘルプ
プロジェクトの作成
[拡張機能] > [Apps Script] を選択し、Google Apps Scriptのプロジェクトを作成します。
以下のコードをコピーして貼り付け、💾 [プロジェクトを保存] します。
// 最初のシート
const [sheet] = SpreadsheetApp.getActiveSpreadsheet().getSheets();
/**
* @example 行全体の取得
* const res = await fetch("https://script.google.com/{SCRIPTID}/exec");
* const rows = await res.json();
* // [
* // ["2006-01-02T15:04:05.999Z",1,2],
* // ["2006-01-02T15:04:06.000Z",3,4],
* // ...
* // ]
*/
function doGet() {
const rows = sheet.getDataRange().getValues().slice(1);
return ContentService.createTextOutput(JSON.stringify(rows)).setMimeType(
ContentService.MimeType.JSON,
);
}
/**
* @example 行の挿入
* const row = [5,6];
* await fetch("https://script.google.com/{SCRIPTID}/exec", { method: "POST", body: JSON.stringify(row) })
*/
function doPost(e) {
const row = JSON.parse(e.postData.contents);
sheet.appendRow([new Date(), ...row]);
return doGet();
}
プロジェクトを保存できたら、そのプロジェクトを利用可能にします。
プロジェクトのデプロイ
プロジェクトを新しくデプロイするには [デプロイ] > [新しいデプロイ] から行います。
[種類の選択] ⚙ > [ウェブアプリ] を選択します。
[アクセスできるユーザー] > [全員] を選択し、[デプロイ] を選択します。
Googleアカウントへのアクセス許可を求められるのでアカウントを選択し、[Allow] をクリックします
WebアプリのURLが表示されればデプロイ完了です。
データの送信にはこのWebアプリのURL (https://script.google.com/macros/s/AKf...
) を使用します。
このURLはコピーしておきましょう。
使用方法
データの取得:
// ここはWebアプリのURLに書き換えます
const endpoint = "https://script.google.com/{SCRIPTID}/exec";
const res = await fetch(endpoint);
const rows = await res.json();
データの送信:
// ここはWebアプリのURLに書き換えます
const endpoint = "https://script.google.com/{SCRIPTID}/exec";
const row = [...<送信する内容>...];
await fetch(endpoint, { method: "POST", body: JSON.stringify(row) });
WebアプリのURLと送信する内容の部分は適宜変更して使用します。
送信してみよう!
サンプルコード:
const row = [42];
await fetch(endpoint, { method: "POST", body: JSON.stringify(row) });
endpoint =
レスポンス:
null
データを送信する
フォームからデータを送信してみましょう。
書式
HTMLとJavaScriptでコメント入力欄を作ります。
HTML:
<form>
<input name="comment" placeholder="コメント" required />
<button type="submit">送信</button>
</form>
JavaScript:
// ここはWebアプリのURLに書き換えます
const endpoint = "https://script.google.com/{SCRIPTID}/exec";
const form = document.querySelector("form");
form.addEventListener("submit", async function submit(e) {
e.preventDefault();
document.body.style.cursor = "wait";
const formData = new FormData(form);
const comment = formData.get("comment");
const row = [comment];
await fetch(endpoint, { method: "POST", body: JSON.stringify(row) });
location.reload();
});
サンプルコード (全体)
<!doctype html>
<meta charset="UTF-8" />
<title>GASで作るWebアプリ - 位置情報メモ</title>
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet"></script>
<script type="module">
/** 経緯度の取得 */
async function getLatLng() {
const position = await new Promise((resolve, reject) =>
navigator.geolocation.getCurrentPosition(resolve, reject),
);
return [position.coords.latitude, position.coords.longitude];
}
const map = L.map("map").setView([36, 138], 15);
// OpenStreetMapのデータはOpen Database Licenseのもとに利用を許諾されています。
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: `© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors`,
}).addTo(map);
// 現在地
const here = await getLatLng();
// 現在地にマーカーを表示
L.circleMarker(here).addTo(map);
// 現在地に移動
map.flyTo(here);
// ここはWebアプリのURLに書き換えます
const endpoint = "https://script.google.com/{SCRIPTID}/exec";
const form = document.querySelector("form");
form.addEventListener("submit", async function submit(e) {
e.preventDefault();
document.body.style.cursor = "wait";
const formData = new FormData(form);
const comment = formData.get("comment");
const row = [comment];
await fetch(endpoint, { method: "POST", body: JSON.stringify(row) });
location.reload();
});
</script>
<h1>位置情報メモ</h1>
<div id="map" style="width: 500px; height: 500px"></div>
<form>
<input name="comment" placeholder="コメント" required />
<button type="submit">送信</button>
</form>
コメントを入力し、[送信] を選択します。
スプレッドシートにコメントのデータが記録されていることを確認してみましょう。
位置情報を送信する
ここまで説明に沿ってやってきていたら comment
の後ろに現在地を書き加えれば現在地の緯度・経度を送信できます。
const row = [comment];
↓
const row = [comment, here[0], here[1]];
このように書き加えればOKです。
書式
// コメント, 緯度, 経度
const row = [comment, here[0], here[1]];
サンプルコード (全体)
<!doctype html>
<meta charset="UTF-8" />
<title>GASで作るWebアプリ - 位置情報メモ</title>
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet"></script>
<script type="module">
/** 経緯度の取得 */
async function getLatLng() {
const position = await new Promise((resolve, reject) =>
navigator.geolocation.getCurrentPosition(resolve, reject),
);
return [position.coords.latitude, position.coords.longitude];
}
const map = L.map("map").setView([36, 138], 15);
// OpenStreetMapのデータはOpen Database Licenseのもとに利用を許諾されています。
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: `© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors`,
}).addTo(map);
// 現在地
const here = await getLatLng();
// 現在地にマーカーを表示
L.circleMarker(here).addTo(map);
// 現在地に移動
map.flyTo(here);
// ここはWebアプリのURLに書き換えます
const endpoint = "https://script.google.com/{SCRIPTID}/exec";
const form = document.querySelector("form");
form.addEventListener("submit", async function submit(e) {
e.preventDefault();
document.body.style.cursor = "wait";
const formData = new FormData(form);
const comment = formData.get("comment");
const row = [comment, here[0], here[1]];
await fetch(endpoint, { method: "POST", body: JSON.stringify(row) });
location.reload();
});
</script>
<h1>位置情報メモ</h1>
<div id="map" style="width: 500px; height: 500px"></div>
<form>
<input name="comment" placeholder="コメント" required />
<button type="submit">送信</button>
</form>
スプレッドシートに位置情報が記録されていることを確認してみましょう。
データを取得する
最後にスプレッドシートのデータを地図上に表示してみましょう。
書式
データの取得:
const res = await fetch(endpoint);
const rows = await res.json();
// 日付と時刻, コメント, 緯度, 経度
for (const [timestamp, comment, lat, lng] of rows) {
// 日付と時刻
const date = new Date(timestamp).toLocaleString();
// …
}
マーカーの追加:
const popup = document.createElement("span");
popup.textContent = <表示する内容>;
L.marker([<緯度>, <経度>]).addTo(map).bindPopup(popup);
サンプルコード (全体)
<!doctype html>
<meta charset="UTF-8" />
<title>GASで作るWebアプリ - 位置情報メモ</title>
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet"></script>
<script type="module">
/** 経緯度の取得 */
async function getLatLng() {
const position = await new Promise((resolve, reject) =>
navigator.geolocation.getCurrentPosition(resolve, reject),
);
return [position.coords.latitude, position.coords.longitude];
}
const map = L.map("map").setView([36, 138], 15);
// OpenStreetMapのデータはOpen Database Licenseのもとに利用を許諾されています。
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: `© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors`,
}).addTo(map);
// 現在地
const here = await getLatLng();
// 現在地にマーカーを表示
L.circleMarker(here).addTo(map);
// 現座地に移動
map.flyTo(here);
// ここはWebアプリのURLに書き換えます
const endpoint = "https://script.google.com/{SCRIPTID}/exec";
const res = await fetch(endpoint);
const rows = await res.json();
for (const [timestamp, comment, lat, lng] of rows) {
const date = new Date(timestamp).toLocaleString();
const popup = document.createElement("span");
popup.textContent = `${date}: ${comment}`;
L.marker([lat, lng]).addTo(map).bindPopup(popup);
}
const form = document.querySelector("form");
form.addEventListener("submit", async function submit(e) {
e.preventDefault();
document.body.style.cursor = "wait";
const formData = new FormData(form);
const comment = formData.get("comment");
const row = [comment, here[0], here[1]];
await fetch(endpoint, { method: "POST", body: JSON.stringify(row) });
location.reload();
});
</script>
<h1>位置情報メモ</h1>
<div id="map" style="width: 500px; height: 500px"></div>
<form>
<input name="comment" placeholder="コメント" required />
<button type="submit">送信</button>
</form>
やってみよう!
- より魅力的にしていくにはどうすればよいか考えてみましょう
- 例: CSSを使ってきれいな見た目にする?
- 例: コードを整理する?
- 思いついたら「とりあえずやってみる」
参考文献
Raspberry Piで温度センサーのデータの送信
Google Apps Scriptを利用してRaspberry Piからスプレッドシートにデータを送信する方法を説明します。
スプレッドシートの作成
Googleスプレッドシートを作成し、Google Apps Scriptのプロジェクトを作成します。
事前準備
- Googleアカウント
スプレッドシートの作成
https://sheet.new にアクセス、または「スプレッドシートのホーム画面」を開き、+をクリックします。
参考: Google スプレッドシートの使い方 - パソコン - Google ドキュメント エディタ ヘルプ
プロジェクトの作成
[拡張機能] > [Apps Script] を選択し、Google Apps Scriptのプロジェクトを作成します。
以下のコードをコピーして貼り付け、💾 [プロジェクトを保存] します。
// 最初のシート
const [sheet] = SpreadsheetApp.getActiveSpreadsheet().getSheets();
/**
* @example 行全体の取得
* const res = await fetch("https://script.google.com/{SCRIPTID}/exec");
* const rows = await res.json();
* // [
* // ["2006-01-02T15:04:05.999Z",1,2],
* // ["2006-01-02T15:04:06.000Z",3,4],
* // ...
* // ]
*/
function doGet() {
const rows = sheet.getDataRange().getValues().slice(1);
return ContentService.createTextOutput(JSON.stringify(rows)).setMimeType(
ContentService.MimeType.JSON,
);
}
/**
* @example 行の挿入
* const row = [5,6];
* await fetch("https://script.google.com/{SCRIPTID}/exec", { method: "POST", body: JSON.stringify(row) })
*/
function doPost(e) {
const row = JSON.parse(e.postData.contents);
sheet.appendRow([new Date(), ...row]);
return doGet();
}
プロジェクトを保存できたら、そのプロジェクトを利用可能にします。
プロジェクトのデプロイ
プロジェクトを新しくデプロイするには [デプロイ] > [新しいデプロイ] から行います。
[種類の選択] ⚙ > [ウェブアプリ] を選択します。
[アクセスできるユーザー] > [全員] を選択し、[デプロイ] を選択します。
Googleアカウントへのアクセス許可を求められるのでアカウントを選択し、[Allow] をクリックします
WebアプリのURLが表示されればデプロイ完了です。
データの送信にはこのWebアプリのURL (https://script.google.com/macros/s/AKf...
) を使用します。
このURLはコピーしておきましょう。
使用方法
データの取得:
// ここはWebアプリのURLに書き換えます
const endpoint = "https://script.google.com/{SCRIPTID}/exec";
const res = await fetch(endpoint);
const rows = await res.json();
データの送信:
// ここはWebアプリのURLに書き換えます
const endpoint = "https://script.google.com/{SCRIPTID}/exec";
const row = [...<送信する内容>...];
await fetch(endpoint, { method: "POST", body: JSON.stringify(row) });
WebアプリのURLと送信する内容の部分は適宜変更して使用します。
送信してみよう!
サンプルコード:
const row = [42];
await fetch(endpoint, { method: "POST", body: JSON.stringify(row) });
endpoint =
レスポンス:
null
温度センサーのデータの送信
それではRaspberry Piからスプレッドシートにデータを送信してみましょう。
温度センサー SHT30 を利用して温度のデータを送信します。
事前準備
- Raspberry Pi
- SHT30 (温度・湿度センサ)
- 配線用のワイヤー
サンプルコード
次のようなNode.jsのコードを実行することでデータを送信します:
// ここはWebアプリのURLに書き換えます
const endpoint = "https://script.google.com/{SCRIPTID}/exec";
import { requestI2CAccess } from "node-web-i2c";
import SHT30 from "@chirimen/sht30";
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const i2cAccess = await requestI2CAccess();
const port = i2cAccess.ports.get(1);
const sht30 = new SHT30(port, 0x44);
await sht30.init();
while (true) {
const { humidity, temperature } = await sht30.readData();
const row = [temperature];
await fetch(endpoint, { method: "POST", body: JSON.stringify(row) });
const message = `現在の温度は${temperature.toFixed(2)}度です`;
console.log(endpoint, message);
// 10秒待機
await sleep(10000); // ms
}
スプレッドシートに温度センサーのデータが記録されていることを確認してみましょう。
グラフの作成
Googleスプレッドシートでグラフを作成します。
- グラフの列を選択します
- [挿入] > [グラフ] を選択します
グラフのタイトル
グラフの見た目を変更する方法をいくつか紹介します。
- 変更するグラフをダブルクリックします
- 右側の [カスタマイズ] を選択します
- [グラフと軸のタイトル] を選択します
- [グラフのタイトル] > タイトルテキストを入力します
縦軸の範囲の変更
縦軸の表示範囲は [縦軸] > [最小値]/[最大値] を入力します。
目盛り
目盛りの追加は [グリッドラインと目盛] > [主目盛り]/[補助目盛り] を選択します。
表示形式
- グラフの列を選択します
- [表示形式] メニューから表示形式を選択します
参考文献
Raspberry Piからスマートフォンにデータを送信する
ntfy.shを利用してRaspberry Piからスマートフォンにデータを送信する方法を説明します。
ntfy.shは、ユーザーに通知を送信するためのシンプルなサービスです。このサービスは特定のイベントや条件が発生したときに通知を送るために利用できます。
制約事項
(無料枠) 1日あたりのメッセージの上限は250件です。 10分あたり1件程度の通知を目安にしましょう。
その他にもAPIにはいくつかの制限があります。注意して利用しましょう。
制限 | 説明 |
---|---|
メッセージの長さ | 各メッセージの長さは最大 4,096 バイトです。長いメッセージは添付ファイルとして扱われます。 |
リクエスト | デフォルトでは、サーバーは訪問者あたり一度に 60 件のリクエストを許可し、その後 5 秒に 1 件の割合で許可されたリクエスト バケットを補充するように設定されています。 |
1 日あたりのメッセージ | デフォルトでは、メッセージ数はリクエスト制限によって制御されます。これはオーバーライドできます。 ntfy.sh では、1 日あたりのメッセージ制限は 250 です。 |
メール | デフォルトでは、サーバーは訪問者ごとに一度に 16 通の電子メールを送信できるように設定されており、許可された電子メール バケットは 1 時間に 1 通の割合で補充されます。 ntfy.sh では、1 日あたりの制限は 5 です。 |
電話通話 | デフォルトでは、通話制限のある層を持つユーザーを除き、サーバーは電話通話を許可しません。 |
サブスクリプション制限 | デフォルトでは、サーバーは各訪問者がサーバーへの 30 接続を開いたままにすることを許可します。 |
添付ファイルのサイズ制限 | デフォルトでは、サーバーは添付ファイルのサイズが最大 15 MB、訪問者あたり合計で最大 100 MB、訪問者全体で最大 5 GB まで許可します。 ntfy.sh では、添付ファイルのサイズ制限は 2 MB で、訪問者あたりの合計は 20 MB です。 |
添付ファイルの有効期限 | デフォルトでは、サーバーは 3 時間後に添付ファイルを削除するため、訪問者の添付ファイルの合計制限からスペースが解放されます。 |
添付ファイルの帯域幅 | デフォルトでは、サーバーは 24 時間以内に訪問者ごとに 500 MB の添付ファイルの GET/PUT/POST トラフィックを許可します。それを超えるトラフィックは拒否されます。 ntfy.sh では、1 日の帯域幅制限は 200 MB です。 |
トピックの総数 | デフォルトでは、サーバーは 15,000 のトピックを許可するように構成されています。ただし、ntfy.sh サーバーにはより高い制限があります。 |
https://docs.ntfy.sh/publish/#limitations より
トピックの作成
ntfy.shを利用するには、まずトピックを作成します。
新しいトピックを作成してみましょう:
トピックにアクセスし[購読]することで通知を受け取ることができるようになります。 このときのURLは忘れないようにメモしておきます。
使用方法
メッセージの送信:
// ここはntfy.shのURLに書き換えます
const endpoint = "https://ntfy.sh/mytopic";
const message = `<メッセージ本文>`;
const res = await fetch(endpoint, { method: "POST", body: message });
送信してみよう!
サンプルコード:
const message = `現在の時刻は ${new Date().toTimeString()} です`;
await fetch(endpoint, { method: "POST", body: message });
endpoint =
レスポンス:
null
温度センサーのデータの送信
それではRaspberry Piからスマートフォンにデータを送信してみましょう。
温度センサー SHT30 を利用して温度のデータを送信します。
事前準備
- Raspberry Pi
- SHT30 (温度・湿度センサ)
- 配線用のワイヤー
配線図
書式
// ここはntfy.shのURLに書き換えます
const endpoint = <ntfy.shのURL>;
await fetch(endpoint, { method: "POST", body: <送信する内容> });
ntfy.shのURLと送信する内容の部分を書き換えて使用します。
スマートフォンに温度センサーのデータが送信されていることを確認してみましょう。
サンプルコード
次のようなNode.jsのコードを実行することでデータを送信します:
// ここはntfy.shのURLに書き換えます
const endpoint = "https://ntfy.sh/536804b7-65aa-403f-97f6-7bd945e83491";
import { requestI2CAccess } from "node-web-i2c";
import SHT30 from "@chirimen/sht30";
const i2cAccess = await requestI2CAccess();
const port = i2cAccess.ports.get(1);
const sht30 = new SHT30(port, 0x44);
await sht30.init();
const { humidity, temperature } = await sht30.readData();
const message = `現在の温度は${temperature.toFixed(2)}度です`;
await fetch(endpoint, { method: "POST", body: message });
console.log(endpoint, message);
制約事項
(無料枠) 1日あたりのメッセージの上限は250件です。 10分あたり1件程度の通知を目安にしましょう。
参考: https://docs.ntfy.sh/publish/#limitations より
質問・提案・問題の報告
もし気になることなどあれば、Cosense または GitHub Issues からお気軽にお寄せください。
Scrapbox
- 利用にはGoogleアカウントが必要です
- 詳しくはCosenseの使い方をご参照ください
GitHub
- 利用にはGitHubアカウントが必要です