様々なフォーカス移動機能や、入力検証のメッセージやアイコン、表形式のドロップダウンなどを備えたお問い合わせフォーム画面を作成する方法を紹介します。ここでは以下の機能を実装しています。快適な入力操作をお試しいただけます。
EnterキーおよびShift+Enterキーでのフォーカス移動
左右矢印キーでのフォーカス移動
入力完了時の自動フォーカス移動(郵便番号、電話番号)
未入力時のウォーターマーク表示
未入力を示す背景色と境界線色
入力完了を示すアイコン
ドロップダウンプラグインを使用した任意のドロップダウンオブジェクト(都道府県名)
ふりがなの自動出力および全角カナ制限
メールアドレス書式チェック
最大文字数チェック(お問い合わせ)
フォームデータ送信、ブラウザ更新時でのフォームデータの保存
import '@mescius/inputman/CSS/gc.inputman-js.css';
import '@mescius/inputman.richtexteditor/CSS/gc.inputman.richtexteditor.css';
import './styles.css';
import { InputMan } from '@mescius/inputman.richtexteditor';
import * as GcCommon from '@mescius/inputman';
GcCommon.InputMan.appearanceStyle = GcCommon.InputMan.AppearanceStyle.Modern;
// 氏名
const username = new GcCommon.InputMan.GcTextBox(document.getElementById('username'), {
watermarkDisplayNullText: '例)入力太郎',
watermarkNullText: 'ふりがなは自動的に出力します',
exitOnLeftRightKey: GcCommon.InputMan.ExitOnLeftRightKey.Both,
exitOnEnterKey: GcCommon.InputMan.ExitKey.Both,
width: 500,
});
username.onIMEReadingStringOutput((sender, eArgs) => {
furigana.text = eArgs.readingString;
validator.validate();
});
username.onInput((sender, eArgs) => {
if (sender.text.length == 0) sender.clearIMEReadingString();
});
// フリガナ
const furigana = new GcCommon.InputMan.GcTextBox(document.getElementById('furigana'), {
watermarkDisplayNullText: '全角カナで入力してください',
watermarkNullText: '氏名を入力してください',
format: 'N',
exitOnLeftRightKey: GcCommon.InputMan.ExitOnLeftRightKey.Both,
exitOnEnterKey: GcCommon.InputMan.ExitKey.Both,
width: 500,
});
furigana.onInput((sender, eArgs) => {
if (sender.text.length == 0) username.clearIMEReadingString();
});
// メールアドレス
const mail = new GcCommon.InputMan.GcMask(document.getElementById('mail'), {
exitOnLeftRightKey: GcCommon.InputMan.ExitOnLeftRightKey.Both,
exitOnEnterKey: GcCommon.InputMan.ExitKey.Both,
width: 500,
});
// 郵便番号
const postal = new GcCommon.InputMan.GcMask(document.getElementById('postal'), {
formatPattern: '〒\\D{3}-\\D{4}',
exitOnLastChar: true,
exitOnLeftRightKey: GcCommon.InputMan.ExitOnLeftRightKey.Both,
exitOnEnterKey: GcCommon.InputMan.ExitKey.Both,
width: 160,
});
// 都道府県
const prefecture = new GcCommon.InputMan.GcTextBox(document.getElementById('prefecture'), {
watermarkDisplayNullText: '都道府県名を選択してください',
exitOnLeftRightKey: GcCommon.InputMan.ExitOnLeftRightKey.Both,
exitOnEnterKey: GcCommon.InputMan.ExitKey.Both,
width: 310,
});
const dropDown = prefecture.createDropDown();
dropDown.getElement().appendChild(document.getElementById('prefDropdown'));
document.getElementById('prefDropdown').addEventListener('click', (e) => {
if (e.srcElement.tagName.toLowerCase() == 'span') {
prefecture.text = e.srcElement.innerText;
dropDown.close();
}
});
// 住所
const address1 = new GcCommon.InputMan.GcTextBox(document.getElementById('address1'), {
watermarkDisplayNullText: '市区町村名を入力してください',
exitOnLeftRightKey: GcCommon.InputMan.ExitOnLeftRightKey.Both,
exitOnEnterKey: GcCommon.InputMan.ExitKey.Both,
width: 500,
});
const address2 = new GcCommon.InputMan.GcTextBox(document.getElementById('address2'), {
watermarkDisplayNullText: '番地以降を入力してください',
watermarkNullText: '全角文字に自動変換します',
format: 'Z',
exitOnLeftRightKey: GcCommon.InputMan.ExitOnLeftRightKey.Both,
exitOnEnterKey: GcCommon.InputMan.ExitKey.Both,
width: 500,
});
// 電話番号
const phone = new GcCommon.InputMan.GcMask(document.getElementById('phone'), {
formatPattern: '\\D{2,3}-\\D{2,3}-\\D{4}',
exitOnLeftRightKey: GcCommon.InputMan.ExitOnLeftRightKey.Both,
exitOnLastChar: true,
exitOnEnterKey: GcCommon.InputMan.ExitKey.Both,
width: 500,
});
// 会社名
const company = new GcCommon.InputMan.GcTextBox(document.getElementById('company'), {
watermarkDisplayNullText: '例)メシウス株式会社',
exitOnLeftRightKey: GcCommon.InputMan.ExitOnLeftRightKey.Both,
exitOnEnterKey: GcCommon.InputMan.ExitKey.Both,
width: 500,
});
// お問い合わせ内容
const question = new InputMan.GcRichTextEditor(document.getElementById('question'), {
baseUrl: '$IMDEMOROOT$/lib/purejs/node_modules/@mescius/inputman.richtexteditor/JS',
plugins: [InputMan.GcRichTextEditorPluginItem.All],
menubar: [],
toolbar: ['forecolor', 'backcolor', 'bold', 'italic', 'underline', 'separateLine', 'bulList', 'numList', 'separateLine', 'Link', 'HTMLCode'],
toolbarMode: InputMan.GcRichTextEditorToolbarMode.Wrap,
watermarkText: 'ここに問合せの内容を入力してください...',
height: 200,
width: 500,
});
// 検証処理
const validator = new GcCommon.InputMan.GcValidator({
items: [
// 氏名
{
control: username,
ruleSet: [
{
rule: GcCommon.InputMan.ValidateType.Required,
},
],
},
// フリガナ
{
control: furigana,
ruleSet: [
{
rule: GcCommon.InputMan.ValidateType.Required,
},
],
},
// メールアドレス
{
control: mail,
ruleSet: [
{
rule: GcCommon.InputMan.ValidateType.Required,
},
{
rule: (control) => {
const regexp = /^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]{1,}\.[A-Za-z0-9]{1,}$/;
return regexp.test(control.value);
},
failMessage: '正しいメールアドレス形式で入力してください',
},
],
},
// 郵便番号
{
control: postal,
ruleSet: [
{
rule: GcCommon.InputMan.ValidateType.Required,
},
],
},
// 都道府県名
{
control: prefecture,
ruleSet: [
{
rule: GcCommon.InputMan.ValidateType.Required,
},
],
},
// 住所
{
control: address1,
ruleSet: [
{
rule: GcCommon.InputMan.ValidateType.Required,
},
],
},
{
control: address2,
ruleSet: [
{
rule: GcCommon.InputMan.ValidateType.Required,
},
],
},
// 電話番号
{
control: phone,
ruleSet: [
{
rule: GcCommon.InputMan.ValidateType.Required,
},
],
},
// 会社名
{
control: company,
ruleSet: [
{
rule: GcCommon.InputMan.ValidateType.Required,
},
],
},
// お問い合わせ内容
{
control: question,
ruleSet: [
{
rule: GcCommon.InputMan.ValidateType.Required,
},
{
rule: (control) => {
return control.getContentLength() < 100;
},
failMessage: '100文字を超える入力はできません',
},
],
validateWhen: GcCommon.InputMan.ValidateWhen.Typing,
},
],
defaultNotify: {
fail: {
icon: true,
controlState: true,
},
success: {
icon: true,
},
},
});
let fp = new GcCommon.InputMan.GcFormPersistence(document.getElementById('imfm'));
fp.saveMode = GcCommon.InputMan.SaveMode.SaveOnSubmit;
fp.persist();
validator.validate();
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>実用例 - お問い合わせフォーム</title>
<!-- SystemJS -->
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
window.onload = function () {
System.import('./src/app');
}
</script>
</head>
<body>
<form id="imfm" action="" target="_parent">
<table class="form">
<tbody>
<tr>
<th>氏名<span class="required">必須</span></th>
<td><input id="username"></td>
</tr>
<tr>
<th>フリガナ<span class="required">必須</span></th>
<td><input id="furigana"></td>
</tr>
<tr>
<th>メールアドレス<span class="required">必須</span></th>
<td><input id="mail"></td>
</tr>
<tr>
<th rowspan="3">住所<span class="required">必須</span></th>
<td><input id="postal" class="postal"><input id="prefecture" class="prefecture"></td>
</tr>
<tr>
<td><input id="address1"></td>
</tr>
<tr>
<td><input id="address2"></td>
</tr>
<tr>
<th>電話番号<span class="required">必須</span></th>
<td><input id="phone"></td>
</tr>
<tr>
<th>会社名<span class="required">必須</span></th>
<td><input id="company"></td>
</tr>
<tr>
<th>お問い合わせ内容<span class="required">必須</span></th>
<td><textarea id="question" class="question"></textarea></td>
</tr>
</tbody>
</table>
</form>
<br>
<input type="submit" form="imfm" value="データの送信">
<p>※実際にはデータはどこにも送信されません。</p>
<div id="prefDropdown">
<table>
<tbody>
<tr>
<th>北海道</th>
<td><span>北海道</span></td>
</tr>
<tr>
<th>東北</th>
<td><span>青森県</span><span>岩手県</span><span>宮城県</span><span>秋田県</span><span>山形県</span><span>福島県</span>
</td>
</tr>
<tr>
<th>関東</th>
<td><span>茨城県</span><span>栃木県</span><span>群馬県</span><span>埼玉県</span><span>千葉県</span><span>東京都</span><span>神奈川県</span>
</td>
</tr>
<tr>
<th>甲信越</th>
<td><span>山梨県</span><span>長野県</span><span>新潟県</span></td>
</tr>
<tr>
<th>北陸</th>
<td><span>富山県</span><span>石川県</span><span>福井県</span></td>
</tr>
<tr>
<th>東海</th>
<td><span>岐阜県</span><span>静岡県</span><span>愛知県</span><span>三重県</span></td>
</tr>
<tr>
<th>近畿</th>
<td><span>滋賀県</span><span>京都府</span><span>大阪府</span><span>兵庫県</span><span>奈良県</span><span>和歌山県</span>
</td>
</tr>
<tr>
<th>中国四国</th>
<td><span>鳥取県</span><span>島根県</span><span>岡山県</span><span>広島県</span><span>山口県</span><span>徳島県</span><span>香川県</span><span>愛媛県</span><span>高知県</span>
</td>
</tr>
<tr>
<th>九州</th>
<td><span>福岡県</span><span>佐賀県</span><span>長崎県</span><span>熊本県</span><span>大分県</span><span>宮崎県</span><span>鹿児島県</span>
</td>
</tr>
<tr>
<th>沖縄</th>
<td><span>沖縄県</span></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
body {
position: static !important;
}
.form {
border-collapse: collapse;
}
.form>tbody>tr>* {
padding: 0.25rem 0.5rem;
border: 1px solid #D2D2D2;
}
.form>tbody>tr>th {
text-align: left;
background: #F0F0F0;
font-weight: normal;
}
.form>tbody>tr>td {
padding-right: 30px;
}
.required {
background-color: orange;
color: white;
font-size: 12px;
margin-left: 0.5rem;
padding: 0 5px;
float: right;
}
.gcim_watermark_null[gcim-notify__control-state] .gcim__input {
color: gray;
}
.postal {
margin-right: 30px;
}
#prefDropdown table {
background-color: azure;
border: darkgray 1px solid;
border-radius: 5px;
}
#prefDropdown th {
padding: 0 0.5rem;
border-right: steelblue 2px solid;
font-weight: bold;
}
#prefDropdown span {
margin: 0 0.5rem;
color: blue;
cursor: pointer;
}
.prefecture {
vertical-align: bottom;
}
body {
position: static !important;
}
[gcim-control-appearance="modern"] .form {
border-collapse: collapse;
}
[gcim-control-appearance="modern"] .form>tbody>tr>* {
padding: 0.25rem 0.5rem;
border: 1px solid #D2D2D2;
}
[gcim-control-appearance="modern"] .form>tbody>tr>th {
text-align: left;
background: #F0F0F0;
font-weight: normal;
}
[gcim-control-appearance="modern"] .form>tbody>tr>td {
padding-right: 30px;
}
[gcim-control-appearance="modern"] .required {
background-color: orange;
color: white;
font-size: 12px;
margin-left: 0.5rem;
padding: 0 5px;
float: right;
}
[gcim-control-appearance="modern"] .gcim_watermark_null[gcim-notify__control-state] .gcim__input {
color: gray;
}
[gcim-control-appearance="modern"] .postal {
margin-right: 30px;
}
[gcim-control-appearance="modern"] #prefDropdown table {
background-color: azure;
border: darkgray 1px solid;
border-radius: 5px;
}
[gcim-control-appearance="modern"] #prefDropdown th {
padding: 0 0.5rem;
border-right: steelblue 2px solid;
font-weight: bold;
}
[gcim-control-appearance="modern"] #prefDropdown span {
margin: 0 0.5rem;
color: blue;
cursor: pointer;
}
[gcim-control-appearance="modern"] .prefecture {
vertical-align: bottom;
}
System.config({
transpiler: 'plugin-babel',
babelOptions: {
es2015: true
},
meta: {
'*.css': { loader: 'css' }
},
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
'@mescius/inputman': 'npm:@mescius/inputman/index.js',
'@mescius/inputman/CSS': 'npm:@mescius/inputman/CSS',
'@mescius/inputman.richtexteditor': 'npm:@mescius/inputman.richtexteditor/index.js',
'@mescius/inputman.richtexteditor/CSS': 'npm:@mescius/inputman.richtexteditor/CSS',
'css': 'npm:systemjs-plugin-css/css.js',
'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js',
'systemjs-babel-build': 'npm:systemjs-plugin-babel/systemjs-babel-browser.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
src: {
defaultExtension: 'js'
},
"node_modules": {
defaultExtension: 'js'
},
}
});