JavaScript
【JavaScript】郵便番号を入力すると住所が自動入力されるライブラリYubinBango.jsを紹介
今回はJavaScriptのライブラリYubinBango.jsをご紹介します。
YubinBango.jsの設定方法や実装例を紹介していますので、参考にしてください。この記事は以下のお悩みを解決します。
- ・郵便番号を入力すると住所が自動で入力できるようにしたい
- ・「住所検索」ボタンを押してから住所が入力できるようにしたい
1. YubinBango.jsとは?
YubinBango.jsは郵便番号を入力すると自動で住所が入力されるJavaScriptのライブラリです。この機能はオンラインサービスやショッピングサイトなどの入力フォームでよく使われていますよね。
フォームの入力時間や入力ミスを減らすことができるのでユーザにとって便利な機能です。YubinBango.jsを利用すれば簡単に実装することができます。
YubinBango.jsの公式サイト(GitHub)
2. YubinBango.jsの設定方法
YubinBango.jsの設定方法は以下の通りです。
①ライブラリを読み込ませるために以下のコードをheadタグ内に記述します。
<script src="https://yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
②formタグにクラス名「h-adr」を指定します。
<form class="h-adr"></form>
③formタグの中に国名「Japan」とクラス名「p-country-name」を指定します。
以下の2つのコードのうちどちらか1つをformタグの中に記述します。この記述がないとライブラリは動作しないので注意しましょう。
<span class="p-country-name" style="display:none;">Japan</span>
<input type="hidden" class="p-country-name" value="Japan">
④郵便番号の入力するinputタグにクラス名「p-postal-code」を指定します。size属性はフォームの幅、maxlength属性は入力可能な文字数を指定します。
<input type="text" class="p-postal-code" size="8" maxlength="8">
また、inputタグが上3桁と下4桁に分かれている場合は以下のようになります。クラスは両方とも「p-postal-code」を指定します。
<input type="text" class="p-postal-code" size="3" maxlength="3">
<input type="text" class="p-postal-code" size="4" maxlength="4">
⑤都道府県を入力するinputタグに「p-region」クラスを指定します。
<input type="text" class="p-region">
また、都道府県はドロップダウンメニューで選択する場合もありますがその場合はselectタグにクラス名「p-region-id」を指定します。
<select class="p-region-id"></select>
⑥市町村区を入力するinputタグにはクラス名「p-locality」を指定します。
<input type="text" class="p-locality">
⑦町域を入力するinputタグにはクラス名「p-street-address」を指定します。
<input type="text" class="p-street-address">
⑧以降の住所を入力するinputタグにはクラス名「p-extended-address」を指定します。
<input type="text" class="p-extended-address">
以上で設定は完了です。
3. YubinBango.jsを使用したフォームの実装例
YubinBango.jsを使用したフォームの実装例をご紹介します。
3-1. 郵便番号の入力フォームが1つの場合
最初は郵便番号の入力フォームが1つの場合です。郵便番号はハイフン「-」があってもなくてもどちらでも住所は自動入力されます。
See the Pen Untitled by Hiro (@Coffee1610) on CodePen.
<head>
<script src="https://yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
</head>
<div class="container">
<!--formタグにクラス名「h-adr」を指定-->
<form action="" class="h-adr">
<!--国名「Japan」とクラス名「p-country-name」を指定-->
<span class="p-country-name" style="display:none;">Japan</span>
<dl>
<dt><label for="postal-code">郵便番号</label></dt>
<!--郵便番号を入力するinputタグにクラス名「p-postal-code」を指定-->
<dd><input type="text" id="postal-code" class="p-postal-code" size="8" maxlength="8"></dd>
<dt><label for="region">都道府県</label></dt>
<!--都道府県を入力するinputタグにクラス名「p-region」を指定-->
<dd><input type="text" id="region" class="p-region" size="30"></dd>
<dt><label for="locality">市町村区</label></dt>
<!--市町村区を入力するinputタグにクラス名「p-locality」を指定-->
<dd><input type="text" id="locality" class="p-locality" size="30"></dd>
<dt><label for="street-address">町域</label></dt>
<!--町域を入力するinputタグにクラス名「p-street-address」を指定-->
<dd><input type="text" id="street-address" class="p-street-address" size="30"></dd>
<dt><label for="extended-address">以降の住所</label></dt>
<!--以降の住所を入力するinputタグにクラス名「p-extended-address」を指定-->
<dd><input type="text" id="extended-address" class="p-extended-address" size="30"></dd>
</dl>
</form>
</div>
3-2. 郵便番号の入力フォームが上3桁、下4桁に分かれている場合
2つ目は郵便番号の入力フォームが上3桁と下4桁に分かれている場合です。これはハイフン「-」を挟んでもう一つinputタグを追加するだけです。クラス名は両方とも「p-postal-code」を指定します。
See the Pen Untitled by Hiro (@Coffee1610) on CodePen.
<head>
<script src="https://yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
</head>
<div class="container">
<!--formタグにクラス名「h-adr」を指定-->
<form action="" class="h-adr">
<!--国名「Japan」とクラス名「p-country-name」を指定-->
<span class="p-country-name" style="display:none;">Japan</span>
<dl>
<dt><label for="postal-code1">郵便番号</label></dt>
<!--郵便番号を入力するinputタグをハイフンを挟んでもう一つ追加し、両方にクラス名「p-postal-code」を指定-->
<dd><input type="text" id="postal-code1" class="p-postal-code" size="3" maxlength="3">-<input type="text" id="postal-code2" class="p-postal-code" size="4" maxlength="4"></dd>
<dt><label for="region">都道府県</label></dt>
<!--都道府県を入力するinputタグにクラス名「p-region」を指定-->
<dd><input type="text" id="region" class="p-region" size="10"></dd>
<dt><label for="locality">市町村区</label></dt>
<!--市町村区を入力するinputタグにクラス名「p-locality」を指定-->
<dd><input type="text" id="locality" class="p-locality" size="30"></dd>
<dt><label for="street-address">町域</label></dt>
<!--町域を入力するinputタグにクラス名「p-street-address」を指定-->
<dd><input type="text" id="street-address" class="p-street-address" size="30"></dd>
<!--以降の住所を入力するinputタグにクラス名「p-extended-address」を指定-->
<dt><label for="extended-address">以降の住所</label></dt>
<dd><input type="text" id="extended-address" class="p-extended-address" size="30"></dd>
</dl>
</form>
</div>
3-3. 住所の入力フォームが1つの場合
3つ目は住所の入力フォームが1つの場合です。住所を入力するinputタグにクラス名「p-region」、「p-locality」、「p-street-address」、「p-extended-address」を全て指定します。
See the Pen Untitled by Hiro (@Coffee1610) on CodePen.
<head>
<script src="https://yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
</head>
<div class="container">
<!--formタグにクラス名「h-adr」を指定-->
<form action="" class="h-adr">
<!--国名「Japan」とクラス名「p-country-name」を指定-->
<span class="p-country-name" style="display:none;">Japan</span>
<dl>
<dt><label for="postal-code">郵便番号</label></dt>
<!--郵便番号を入力するinputタグにクラス名「p-postal-code」を指定-->
<dd><input type="text" id="postal-code" class="p-postal-code" size="8" maxlength="8"></dd>
<dt><label for="address">住所</label></dt>
<!--住所を入力するinputタグにクラス名「p-region」 「p-locality」 「p-street-address」 「p-extended-address」を全て指定-->
<dd><input type="text" id="address" class="p-region p-locality p-street-address p-extended-address" size="50"></dd>
</dl>
</form>
</div>
3-4. 都道府県のフォームがドロップダウンメニューの場合
4つ目は都道府県の入力がドロップダウンメニューで入力する場合です。入力フォーム(inputタグ)の場合はクラス名「p-region」を指定していましたが、ドロップダウンメニューの場合はselectタグにクラス名「p-region-id」を指定します。
See the Pen Untitled by Hiro (@Coffee1610) on CodePen.
<head>
<script src="https://yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
</head>
<div class="container">
<!--formタグにクラス名「h-adr」を指定-->
<form action="" class="h-adr">
<!--国名「Japan」とクラス名「p-country-name」を指定-->
<span class="p-country-name" style="display:none;">Japan</span>
<dl>
<dt><label for="postal-code">郵便番号</label></dt>
<!--郵便番号を入力するinputタグにクラス名「p-postal-code」を指定-->
<dd><input type="text" class="p-postal-code" size="8" maxlength="8"></dd>
<dt><label for="region">都道府県</label></dt>
<dd>
<!--都道府県を入力するselectタグにクラス名「p-region-id」を指定-->
<select name="" id="region" class="p-region-id">
<option value="1">北海道</option>
<option value="2">青森県</option>
<option value="3">秋田県</option>
<option value="4">岩手県</option>
<option value="5">山形県</option>
<option value="6">宮城県</option>
<option value="7">福島県</option>
<option value="8">茨城県</option>
<option value="9">栃木県</option>
<option value="10">群馬県</option>
<option value="11">千葉県</option>
<option value="12">埼玉県</option>
<option value="13">東京都</option>
<option value="14">神奈川県</option>
<option value="15">新潟県</option>
<option value="16">長野県</option>
<option value="17">山梨県</option>
<option value="18">静岡県</option>
<option value="19">愛知県</option>
<option value="20">岐阜県</option>
<option value="21">三重県</option>
<option value="22">富山県</option>
<option value="23">石川県</option>
<option value="24">福井県</option>
<option value="25">和歌山県</option>
<option value="26">奈良県</option>
<option value="27">滋賀県</option>
<option value="28">京都府</option>
<option value="29">大阪府</option>
<option value="30">兵庫県</option>
<option value="31">岡山県</option>
<option value="32">広島県</option>
<option value="33">山口県</option>
<option value="34">鳥取県</option>
<option value="35">島根県</option>
<option value="36">徳島県</option>
<option value="37">香川県</option>
<option value="38">高知県</option>
<option value="39">愛媛県</option>
<option value="40">福岡県</option>
<option value="41">佐賀県</option>
<option value="42">長崎県</option>
<option value="43">大分県</option>
<option value="44">宮崎県</option>
<option value="45">熊本県</option>
<option value="46">鹿児島県</option>
<option value="47">沖縄県</option>
</select>
</dd>
<dt><label for="locality">市町村区</label></dt>
<!--市町村区を入力するinputタグにクラス名「p-locality」を指定-->
<dd><input type="text" id="locality" class="p-locality" size="30"></dd>
<dt><label for="street-address">町域</label></dt>
<!--町域を入力するinputタグにクラス名「p-street-address」を指定-->
<dd><input type="text" id="street-address" class="p-street-address" size="30"></dd>
<dt><label for="extended-address">それ以降の住所</label></dt>
<!--以降の住所を入力するinputタグにクラス名「p-extended-address」を指定-->
<dd><input type="text" id="extended-address" class="p-extended-address" size="30"></dd>
</dl>
</form>
</div>
3-5. ボタンを押すと住所が入力される場合
5つ目は郵便番号のフォームの隣に「住所検索」ボタンを作成し、郵便番号を入力後ボタンを押すと住所が入力される場合です。
これまでとは違い、郵便番号を入力しても自動で住所が入力されないようにJavaScriptで指定する必要があります。
以下のサイトを参考にさせていただきました。
See the Pen Untitled by Hiro (@Coffee1610) on CodePen.
<head>
<script src="https://yubinbango.github.io/yubinbango/yubinbango.js" charset="UTF-8"></script>
</head>
<div class="container">
<!--formタグにクラス名「h-adr」を指定-->
<form action="" class="h-adr">
<!--国名「Japan」とクラス名「p-country-name」を指定-->
<span class="p-country-name" style="display:none;">Japan</span>
<dl>
<dt><label for="postal-code1">郵便番号</label></dt>
<!--郵便番号を入力するinputタグにクラス名「p-postal-code」を指定、 住所検索ボタンを追加-->
<dd><input type="text" id="postal-code1" class="p-postal-code" size="3" maxlength="3">-<input type="text" id="postal-code2" class="p-postal-code" size="4" maxlength="4"><button type="button" class="address-search">住所検索</button></dd>
<dt><label for="region">都道府県</label></dt>
<dd>
<!--都道府県を入力するselectタグにクラス名「p-region-id」を指定-->
<select name="" id="region" class="p-region-id">
<option value="1">北海道</option>
<option value="2">青森県</option>
<option value="3">秋田県</option>
<option value="4">岩手県</option>
<option value="5">山形県</option>
<option value="6">宮城県</option>
<option value="7">福島県</option>
<option value="8">茨城県</option>
<option value="9">栃木県</option>
<option value="10">群馬県</option>
<option value="11">千葉県</option>
<option value="12">埼玉県</option>
<option value="13">東京都</option>
<option value="14">神奈川県</option>
<option value="15">新潟県</option>
<option value="16">長野県</option>
<option value="17">山梨県</option>
<option value="18">静岡県</option>
<option value="19">愛知県</option>
<option value="20">岐阜県</option>
<option value="21">三重県</option>
<option value="22">富山県</option>
<option value="23">石川県</option>
<option value="24">福井県</option>
<option value="25">和歌山県</option>
<option value="26">奈良県</option>
<option value="27">滋賀県</option>
<option value="28">京都府</option>
<option value="29">大阪府</option>
<option value="30">兵庫県</option>
<option value="31">岡山県</option>
<option value="32">広島県</option>
<option value="33">山口県</option>
<option value="34">鳥取県</option>
<option value="35">島根県</option>
<option value="36">徳島県</option>
<option value="37">香川県</option>
<option value="38">高知県</option>
<option value="39">愛媛県</option>
<option value="40">福岡県</option>
<option value="41">佐賀県</option>
<option value="42">長崎県</option>
<option value="43">大分県</option>
<option value="44">宮崎県</option>
<option value="45">熊本県</option>
<option value="46">鹿児島県</option>
<option value="47">沖縄県</option>
</select>
</dd>
<dt><label for="locality">市町村区</label></dt>
<!--市町村区を入力するinputタグにクラス名「p-locality」を指定-->
<dd><input type="text" id="locality" class="p-locality" size="30"></dd>
<dt><label for="street-address">町域</label></dt>
<!--町域を入力するinputタグにクラス名「p-street-address」を指定-->
<dd><input type="text" id="street-address" class="p-street-address" size="30"></dd>
<dt><label for="extended-address">それ以降の住所</label></dt>
<!--以降の住所を入力するinputタグにクラス名「p-extended-address」を指定-->
<dd><input type="text" id="extended-address" class="p-extended-address" size="30"></dd>
</dl>
</form>
</div>
const hadr = document.querySelector(".h-adr");
const btn = document.querySelector(".address-search");
const postalcode = hadr.querySelectorAll(".p-postal-code");
const postalcodeField = postalcode[postalcode.length - 1];
let cancelFlag = true;
const eventCanceler = (e) => {
//cancelFlagがtrueならYubinBango.jsのkeyupイベントを実行させない
if(cancelFlag) {
e.stopImmediatePropagation();
}
return false;
}
postalcodeField.addEventListener("keyup", eventCanceler);
btn.addEventListener("click", () => {
//ボタンがクリックされたらcancelFlagをfalseにする
cancelFlag = false;
let event;
//ブラウザがEventクラスをサポートしているかどうか
if(typeof Event === "function") {
//新しいkeyupイベントを作成
event = new Event("keyup");
}else {
//新しいkeyupイベントを作成
event = document.createEvent("Event");
event.initEvent("keyup", false, false);
}
//eventを実行する
postalcodeField.dispatchEvent(event);
//処理が実行されたらcancelFlagをtrueにする
cancelFlag = true;
});
JavaScriptの解説
1行目:const hadr = document.querySelector(“.h-adr”);
querySelector()は指定したセレクタに一致する最初の要素を返します。ここでは「h-adr」クラス(formタグ)を取得しています。
2行目:const btn = document.querySelector(“.address-search”);
「address-search」クラス(住所検索ボタン)を取得しています。
3行目:const postalcode = hadr.querySelectorAll(“.p-postal-code”);
querySelectorAll()は指定したセレクタに一致する全ての要素(NodeList)を返します。「p-postal-code」クラスは郵便番号を入力するinputタグです。今回はinputタグが2つあるため両方を取得しています。
4行目:const postalcodeField = postalcode[postalcode.length – 1];
postalcodeFieldはpostalcodeの最後の要素を取得します。ここでは郵便番号の下4桁を入力するinputタグを取得しています。
8-14行目:const eventCanceler = (e) => {~}
郵便番号が入力したときに自動で住所が入力されないようにする関数です。
10-12行目:if(cancelFlag) {e.stopImmediatePropagation();};
cancelFlagがtrueのときe.stopImmediatePropagation()を実行します。これによりYubinBango.jsに登録されているイベントリスナーが呼び出されず、郵便番号を入力しても住所が自動で入力されなくなります。
e.stopImmediatePropagation()については、目次4の補足で解説していますのでよくわからないという方は参考にしてください。
16行目:postalField.addEventListener(“keyup”, eventCanceler);
YubinBango.jsは郵便番号の入力フォームが2つある場合、下4桁のフォームに郵便番号を入力するとkeyupイベントが発生し住所が入力されます。
eventCancelerを実行すると、YubinBango.jsに登録されているイベントリスナーが呼び出されないので住所が入力されなくなります。
18-38行目:btn.addEventListener(“click”, () => {~});
住所検索ボタンをクリックすると処理を実行します。
20行目:cancelFlag = false;
住所検索ボタンをクリックしたらcancelFlagをfalseに変更します。
24-32行目:if(typeof Event === “function”) {~};
現在使用しているブラウザがEventコンストラクターをサポートしてるかどうかをtypeofを使って判定しています。
古いブラウザはEventコンストラクターをサポートしていない場合があるので、その場合はelse以降の処理を実行します。
26行目:event = new Event(“keyup”);
ブラウザがEventコンストラクターをサポートしている場合はnew Event()でイベントを生成します。
第1引数にはイベントの種類(clickやkeyupなどの既存のイベントまたはカスタムイベントの任意のイベント名)を指定します。ここではkeyupイベントを生成してます。
第2引数にはbubbles(イベントを祖先要素に伝搬するかどうか 既定値:false)、cancelable(イベントがキャンセル可能か 既定値:false )をオブジェクトで指定できます。第2引数は省略可能で今回は省略されているので既定値のfalseになります。
29行目:event = document.createEvent(“Event”);
ブラウザがEventコンストラクターをサポートしていない場合はcreateEvent()でイベントを生成します。引数にはイベントの種類(Event、MouoseEventsなど)を指定します。
30行目:event.initEvent(“keyup”, false, false);
createEvent()で生成したイベントをinitEvent()で初期化します。第1引数はイベントの種類(clickやscrollなど)、第2引数はbubbles(イベントを祖先要素に伝搬するかどうか)、第3引数はcancelable(イベントをキャンセル可能か)を指定します。
現在、createEvent()とinitEvent()は非推奨になっているので、古いブラウザに対応する必要がない場合は使用は避けたほうがいいでしょう。
33行目:postalcodeField.dispatchEvent(event);
dispatchEvent()は定義したeventを実行します。
35行目:cancelFlag = true;
eventを実行後、cancelFlagをtrueに変更します。
4. 補足
ここではe.stopImmediatePropagation()についてもう少し詳しく解説します。
同じ要素に対して同じ発火条件のイベントを複数のイベントリスナーに登録している場合、順番にイベントリスナーが呼び出されますが途中でe.stopImmediatePropagation()が実行されると、残りのイベントリスナーが呼び出されなくなります。
少しわかりくいと思うので具体例を見てみましょう。ボタンを1つ作成し、クリックするとアラートが表示されるイベントリスナーを2つ登録します。
<div>
<button type="button" class="btn">ボタン</button>
</div>
const btn = document.querySelector(".btn");
btn.addEventListener("click", () => {
alert("A");
});
btn.addEventListener("click", () => {
alert("B");
});
これが同じ要素(ボタン)に対して同じ発火条件のイベント(click)を複数のイベントリスナーに登録している状態です。
ボタンを押すと以下のようになります。
アラートはAとBが表示されています。ボタンをクリックすると上のイベントリスナーから順に呼び出されて、実行されていることがわかります。
次に上のイベントリスナーにe.stopImmediatePropagation()を指定します。
const btn = document.querySelector(".btn");
btn.addEventListener("click", (e) => {
alert("A");
e.stopImmediatePropagation();
});
btn.addEventListener("click", () => {
alert("B");
});
ボタンをクリックすると以下のようになります。
今度はアラートはAしか表示されていません。この結果からe.stopImmediatePropagation()の実行後、次のイベントリスナーは呼び出されず実行されていないことがわかります。
次に目次3-5の場合では、JavaScriptファイルの16行目に以下のイベントリスナーを登録しています。
postalField.addEventListener("keyup", eventCanceler);
postalFieldはpostalcode[postalcode.length – 1]が入った変数、eventCancelerはe.stopImmediatePropagation()が実行される関数です。
一方、YubinBango.jsには住所が自動入力されるように処理が記述されたイベントリスナーが登録されています。
postalcode[postalcode.length - 1].addEventListener("keyup", (e) => {
//郵便番号を入力すると住所が自動入力されるように処理が記述されています
}, false);
つまりこの2つのイベントリスナーは同じ要素(postalcode[postalcode.length – 1])に対して同じ発火条件のイベント(keyup)が複数のイベントリスナーに登録されている状態になります。
postalField.addEventListener(“keyup”, eventCanceler)が呼び出されてe.stopImmediatePropagation()が実行されるとYubinBango.jsのイベントリスナーは呼び出されないので住所の自動入力は実行されないということになります。
5. まとめ
今回は郵便番号を入力すると住所の自動入力が実装できるライブラリYubinBango.jsをご紹介しました。
ボタンを押してから住所を入力させる場合はJavaScriptを記述する必要がありますがそれ以外はHTMLにクラスを指定するだけで簡単に設定にできるようになっているので非常にありがたいですね。
ぜひ、ご自身で実際に使って確認してみてください。