第17話:Webページの書き換え

第3部 Webページのプログラミング

目次

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ台詞

【1Page】
アイコン先生:今日は Webページの書き換え について説明する
アイコン遊:ゴクリ
    サイトを 改竄するの?
アイコン先生:いやいや そんな大それた ことはしない
    Webページの オブジェクトを 操作するだけだ
アイコン麗:オブジェクト?
    プログラムだけでなく Webページにも オブジェクトが あるんですか?
アイコン先生:そうだ
【2Page】
アイコン先生:Webページは ブラウザから見ると 1枚のシートみたいに見える
    これは違うように 表現できる
アイコン麗:違うように?
アイコン先生:こうした階層構造だ
    『Window』の中に 『document』 その中に HTMLの部品となる 『element』という 構造だ
        window
            document
                element
                    element
                        element
                        element
                            element
                        element
                    element
                    :
アイコン守:あれ?
    『document』って 『document.write()』の 『document』ですか?
アイコン先生:ああ いいところ に気付いたな
    『window』はブラウザを 『document』はWebページを 表すオブジェクトだ
    『window』は 省略可能で
    『window.document.write()』
    が本来の書き方なんだ
【3Page】
アイコン守:そうだったんだ
アイコン遊:ははーん 分かったわ
    このオブジェクトの プロパティを変更すれば 
    ブラウザの内容が 書き換わるのね!
アイコン先生:よく分かったな
アイコン遊:当然よ!
    私って 天才!
アイコン先生:それじゃあ やってみろ
アイコン遊:任せなさい!
アイコン遊:(いろいろと考える)
    すみません 分かりません
【4Page】
アイコン先生:そうだろう 教えてないからな
    じゃあ 今日の 本題に入るぞ
    HTMLファイルは タグでツリー状に なっている
    そしてwindowオブジェクトから 直接たどって操作できない
        <html>
            <head>
            <body>
                <h1>
                    文字列
                <br>
                <div>
                    文字列
    だから HTMLの各要素を 指定する方法を 知る必要がある
    その仕組みを 『DOM』と言う
        DOM = Document Object Model
    それじゃあ 一番簡単な方法で 指定してみる
    タグに指定した『id』属性の値が 『target』の要素を選択して 書き換えてみるぞ
        <div id="target">
        『id』属性 『id』属性の値
【5Page】
        <html>
            <body>
                <div id="target">目標の文字列</div>

                <script type="text/javascript">
                <!--
                // 『id』が『target』の要素(<div id="target">目標の文字列</div>)を選択
                var ele = document.getElementById("target");    

                // 要素の内部のHTML(ここでは『目標の文字列』)を書き換え
                ele.innerHTML = "書き換えたよ!";
                // -->
                </script>
            </body>
        </html>
    『書き換えたよ!』と表示
アイコン守:『getElementById』で オブジェクトを 得ているんですね
アイコン先生:そうだ
    Webページ内の 各要素には 『innerHTML』という プロパティがある
    これを書き換えれば 見た目が変わる
        内部のHTMLのテキストを表すプロパティ
        要素(element).innerHTML
【6Page】
アイコン先生:また画像などでは 『src』プロパティを 書き換えれば 中身を変えられる
        要素(element).src
        画像などのファイルのパス
        <html>
            <body>
                <img src="pic/a.gif">
                <img id="target" src="pic/a.gif">

                <script type="text/javascript">
                <!--
                var ele = document.getElementById("target");
                ele.src = "pic/b.gif";  // 画像ファイルのパスを変更
                // -->
                </script>
            </body>
        </html>
    (2番目の画像が書き換わった様子)
    『id』が『targer』の画像を…
    『pic/b.gif』に変更!
アイコン遊:なるほど 便利ね
    でも 全部のタグに IDを書くのは面倒ね
アイコン先生:そういった場合は タグ名を使って 配列で取得すればよい
【7Page】
        <html>
            <body>
                <img src="pic/a.gif">
                <img src="pic/a.gif">
                <img src="pic/a.gif">
                <img src="pic/a.gif">
                <img src="pic/a.gif">

                <script type="text/javascript">
                <!--
                // 『<img>』タグの要素を、配列として選択
                var imgs = document.getElementsByTagName("img");

                // 配列に格納された各要素に対して処理を実行
                for (var i = 0; i < imgs.length; i ++) {
                    // 『width』(横幅)の値を書き換える
                    imgs[i].width = (1 + i) * 32;
                }
                // -->
                </script>
            </body>
        </html>
    注意点は 『getElement"s"ByTagName』と 複数形になっていることだ
    また 『DOM』ではないが 『location』を 変更すれば
    表示しているページを 移動できる
【8Page】
        <html>
            <body>
                <script type="text/javascript">
                <!--
                // 『location』の『href』を変更して
                // ブラウザで表示されているページを変更する
                window.location.href = "https://crocro.com/";
                // -->
                </script>
            </body>
        </html>
    (ページが変わる)
    表示されている ページが変わる
アイコン遊:へー 面白いわね
アイコン麗:でも ページが 表示された瞬間に 書き換わるから あまり意味がないですね
アイコン先生:そうだな
    というわけで次回は イベントを利用して
    ユーザーの操作で Webページを加工していくぞ

説明

この章では、『Webページの書き換え』について学びます。

JavaScriptから見たWebページは、『window』オブジェクトを頂点とした、階層構造を持っています。これらは全てオブジェクトですので、通常のオブジェクトと同じようにプロパティやメソッドを持っており、プログラムで操作できます。

これまでも『window.alert』や『document.write』メソッド、『document.title』といったプロパティを利用してきました。

○window
┣○alert
┣○……
┗○document
  ┣○write
  ┣○title
 ┣○……

Webページでは、HTMLタグを元に、『DOM』(Document Object Model)と呼ばれる、部品(『element』)の階層構造を作っています。

JavaScriptでは、『document』の各種メソッドを利用して、目的の部品を『element』オブジェクトとして取得できます。そして、この『element』オブジェクトに対して各種操作を行います。

それでは以下、JavaScriptを使い、この『DOM』を操作する方法を学んでいきましょう。

『DOM』でのオブジェクト操作

『DOM』(Document Object Model)は、HTMLファイルのタグから作られたWebページの部品(『Element』)にアクセスする方法です。

JavaScriptでは『getElementById』などのメソッドを使い、特定の『Element』オブジェクトを取得できます(『Element』は『要素』という意味)。

以下、簡単な例を示します。

『getElementById』メソッド

<div id="target">目標の文字列</div>
// 『id』が『target』の要素(<div id="target">目標の文字列</div>)を選択
var ele = document.getElementById("target");

// 要素の内部のHTML(ここでは『目標の文字列』)を書き換え
ele.innerHTML = "書き換えたよ!";

『id』は、タグの中に書く属性の1つです。この『id』属性の値には、そのWebページでユニークな値(他に同じ値がない値)を記入します。ユニークな値を記入しているので、『getElementById』メソッドを使うことで、その要素1つだけを特定して、取り出すことができます。

上記のプログラムでは、変数『ele』に格納した要素(『element』オブジェクト)の『innerHTML』プロパティの値を書き換えています。『innerHTML』プロパティは、その要素の配下にあるHTMLを、テキストとして読み込んだり、書き換えたりするためのプロパティです。

このプログラムでは、『書き換えたよ!』という文字列を入れています。そのため、画面内の『目標の文字列』は『書き換えたよ!』という文字列に書き換わります。

『src』プロパティ

要素の中には、画像のように『src』属性を持つものがあります。

<img src="pic/a.gif">
<img id="target" src="pic/a.gif">

『img』タグでは、『Element』オブジェクトの『src』プロパティの値を書き換えることで、画像ファイルのパスを変更できます。パスを変更すると、画面に表示される画像が差し替わります。

var ele = document.getElementById("target");
ele.src = "pic/b.gif";     // 画像ファイルのパスを変更

上記のプログラムでは、id『target』の画像のパスが、『pic/a.gif』から『pic/b.gif』に書き換わります。

『getElementsByTagName』メソッド

さて、これまでの例では、要素は全て『getElementById』メソッドを使って取得してきました。しかし、HTMLファイルの全てのタグに『ID』属性を指定するのは大変です。実際のHTMLファイルでは、ほとんどのタグには『id』属性を設定していないでしょう。そういった場合は、要素を選択することはできないのでしょうか?

こういった場合は、いくつかの方法が用意されています。まずはその1つ目を紹介します。『タグの種類』から要素を選択する『getElementsByTagName』メソッドです。以下のように、タグの名前を引数に設定することで、そのタグの全要素の配列を取得できます。

// 『<img>』タグの要素を、配列として選択
var imgs = document.getElementsByTagName("img");

注意するのは、『getElementsByTagName』と、『Element』が複数形になっていることです。この『s』を忘れる人が多いので注意してください。取得した要素の配列は、『for』文で順次処理していくことで操作できます。

// 配列に格納された各要素に対して処理を実行
for (var i = 0; i < imgs.length; i ++) {
    // 『width』(横幅)の値を書き換える
    imgs[i].width = (1 + i) * 32;
}

ここでは、全ての画像の『width』属性の値を書き換えて、画像の横幅を変更しています。

『getElementsByClassName』メソッド

次は、クラス名から要素を選択する『getElementsByClassName』メソッドです。『class』は、タグの中に書く属性の1つです。『class』属性は『id』属性と違い、同じWebページ中に複数配置することが可能です。

以下、簡単な例を示します。

<div class="target">目標の文字列1</div>
<div class="target">目標の文字列2</div>
<div class="target">目標の文字列3</div>
// 『class』属性が『target』の要素を、配列として選択
var targets = document.getElementsByClassName("target");

// 配列に格納された各要素に対して処理を実行
for (var i = 0; i < targets.length; i ++) {
    // 内部のHTMLを書き換える
    targets[i].innerHTML = i + ". 書き換え!";
}

こちらも『Elements』と、『Element』が複数形になっています。そのため取得した要素の配列は、『for』文で順次処理して操作できます。

『querySelector』『querySelectorAll』メソッド

次は、『セレクタ』と呼ばれる、特殊な記法で要素を選択する『querySelector』『querySelectorAll』メソッドです。『セレクタ』は、『CSS』などで、要素を指定するための書き方です。『CSS』は、もっと先の章で出てくるので、そのタイミングでまた見直してください。

『querySelector』はセレクタにマッチした最初の要素を、『querySelectorAll』は全ての要素を戻します。

以下、簡単な例を示します。

<div class="animal"></div>
<div class="animal"></div>
<div class="animal"></div>
// 『class』属性が『target』の要素を、配列として選択
var animals = document.querySelectorAll(".animal");

// 配列に格納された各要素に対して処理を実行
for (var i = 0; i < animals.length; i ++) {
    // 内部のHTMLを書き換える
    animals[i].innerHTML = "\" + animals[i].innerHTML + "/";
}

こちらも『Elements』と、『Element』が複数形になっています。そのため取得した要素の配列は、『for』文で順次処理して操作できます。

『DOM』で使用できる代表的なメソッド

以下、『DOM』操作で使用できるメソッドのうち、代表的なものを挙げておきます。

注:以下、『element』と書いてあるオブジェクトは、『document』もしくは『その他の要素』になります。

要素の取得

意味
document.getElementById(id) 『document』から、指定『ID』の要素を取得
element.getElementsByTagName(タグ名) 指定タグ名の要素の配列を取得
element.getElementsByName(nameの値) 指定『name』属性の要素の配列を取得
element.getElementsByClassName(classの値) 指定『class』属性の要素の配列を取得
element.querySelector(セレクタ) 指定『セレクタ』の要素の配列を取得
element.parentNode 親要素を取得
element.childNodes 子要素の配列を取得
element.firstChild 最初の子要素を取得
element.lastChild 最後の子要素を取得
element.previousSibling 1つ前の要素を取得
element.nextSibling 1つ後の要素を取得

要素内のHTMLやテキストにアクセス

意味
element.innerHTML 要素内のHTMLの文字列
element.textContent 要素内の文字列のみ

以下、プログラムのサンプルです。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        aaa<div>bbb</div>ccc

        <script>
        alert(document.body.innerHTML);
        alert(document.body.textContent);
        </script>
    </body>
</html>

『document.body.innerHTML』は、HTMLファイルの『<body>』タグ内のHTML文字列です。

『document.body.textContent』は、HTMLファイルの『<body>』タグ内の内部テキストです。

要素内の属性にアクセス(例は『id』へのアクセス)

意味 使い方 説明
element.属性名 属性の参照 a = element.id; 変数『a』に『id』の値を入れる
element.id = a; 『id』に変数『a』の値を入れる
element.getAttribute(属性名) 属性の取得 a = element.getAttribute("id"); 変数『a』に『id』の値を入れる
element.setAttribute(属性名, 値) 属性の設定 element.setAttribute("id", a); 『id』に変数『a』の値を入れる

要素の追加

要素の追加は、『innerHTML』の値に、文字列を設定することで行えます。また、要素を作成して、『DOM』の要素として追加することもできます。

以下、2種類の方法で、要素を追加する例を示します。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <div id="a"></div>
        <div id="b"></div>

        <script>
        var a = document.getElementById("a");
        var b = document.getElementById("b");

        a.innerHTML = '<div style="color: red">red</div>';

        var textEle = document.createTextNode("blue");
        var newEle = document.createElement("div");
        newEle.appendChild(textEle);
        newEle.setAttribute("style", "color: blue;");
        b.appendChild(newEle);
        </script>
    </body>
</html>

ここでは、『createTextNode』『createElement』というメソッドで新しい要素を作成しています。また、『appendChild』メソッドで、要素を子要素として、親要素に追加しています。

以下、それぞれのメソッドの意味を表に示します。

意味
element.createElement(タグ名) 『タグ名』の要素の作成
element.createTextNode(文字列) 文字列要素の作成
element.appendChild(要素) 要素を、子要素として追加

『DOM』は、それだけで本になるぐらい、様々なテクニックがあります。詳しく知りたければ、インターネットや書籍で調べてください。

参考

『フォーム』の操作

Webページには、『フォーム』と呼ばれるオブジェクトがあります。これは、ボタンやリスト、ラジオボタンや、チェックボックスなどです。

<form name="form1" method="get" action="index.cgi">
テキスト:
<input type="text" name="text1" value="text value" size=30>
<br>
テキスト エリア:<br>
<textarea name="tarea1" cols=40 rows=4></textarea>
<br>
<input type="checkbox" name="cbox1" checked>チェックボタン1
<br>
<input type="radio" name="radio1" value="r1" checked>ラジオボタン1
<input type="radio" name="radio1" value="r2">ラジオボタン2
<br>
<select name="select1">
<option value="1">セレクト1</option>
<option value="2">セレクト2</option>
<option value="3" selected>セレクト3</option>
</select>
<br>
<input type="hidden" name="hidden1" value="隠れた値">
<br>
<input type="submit" value="実行">
<input type="reset" value="取消">
</form>

これらの要素には、『DOM』以外の簡易な方法でもアクセスできます。

『document.(『フォーム』の『name』の値).(『フォームの部品』の『name』の値)』と書くことで、その要素を取得できます。

var element = document.form1.text1;

こうやって取得した要素は、部品の種類によって、操作方法が異なります。

文字列を入力する部品(『<input type="text">』『<textarea>』『<input type="hidden">』など)は、『value』プロパティを使って、内部の文字列を取得したり、書き換えたりできます。

var element = document.form1.text1;
alert("text1 : " + element.value);
element.value = "新しい値";

チェックボタン(『<input type="checkbox">』)や、ラジオボタン(『<input type="radio">』)は、『checked』プロパティを使って、選択状態を取得したり、変更したりできます。

var ele = document.form1.cbox1;
alert("cbox1 : " + ele.checked);
ele.checked = false;

var ele = document.form1.radio1;
if (ele.length) {
    // 配列の場合
    for (var i = 0; i < ele.length; i ++) {
        alert("radio1[" + i + "] : " + ele[i].checked);
    }
} else {
    // 1つしかない場合
    alert("radio1 : " + ele.checked);
}

セレクト(『<select>』)は、『selectedIndex』プロパティを使って、選択要素の番号を取得したり、変更したりできます。

var ele = document.form1.select1;
alert("select1 : " + ele.selectedIndex);
ele.selectedIndex = 0;

また『options』を利用して、セレクト配下の『<option>』の配列を取得できます。この配列は、『selected』プロパティを使って、選択状態を取得したり、変更したりできます。

var ele = document.form1.select1;
for (var i = 0; i < ele.length; i ++) {
    alert("select1[" + i + "] : " + ele[i].selected);
}

これらの要素には、『DOM』を使ってもアクセスできます。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <input type="text" id="input" value="AAA"><br>
        <select id="select">
            <option>0 : BBB</option>
            <option>1 : CCC</option>
        </select><br>
        <input type="checkbox" id="check" value="DDD">

        <script>
        var input = document.getElementById("input");
        input.value = "入力";

        var select = document.getElementById("select");
        select.selectedIndex = 1;

        var check = document.getElementById("check");
        check.checked = true;
        </script>
    </body>
</html>

さらに詳しく知りたい場合は、下記を参考にしてください。

参考

『location』オブジェクト

WebページのURLが保持されているオブジェクトです。『window.location』『location』のどちらの書き方でも利用できます。

以下、よく利用するプロパティを示します。

意味 中身の例
location.href URL https://www.google.com/hoge/hoge/index.cgi?q=search#result
location.protocol プロトコル https:
location.host ホスト www.google.com:8000
location.hostname ホスト名 www.google.com
location.port ポート 8000
location.pathname パスとファイル名 /hoge/hoge/index.cgi
location.search 検索などのCGIの値 ?q=search
location.hash #以降の内部リンク #result

この中で、『location.href』は特殊なプロパティです。『location.href』に新しいURLを代入すれば、そのページに移動することができます。

location.href = "https://crocro.com/";

上記のプログラムを実行すると、WebページのURLが『https://crocro.com/』に変わり、表示されているページが、このページに書き換わります。

サンプルの入手

以下は、今回出てきたサンプルです。

ZIPでまとめてダウンロード (右クリックから保存してください)

sample1.html』(要素内部の書き換え)を表示

sample2.html』(要素のプロパティ一覧)を表示

sample3.html』(画像の『src』を書き換え)を表示

sample4.html』(様々な方法で要素を選択)を表示

sample5.html』(要素内のHTMLやテキスト)を表示

sample6.html』(要素の追加)を表示

sample7.html』(フォームの操作)を表示

sample8.html』(フォームの操作)を表示

sample9.html』(『location』の書き換え)を表示

プログラムの中身を見たい場合は、それぞれのHTMLファイルをブラウザで開いたあと、右クリックをして『ソースの表示』を選択してください。

メモ帳で、ファイルの中身を見ることができます。