見出し画像

ブックマークレットで始める業務改善⑦ 検索フォームの自動化(まとめて操作)

前回はこちらです。

以前お伝えした通り、ブックマークレットのプログラムの基本は

  1. Webページ上の操作したい要素(入力フォームなど)を捕まえて、

  2. その要素に対してやりたいことをやる!

です。今回は、これを複数の要素に対してまとめて行う方法を解説します。

だんだんと、プログラムっぽくなっていきますよ😎 落ち着いてゆっくり進めましょう。


複数の要素を取得するプログラム

前回の練習問題で、エリアの8個のチェックボックスをひとつずつ操作しました。ちょっと面倒でしたね。

フォームによっては何十個もチェックボックスがあるかもしれませんし、何かに連動して動的に数が変わるかもしれません。そうなると全部を列挙することがそもそも難しくなってしまいます。

こういうときに使える、querySelectorAll( ) という関数があります。これまで使ってきた querySelector( ) の最後にAllが付きました。その名が示す通り、条件(CSSセレクターと言います)に当てはまる要素を全部取ってきてくれます。
※ querySelector( ) に複数の要素が見つかるCSSセレクターを指定すると、最初の要素がひとつだけ返ってきます。

querySelectorAll( ) の典型的な使い方は以下の通りです。

document.querySelectorAll(CSSセレクター).forEach(function(e){
	ここに処理内容を書く
});

CSSセレクターは、これまでは"#user_id"のようにIDを指定するものを使ってきました。同じIDはページの中に一つしか無いので、要素を一つしか捕まえてこない querySelector( ) で十分だったわけです。複数の要素を捕まえたいなら querySelectorAll( ) の出番です。

注意点として、
document.querySelectorAll(CSSセレクター).checked = true;
のようには書けません。querySelectorAll( ) は要素そのものではなく「要素のリスト」を返しているためです。forEach( )などを使う必要があります(後で説明します)。

では、querySelectorAll( ) を使ってエリアの8個のチェックボックスをまとめて捕まえるには、どのようなCSSセレクターを書けばよいのでしょうか。

デベロッパーツールで該当箇所を見てみると、以下のようになっていました。(適当にデベロッパーツールのウィンドウ幅を調整してください。)

8個のチェックボックスはすべてinputタグ(<input>)で、name="area"(このようなタグに付加された情報を属性といいます)を持っています。これをうまく使いたいですね。こんなときのCSSセレクターは以下のように書きます。

document.querySelectorAll("input[name='area']").forEach(function(e){
	ここに処理内容を書く
});

typeという属性を使いたければ、CSSセレクターは input[type='checkbox'] でもOKです。

複数の要素を操作するプログラム

querySelectorAll( ) で捕まえた要素たちにチェックを入れるには、以下のように書きます。

document.querySelectorAll("input[name='area']").forEach(function(e){
	e.checked = true;
});

分解して解説すると、

  • document.querySelectorAll("input[name='area']")で、ページ全体から該当する要素(8個)を捕まえています

  • forEach( )で、捕まえた要素をひとつずつ順番に処理しています

  • function(e) { } のところは、JavaScriptへの理解が進むまでは気にしなくて大丈夫です。常にコピペしてください

  • eは、forEachで処理の順番が来た要素が入っています。e.checked = true;でチェックを入れられますし、もし取得した要素がテキスト入力欄なら e.value = "こんにちは!"; とすれば文字を入力できます

ここまでをまとめると、前回のブックマークレットは以下のように短くできました!👏 動かしてみてください。

javascript:(function(){
    document.querySelector("#shipped").checked = true;
	document.querySelectorAll("input[name='area']").forEach(function(e){
		e.checked = true;
	});
    document.querySelector("#min-amount").value = "100000";
    document.querySelector("#max-amount").value = "1000000";
    document.querySelector("#submit-button").click();
})();

なお、ネットでforEachを使ったプログラムを調べていると、

document.querySelectorAll("input[name='area']").forEach(e => e.checked = true);

という矢印(=>)を使った書き方を見かけると思います。これはアロー関数という仕組みで、処理の内容は同じですが、プログラムをより短く書けます。お好みで好きな方をお使いください。

CSSセレクターの選び方

CSSセレクターの書き方はものすごくたくさんあります。今回のように属性を利用したものもあれば、親子関係を使うものもあります。次回、よく使うものを詳しく説明します。

今回の練習問題で言うと、以下のCSSセレクターはいずれも正解です。余力があればそれぞれ本当に動くか試してみてください。

  1. input[name='area']

  2. input[type='checkbox']

  3. [name='area']

  4. [type='checkbox']

  5. input[type='checkbox'][name='area']

3.や4.のように、実は今回はタグ(input)を指定する必要はありません。 name='area' や type='checkbox' の属性を持つ要素が他に無いからです。緩い絞り込みです。

5.のように、属性を複数指定することもできます。コンサバな(石橋をたたいて渡る方式の)絞り込みです。

ではどれがベストかというと、私なら実務では5.を選びます。他はいずれも絞り込みが緩く、今後の対象システムのバージョンアップで無関係な要素が増えたりすると、うまく動かなくなる恐れがあるからです。一方で、絞り込みがきつ過ぎるとそれはそれで変化に弱くなります。

このバランスは悩ましいところですが、なるべく想像力を働かせて、将来あり得る変更を考慮できるようになると良いです。ただしその前に、まず目先のwebページで動くものを作るのが先決ですが。

今回のまとめ

  • 複数の要素を捕まえるには querySelectorAll( ) を使います

  • querySelector( ) や querySelectorAll( ) に入れる検索条件をCSSセレクターと言います。いろいろな書き方がありますが、これまで出てきたのは

    • #user_id ← 要素のIDで指定(原則一個だけ見つかる)

    • input[name='area'] ← 要素のタグと属性で指定(複数見つかることもある)

  • 見つかった複数の要素に対して何かするときは、forEach( ) を使います


次回はこちらです。

このシリーズのすべての記事は、こちらのマガジンにまとめています。

🐶スキしていただけると励みになります!


この記事が気に入ったらサポートをしてみませんか?