ここではInputManJSを利用してモバイルを想定した、お問い合わせフォーム画面を作成する方法を紹介します。
各コントロールで次の機能を追加しています。
お名前、お名前(ふりがな)、会社名(GcTextBox):入力補助のためのウォーターマークを設定しています。
お名前(ふりがな)(GcTextBox):お名前の入力欄を入力時にふりがなを自動取得しています。
電話番号(GcMask):ウォーターマークと数値のみのマスク処理の設定、入力完了後に次のコントロールへ自動フォーカス移動します。
メールアドレス(GcMask):ウォーターマークとメールアドレス用マスク処理の設定、Enterキーを入力で次のコントロールへ自動フォーカス移動します。
お問い合わせ内容(GcMultiLineTextBox):ヘルプボタンで入力可能文字数を表示します。 *モバイルの画面を超えてメッセージが表示される場合があります
必須項目の検証(GcValidator):送信ボタンを押下した時に、お名前、お名前(ふりがな)、会社名、メールアドレス、お問い合わせ内容の入力項目に対して、入力済みかを検証します。
文字列長の検証(GcValidator):お問い合わせ内容の入力項目に対して、1文字以上200文字以下かを検証します。
import './styles.css';
import { InputMan } from '@mescius/inputman';
import '@mescius/inputman/CSS/gc.inputman-js.css';
InputMan.appearanceStyle = InputMan.AppearanceStyle.Modern;
document.readyState === 'complete' ? init() : window.onload = init;
function init() {
const username = new InputMan.GcTextBox(document.getElementById('username'), {
watermarkDisplayNullText: '例)入力太郎',
});
const furigana = new InputMan.GcTextBox(document.getElementById('furigana'), {
watermarkDisplayNullText: '例)にゅうりょくたろう',
});
username.onIMEReadingStringOutput((sender, eArgs) => {
furigana.text = eArgs.readingString;
});
username.onInput((sender, eArgs) => {
if (sender.text.length === 0) {
furigana.clear();
}
});
username.onFocusOut(() => validator.validate(furigana));
const company = new InputMan.GcTextBox(document.getElementById('company'), {
watermarkDisplayNullText: '例)入力 株式会社',
});
const phone = new InputMan.GcMask(document.getElementById('phone'), {
watermarkDisplayNullText: '例)000-0000-0000',
formatPattern: '\\D{2,4}-\\D{2,4}-\\D{4}',
exitOnLastChar: true,
});
// メールアドレス
const mail = new InputMan.GcMask(document.getElementById('mail'), {
watermarkDisplayNullText: '例)example@gmail.com',
formatPattern: '[\\W_.+-]+@[\\W]+.[\\W.]+',
exitOnEnterKey: 'enter',
});
// お問い合わせ内容
const question = new InputMan.GcMultiLineTextBox(
document.getElementById('question'),
{
height: 100,
container: document.querySelector(".display"),
showHelpButton: true,
helpContent: '200文字以内で入力してしてください。',
scrollBarMode: 'automatic',
scrollBars: 'vertical',
}
);
let isPosted = false;
document.getElementById('btn').addEventListener('click', () => {
if (isPosted) return;
if (validator.validate()) {
document.getElementById('message').innerText =
'お問い合わせ内容は正しく送信されました。';
document.getElementById('message').classList.remove('falid');
document.getElementById('message').classList.add('posted');
username.clear();
company.clear();
phone.clear();
mail.clear();
question.clear();
validator.destroy();
username.watermarkDisplayNullText = '';
company.watermarkDisplayNullText = '';
phone.watermarkDisplayNullText = '';
mail.watermarkDisplayNullText = '';
question.watermarkDisplayNullText = '';
username.enabled = false;
furigana.enabled = false;
company.enabled = false;
phone.enabled = false;
mail.enabled = false;
question.enabled = false;
isPosted = true;
setTimeout(() => {
document.getElementById('message').innerText = '';
document.getElementById('message').classList.remove('posted');
}, 5000);
} else {
document.getElementById('message').innerText =
'入力に不備があります、再度お確かめください。';
document.getElementById('message').classList.add('falid');
}
});
const validator = new InputMan.GcValidator({
items: [
{
control: username,
ruleSet: [
{
rule: InputMan.ValidateType.Required,
},
],
},
{
control: furigana,
ruleSet: [
{
rule: InputMan.ValidateType.Required,
},
],
},
{
control: company,
ruleSet: [
{
rule: InputMan.ValidateType.Required,
},
],
},
{
control: mail,
ruleSet: [
{
rule: InputMan.ValidateType.Required,
},
],
},
{
control: question,
ruleSet: [
{
rule: function (control) {
return control.text.length > 0 && control.text.length <= 200;
},
},
],
},
],
defaultNotify: {
fail: {
icon: {
direction: InputMan.IconDirection.Inside,
},
controlState: true,
},
success: {
icon: {
direction: InputMan.IconDirection.Inside,
},
controlState: true,
},
},
});
}
<!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>
<div class="mobile">
<div class="display">
<div class="header">
<h2 class="title">お問い合わせフォーム</h2>
</div>
<div id="message"></div>
<div class="scroll-area">
<span class="tag required">必須</span><span class="label">お名前</span>
<div class="margintop"></div>
<input id="username" />
<div class="margintop"></div>
<span class="tag required">必須</span><span class="label">お名前(ふりがな)</span>
<div class="margintop"></div>
<input id="furigana" />
<div class="margintop"></div>
<span class="tag required">必須</span><span class="label">会社名</span>
<div class="margintop"></div>
<input id="company" />
<div class="margintop"></div>
<span class="tag voluntary">任意</span><span class="label">電話番号</span>
<div class="margintop"></div>
<input id="phone" />
<div class="margintop"></div>
<span class="tag required">必須</span><span class="label">メールアドレス</span>
<div class="margintop"></div>
<input id="mail" />
<div class="margintop"></div>
<span class="tag required">必須</span><span class="label">お問い合わせ内容</span>
<div class="margintop"></div>
<textarea id="question" class="question"></textarea>
<div class="margintop"></div>
<a id="btn" class="btn">送信する</a>
</div>
</div>
<div class="btn2"></div>
</div>
</body>
</html>
body {
font-family: sans-serif;
font-size: 14px;
margin: 50px 15px;
}
.mobile {
height: 600px;
width: 350px;
margin: 0 auto 0;
border: 1px solid #cfd8df;
background-color: black;
border-radius: 50px;
}
.display {
margin-top: 50px;
height: 480px;
width: 91%;
margin-left: 16px;
border: 1px solid #cfd8df;
background-color: #fff;
justify-content: center;
border-radius: 5px;
}
.tag {
color: white;
font-size: 14px;
margin-left: 0.1rem;
padding: 0 5px;
border-radius: 6px;
}
.required {
background-color: orange;
}
.voluntary {
background-color: rgb(88, 111, 117);
}
.scroll-area {
margin-top: 10%;
height: 350px;
margin-left: 35px;
overflow-y: scroll;
}
.label {
font-size: 15px;
font-weight: bold;
padding: 0 5px;
}
.scroll-area::-webkit-scrollbar {
display: none;
}
.gcim{
width: 120%
}
.gcim_watermark_null {
color: lightgrey;
}
.margintop{
margin-top: 20px;
}
a.btn {
display: block;
text-align: center;
text-decoration: none;
width: 140px;
padding: 1rem 2rem;
font-weight: bold;
border: 2px solid #27acd9;
background: #27acd9;
color: #fff;
transition: 0.5s;
margin-left: 15px
}
a.btn:hover {
color: #27acd9;
background: #fff;
}
.btn2 {
background-color: whitesmoke;
margin-top: 10px;
position: relative;
left: 43%;
width: 45px;
height: 45px;
border-radius: 50%;
}
.header{
height: 50px;
width: 100%;
background-color: lightgrey;
display: flex;
justify-content: center;
align-items: center;
}
.posted{
background-color: rgba(201, 250, 168, 0.986);
height: 30px;
text-align: center;
font-weight:bold
}
.falid{
background-color: rgba(245, 233, 202, 0.986);
height: 30px;
text-align: center;
color: red;
font-weight:bold
}
.question .gcim__help-button_tip {
background-color: #fff;
color: rgb(194, 189, 189);
font-weight: bold;
font-size: 14px;
}
.gcim__side-button{
margin-bottom: 142%;
}
body {
font-family: sans-serif;
font-size: 14px;
margin: 50px 15px;
}
[gcim-control-appearance="modern"] .mobile {
height: 600px;
width: 350px;
margin: 0 auto 0;
border: 1px solid #cfd8df;
background-color: black;
border-radius: 50px;
}
[gcim-control-appearance="modern"] .display {
margin-top: 50px;
height: 480px;
width: 91%;
margin-left: 16px;
border: 1px solid #cfd8df;
background-color: #fff;
justify-content: center;
border-radius: 5px;
}
[gcim-control-appearance="modern"] .tag {
color: white;
font-size: 14px;
margin-left: 0.1rem;
padding: 0 5px;
border-radius: 6px;
}
[gcim-control-appearance="modern"] .required {
background-color: orange;
}
[gcim-control-appearance="modern"] .voluntary {
background-color: rgb(88, 111, 117);
}
[gcim-control-appearance="modern"] .scroll-area {
margin-top: 10%;
height: 350px;
margin-left: 35px;
overflow-y: scroll;
}
[gcim-control-appearance="modern"] .label {
font-size: 15px;
font-weight: bold;
padding: 0 5px;
}
[gcim-control-appearance="modern"] .scroll-area::-webkit-scrollbar {
display: none;
}
[gcim-control-appearance="modern"] .gcim {
width: 120%;
}
[gcim-control-appearance="modern"] .gcim_watermark_null {
color: lightgrey;
}
[gcim-control-appearance="modern"] .margintop {
margin-top: 20px;
}
[gcim-control-appearance="modern"] a.btn {
display: block;
text-align: center;
text-decoration: none;
width: 140px;
padding: 1rem 2rem;
font-weight: bold;
border: 2px solid #27acd9;
background: #27acd9;
color: #fff;
transition: 0.5s;
margin-left: 15px;
}
[gcim-control-appearance="modern"] a.btn:hover {
color: #27acd9;
background: #fff;
}
[gcim-control-appearance="modern"] .btn2 {
background-color: whitesmoke;
margin-top: 10px;
position: relative;
left: 43%;
width: 45px;
height: 45px;
border-radius: 50%;
}
[gcim-control-appearance="modern"] .header {
height: 50px;
width: 100%;
background-color: lightgrey;
display: flex;
justify-content: center;
align-items: center;
}
[gcim-control-appearance="modern"] .posted {
background-color: rgba(201, 250, 168, 0.986);
height: 30px;
text-align: center;
font-weight: bold;
}
[gcim-control-appearance="modern"] .falid {
background-color: rgba(245, 233, 202, 0.986);
height: 30px;
text-align: center;
color: red;
font-weight: bold;
}
[gcim-control-appearance="modern"] .question .gcim__help-button_tip {
background-color: #fff;
color: rgb(194, 189, 189);
font-weight: bold;
font-size: 14px;
}
[gcim-control-appearance="modern"] .gcim__side-button {
margin-bottom: 142%;
}
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',
'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'
},
}
});