💻
郵便番号を住所に変換するサイトを作成する
概要
JavaScript で郵便番号を住所に変換するサイトを作成します。
- 郵便番号の入力チェックに正規表現を使用する
- 郵便番号と住所の変換で非同期処理を使用する
- 住所をクリップボードにコピーする
完成画像
完成画像
実装
プロジェクトを作成する
1. プロジェクトを作成する
プロジェクトのディレクトリを任意の場所に作成し、Visual Studio Code でプロジェクトを開いてください。
2. HTML ファイルを作成する
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>郵便番号を住所に変換する</title>
<link rel="stylesheet" href="style.css" />
</head>
<body class="flex-col flex-center">
<div class="container flex-col flex-center w-320 gap-md">
<h1 class="text">郵便番号を住所に変換する</h1>
</div>
<script type="module" src="main.js" defer></script>
</body>
</html>
3. CSS ファイルを作成する
style.css
* {
margin: 0;
padding: 0;
}
/* objectの上にあるボタンのクリックイベントを発火させる */
object {
pointer-events: none;
}
body {
height: 100vh;
}
.container {
padding: 20px;
border-radius: 10px;
border: 1px solid #ccc;
}
#zipcode {
flex-grow: 1;
padding: 2px 16px;
}
/* 横幅 */
.w-240 {
width: 240px;
}
.w-320 {
width: 320px;
}
.w-full {
width: 100%;
}
/* フレックスボックス */
.flex-col {
display: flex;
flex-direction: column;
}
.flex-row {
display: flex;
flex-direction: row;
}
.flex-center {
justify-content: center;
align-items: center;
}
.flex-between {
justify-content: space-between;
align-items: center;
}
.flex-start {
justify-content: flex-start;
align-items: center;
}
/* グリッドレイアウト */
/* .grid {
display: grid;
grid-template-columns: 5fr 1fr;
} */
/* フレックスボックやグリッドレイアウトの空白 */
.gap-sm {
gap: 10px;
}
.gap-md {
gap: 20px;
}
.gap-lg {
gap: 30px;
}
/* テキストサイズ */
.text {
font-size: 20px;
}
.error {
color: red;
}
/* ボタン */
button {
background: #50b894;
color: #fff;
border: none;
padding: 10px;
cursor: pointer;
}
button:hover {
background: #38a06f;
}
4. JavaScript ファイルを作成する
main.js
5. SVG ファイルを作成する
<!--?xml version="1.0" encoding="utf-8"?-->
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="width: 256px; height: 256px; opacity: 1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#4B4B4B;}
</style>
<g>
<rect x="115.774" y="335.487" class="st0" width="194.387" height="18.588" style="fill: rgb(75, 75, 75);"></rect>
<rect x="115.774" y="260.208" class="st0" width="194.387" height="18.527" style="fill: rgb(75, 75, 75);"></rect>
<rect x="115.774" y="184.862" class="st0" width="194.387" height="18.588" style="fill: rgb(75, 75, 75);"></rect>
<rect x="218.582" y="109.576" class="st0" width="91.58" height="18.588" style="fill: rgb(75, 75, 75);"></rect>
<path class="st0" d="M385.112,396.188V39.614c0-2.294-0.197-4.603-0.592-6.768C381.3,14.19,365.006,0,345.438,0H184.686
c-11.561,0-22.598,4.603-30.741,12.747L53.637,112.986c-8.151,8.22-12.747,19.249-12.747,30.818v252.384
c0,21.802,17.806,39.607,39.683,39.607h264.864C367.308,435.795,385.112,417.99,385.112,396.188z M170.634,27.529v89.074
c0,9.662-3.745,13.399-13.339,13.399H68.222L170.634,27.529z M63.163,396.188V149.775h106.02c3.486,0,6.768-0.85,9.655-2.362
c4.079-2.036,7.361-5.324,9.328-9.328c1.519-2.894,2.302-6.115,2.302-9.526V22.272h154.97c7.156,0,13.331,4.33,15.959,10.574
c0.92,2.104,1.376,4.337,1.376,6.768v356.574c0,9.518-7.748,17.342-17.335,17.342H80.574
C70.98,413.53,63.163,405.706,63.163,396.188z" style="fill: rgb(75, 75, 75);"></path>
<path class="st0" d="M431.488,76.205h-26.732l1.375,22.272h25.356c9.594,0,17.349,7.748,17.349,17.342v356.573
c0,9.519-7.755,17.342-17.349,17.342H166.562c-7.163,0-13.339-4.406-15.968-10.581c-0.85-2.097-1.374-4.33-1.374-6.761V456.89
h-22.272v15.503c0,2.294,0.198,4.589,0.593,6.761c3.22,18.588,19.515,32.846,39.022,32.846h264.926
c21.877,0,39.622-17.805,39.622-39.607V115.82C471.11,93.943,453.365,76.205,431.488,76.205z" style="fill: rgb(75, 75, 75);"></path>
</g>
</svg>
郵便番号の入力欄を検証する
1. 郵便番号を入力するフォームを作成する
index.html
<div class="container flex-col flex-center w-320 gap-md">
<h1 class="text">郵便番号を住所に変換する</h1>
<form id="form" class="flex-col flex-center gap-sm w-full">
<div class="flex-row gap-sm w-full">
<input type="text" id="zipcode" placeholder="郵便番号" class="text" />
<button type="submit">検索</button>
</div>
<div id="zipcodeError" class="error"></div>
</form>
</div>
2. submit イベントの中で郵便番号を検証する
main.js
/* ****************************************
要素一覧
**************************************** */
const formElement = document.getElementById("form");
const zipcodeElement = document.getElementById("zipcode");
const zipcodeErrorElement = document.getElementById("zipcodeError");
/* ****************************************
処理
**************************************** */
formElement.addEventListener("submit", onSubmit);
/* ****************************************
関数一覧
**************************************** */
/** 郵便番号を検証する */
function validateZipcode(zipcode) {
// 郵便番号の正規表現
const pattern = /^\d{3}-?\d{4}$/;
// 入力された郵便番号が正しいかどうかを返す
return pattern.test(zipcode);
}
/** 郵便番号のエラーメッセージを設定する */
function setZipcodeError(isValid) {
// エラーメッセージを設定する
if (isValid) {
zipcodeErrorElement.innerText = "";
} else {
zipcodeErrorElement.innerText = "郵便番号が正しくありません";
}
}
/* ****************************************
イベントの関数一覧
**************************************** */
async function onSubmit(event) {
// イベントをキャンセルする
event.preventDefault();
// 郵便番号を取得する
const zipcode = zipcodeElement.value;
// 郵便番号が正しくない場合は、エラーメッセージを表示する
const isValid = validateZipcode(zipcode);
// 郵便番号が正しくない場合は、エラーメッセージを表示する
setZipcodeError(isValid);
if (!isValid) {
return;
}
console.log("submit");
}
郵便番号を住所に変換する
1. 住所の表示欄を作成する
index.html
<div class="container flex-col flex-center w-320 gap-md">
<h1 class="text">郵便番号を住所に変換する</h1>
<form id="form" class="flex-col flex-center gap-sm w-full">
<div class="flex-row gap-sm w-full">
<input type="text" id="zipcode" placeholder="郵便番号" class="text" />
<button type="submit">検索</button>
</div>
<div id="zipcodeError" class="error"></div>
</form>
<div class="flex-row flex-between gap-sm w-full">
<div class="flex-row flex-start gap-sm text">
<div>住所:</div>
<div id="address"></div>
</div>
</div>
</div>
2. 非同期処理で郵便番号を住所に変換する
main.js
/* ****************************************
要素一覧
**************************************** */
const addressElement = document.getElementById("address");
/* ****************************************
イベントの関数一覧
**************************************** */
async function onSubmit(event) {
// イベントをキャンセルする
event.preventDefault();
// 郵便番号を取得する
const zipcode = zipcodeElement.value;
// 郵便番号が正しくない場合は、エラーメッセージを表示する
const isValid = validateZipcode(zipcode);
// 郵便番号が正しくない場合は、エラーメッセージを表示する
setZipcodeError(isValid);
if (!isValid) {
return;
}
// 郵便番号を住所に変換するWebAPIのURL
const url = `https://zipcloud.ibsnet.co.jp/api/search?zipcode=${zipcode}`;
try {
// WebAPIにリクエストを送信する
const response = await fetch(url);
// レスポンスデータをJSON形式からオブジェクトに変換する
const data = await response.json();
// 住所を表示する
const result = data.results[0];
addressElement.innerText = `${result.address1}${result.address2}${result.address3}`;
} catch (error) {
// 郵便番号から住所を取得できなかったメッセージを表示する
addressElement.innerText = "住所が取得できませんでした";
}
}
住所をクリップボードにコピーする
1. クリップボードに保存するボタンを作成する
index.html
<div class="container flex-col flex-center w-320 gap-md">
<h1 class="text">郵便番号を住所に変換する</h1>
<form id="form" class="flex-col flex-center gap-sm w-full">
<div class="flex-row gap-sm w-full">
<input type="text" id="zipcode" placeholder="郵便番号" class="text" />
<button type="submit">検索</button>
</div>
<div id="zipcodeError" class="error"></div>
</form>
<div class="flex-row flex-between gap-sm w-full">
<div class="flex-row flex-start gap-sm text">
<div>住所:</div>
<div id="address"></div>
</div>
<button type="button" id="copy" class="flex-col flex-center">
<object data="clipboard.svg" width="24" height="24"></object>
</button>
</div>
</div>
2. クリップボードに住所をコピーする
main.js
/* ****************************************
要素一覧
**************************************** */
const copyElement = document.getElementById("copy");
/* ****************************************
処理
**************************************** */
copyElement.addEventListener("click", copyToClipboard);
/* ****************************************
イベントの関数一覧
**************************************** */
/** クリップボードにコピーする */
function copyToClipboard() {
// 住所を取得する
const address = addressElement.innerText;
// 住所が空の場合は何もしない
if (address.length === 0) {
return;
}
// 住所をクリップボードにコピーする
try {
navigator.clipboard.writeText(address);
alert("住所をコピーしました");
} catch (error) {
alert("コピーに失敗しました");
}
}
完成のソースコード
index.html
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>郵便番号を住所に変換する</title>
<link rel="stylesheet" href="style.css" />
</head>
<body class="flex-col flex-center">
<div class="container flex-col flex-center w-320 gap-md">
<h1 class="text">郵便番号を住所に変換する</h1>
<form id="form" class="flex-col flex-center gap-sm w-full">
<div class="flex-row gap-sm w-full">
<input type="text" id="zipcode" placeholder="郵便番号" class="text" />
<button type="submit">検索</button>
</div>
<div id="zipcodeError" class="error"></div>
</form>
<div class="flex-row flex-between gap-sm w-full">
<div class="flex-row flex-start gap-sm text">
<div>住所:</div>
<div id="address"></div>
</div>
<button type="button" id="copy" class="flex-col flex-center">
<object data="clipboard.svg" width="24" height="24"></object>
</button>
</div>
</div>
<script type="module" src="main.js" defer></script>
</body>
</html>
style.css
style.css
* {
margin: 0;
padding: 0;
}
/* objectの上にあるボタンのクリックイベントを発火させる */
object {
pointer-events: none;
}
body {
height: 100vh;
}
.container {
padding: 20px;
border-radius: 10px;
border: 1px solid #ccc;
}
#zipcode {
flex-grow: 1;
padding: 2px 16px;
}
/* 横幅 */
.w-240 {
width: 240px;
}
.w-320 {
width: 320px;
}
.w-full {
width: 100%;
}
/* フレックスボックス */
.flex-col {
display: flex;
flex-direction: column;
}
.flex-row {
display: flex;
flex-direction: row;
}
.flex-center {
justify-content: center;
align-items: center;
}
.flex-between {
justify-content: space-between;
align-items: center;
}
.flex-start {
justify-content: flex-start;
align-items: center;
}
/* グリッドレイアウト */
/* .grid {
display: grid;
grid-template-columns: 5fr 1fr;
} */
/* フレックスボックやグリッドレイアウトの空白 */
.gap-sm {
gap: 10px;
}
.gap-md {
gap: 20px;
}
.gap-lg {
gap: 30px;
}
/* テキストサイズ */
.text {
font-size: 20px;
}
.error {
color: red;
}
/* ボタン */
button {
background: #50b894;
color: #fff;
border: none;
padding: 10px;
cursor: pointer;
}
button:hover {
background: #38a06f;
}
main.js
main.js
"use strict";
/* ****************************************
要素一覧
**************************************** */
const formElement = document.getElementById("form");
const zipcodeElement = document.getElementById("zipcode");
const zipcodeErrorElement = document.getElementById("zipcodeError");
const addressElement = document.getElementById("address");
const copyElement = document.getElementById("copy");
/* ****************************************
処理
**************************************** */
formElement.addEventListener("submit", onSubmit);
copyElement.addEventListener("click", copyToClipboard);
/* ****************************************
関数一覧
**************************************** */
/** 郵便番号を検証する */
function validateZipcode(zipcode) {
// 郵便番号の正規表現
const pattern = /^\d{3}-?\d{4}$/;
// 入力された郵便番号が正しいかどうかを返す
return pattern.test(zipcode);
}
/** 郵便番号のエラーメッセージを設定する */
function setZipcodeError(isValid) {
// エラーメッセージを設定する
if (isValid) {
zipcodeErrorElement.innerText = "";
} else {
zipcodeErrorElement.innerText = "郵便番号が正しくありません";
}
}
/* ****************************************
イベントの関数一覧
**************************************** */
async function onSubmit(event) {
// イベントをキャンセルする
event.preventDefault();
// 郵便番号を取得する
const zipcode = zipcodeElement.value;
// 郵便番号が正しくない場合は、エラーメッセージを表示する
const isValid = validateZipcode(zipcode);
// 郵便番号が正しくない場合は、エラーメッセージを表示する
setZipcodeError(isValid);
if (!isValid) {
return;
}
// 郵便番号を住所に変換するWebAPIのURL
const url = `https://zipcloud.ibsnet.co.jp/api/search?zipcode=${zipcode}`;
try {
// WebAPIにリクエストを送信する
const response = await fetch(url);
// レスポンスデータをJSON形式からオブジェクトに変換する
const data = await response.json();
// 住所を表示する
const result = data.results[0];
addressElement.innerText = `${result.address1}${result.address2}${result.address3}`;
} catch (error) {
// 郵便番号から住所を取得できなかったメッセージを表示する
addressElement.innerText = "住所が取得できませんでした";
}
}
/** クリップボードにコピーする */
function copyToClipboard() {
// 住所を取得する
const address = addressElement.innerText;
// 住所が空の場合は何もしない
if (address.length === 0) {
return;
}
// 住所をクリップボードにコピーする
try {
navigator.clipboard.writeText(address);
alert("住所をコピーしました");
} catch (error) {
alert("コピーに失敗しました");
}
}
clipboard.svg
<!--?xml version="1.0" encoding="utf-8"?-->
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="width: 256px; height: 256px; opacity: 1;" xml:space="preserve">
<style type="text/css">
.st0{fill:#4B4B4B;}
</style>
<g>
<rect x="115.774" y="335.487" class="st0" width="194.387" height="18.588" style="fill: rgb(75, 75, 75);"></rect>
<rect x="115.774" y="260.208" class="st0" width="194.387" height="18.527" style="fill: rgb(75, 75, 75);"></rect>
<rect x="115.774" y="184.862" class="st0" width="194.387" height="18.588" style="fill: rgb(75, 75, 75);"></rect>
<rect x="218.582" y="109.576" class="st0" width="91.58" height="18.588" style="fill: rgb(75, 75, 75);"></rect>
<path class="st0" d="M385.112,396.188V39.614c0-2.294-0.197-4.603-0.592-6.768C381.3,14.19,365.006,0,345.438,0H184.686
c-11.561,0-22.598,4.603-30.741,12.747L53.637,112.986c-8.151,8.22-12.747,19.249-12.747,30.818v252.384
c0,21.802,17.806,39.607,39.683,39.607h264.864C367.308,435.795,385.112,417.99,385.112,396.188z M170.634,27.529v89.074
c0,9.662-3.745,13.399-13.339,13.399H68.222L170.634,27.529z M63.163,396.188V149.775h106.02c3.486,0,6.768-0.85,9.655-2.362
c4.079-2.036,7.361-5.324,9.328-9.328c1.519-2.894,2.302-6.115,2.302-9.526V22.272h154.97c7.156,0,13.331,4.33,15.959,10.574
c0.92,2.104,1.376,4.337,1.376,6.768v356.574c0,9.518-7.748,17.342-17.335,17.342H80.574
C70.98,413.53,63.163,405.706,63.163,396.188z" style="fill: rgb(75, 75, 75);"></path>
<path class="st0" d="M431.488,76.205h-26.732l1.375,22.272h25.356c9.594,0,17.349,7.748,17.349,17.342v356.573
c0,9.519-7.755,17.342-17.349,17.342H166.562c-7.163,0-13.339-4.406-15.968-10.581c-0.85-2.097-1.374-4.33-1.374-6.761V456.89
h-22.272v15.503c0,2.294,0.198,4.589,0.593,6.761c3.22,18.588,19.515,32.846,39.022,32.846h264.926
c21.877,0,39.622-17.805,39.622-39.607V115.82C471.11,93.943,453.365,76.205,431.488,76.205z" style="fill: rgb(75, 75, 75);"></path>
</g>
</svg>
Discussion