メールフォームプロを一つのページに複数設置したい
- イベント申し込みや資料ダウンロードなど、一つのページにメールフォームを複数設置したいケースがあります
- メールフォームプロは、原則一つのページに一つしか設置することができません。ですが、オプションの「MultiConfig」機能を使うことで、擬似的にフォームを分けて設置することができます
動作イメージ
- ボタン押下によって入力フォームのサブウインドウが表示されます
- 「MultiConfig」機能によって、3つのフォームはそれぞれ別のconfigファイルを参照し、自動返信メールの内容や、サンクスページのURLを切り替えることができます
「MultiConfig」機能について
- 一つのメールフォームで、複数のconfigファイルを切り替えて参照させる機能です
- 通常は、以下のような形でメールフォームプロを呼び出します。このとき参照されるconfigファイルは「config.cgi」となります
<form id="mailformpro" action="/mailformpro/mailformpro.cgi" method="POST">
〜
<script type="text/javascript" id="mfpjs" src="/mailformpro/mailformpro.cgi" charset="UTF-8"></script>
</form>
- 「MultiConfig」機能でconfigファイルを切り替える場合、cgiのパスに「?type=xxx」とつけます。このとき参照されるconfigファイルは「config.xxx.cgi」となります。異なるconfigファイルを参照させることでフォームの挙動を変え、あたかも複数のフォームが設置されているかのような動作が実現できます
- 今回は、このパスの書き換えをJavascriptによって行い、ボタンが押される度にパスを書き換えてconfigファイルの参照先を変えていきます
<form id="mailformpro" action="/mailformpro/mailformpro.cgi?type=xxx" method="POST">
〜
<script type="text/javascript" id="mfpjs" src="/mailformpro/mailformpro.cgi?type=xxx" charset="UTF-8"></script>
</form>
設置手順
configファイルの作成
- まずは通常の設置時と同じようにconfigファイルを作成します。
- 設置者用メールのアドレスを設定する箇所に、以下のような配列の初期化文を入れてください
@mailto = ();
push @mailto,'xxx@test.com';
push @mailto,'yyy@test.com';
push @mailto,'zzz@test.com';
- これは、設置者用メールが二重で送られてこないようにするための記述です
- configの切り替え時、各設定は切り替えたconfigの内容で上書きされるのですが、設置者用メールアドレスは配列に追加するような書き方になるため、初期化文がないと切り替えたconfigに書いてあるアドレスがそのまま追加されてしまいます
push @Modules,'MultiConfig'; ## 複数の設定ファイルを分岐させる
- あとは、オプション機能の一覧にある「MultiConfig」を有効にするため、行頭の「#」を外してください
configファイルの複製
- 作成したconfigファイルを、必要なフォームの数だけコピーしてください
- コピーしたconfigファイルは、ファイル名を「config.xxx.cgi」という形式にします
- コピーしたファイルは元のconfigファイルと同じフォルダに置いておきます
- 今回のケースでは「config.cgi」「config.aaa.cgi」「config.bbb.cgi」の3つのconfigファイルを切り替えていきます
- 複製したconfigファイルについて以下の内容を変更すれば、configファイルの準備は完了です
- 設置者メールの送信先
- サンクスページのURL
- 自動返信メールの内容 など
htmlの実装
<button class="open_inline_form" data-type="">メールフォーム①</button>
<button class="open_inline_form" data-type="aaa">メールフォーム②</button>
<button class="open_inline_form" data-type="bbb">メールフォーム③</button>
<div id="bg_inline_form" class="bg_inline_form">
<div id="inline_form" class="inline_form">
<button id="close_inline_form" class="close_inline_form"></button>
<div class="inline_form_content">
<form id="mailformpro" action="/mailformpro/mailformpro.cgi" method="POST">
<dl class="mailform">
<dt class="mfp"><span class="must">必須</span>お名前</dt>
<dd class="mfp">
<input type="text" name="お名前" size="40" required="required" placeholder="山田太郎">
</dd>
<dt class="mfp"><span class="must">必須</span>メールアドレス</dt>
<dd class="mfp">
<input type="email" data-type="email" data-parent="mailfield" name="email" size="40" required="required" placeholder="xxx@test.com">
</dd>
<dt class="mfp"><span class="must">必須</span>電話番号</dt>
<dd class="mfp">
<input type="tel" data-type="tel" name="電話番号" size="20" required="required" placeholder="0123-45-6789">
</dd>
</dl>
<div class="mfp_buttons">
<button type="submit">送信する</button>
</div>
<script type="text/javascript" id="mfpjs" src="/mailformpro/mailformpro.cgi" charset="UTF-8"></script>
</form>
</div>
</div>
</div>
- htmlのコードです
- ポイントは、各フォームを呼び出す3つのボタンに設定された「data-type」です
- この内容が、先に作成したconfigファイル名と対応しています。configファイル「config.aaa.cgi」のフォームを呼び出す場合、「data-type」は「aaa」となります
- メールフォーム①はデフォルトのconfigファイルを参照するため、「data-type」は空の「""」としておきます
- 呼び出されるフォームは「inline_form_content」クラスの要素で囲んでいます。フォームの中身は特に手を入れる必要はありません
CSSの実装
.open_inline_form {
display: block;
width: 18em;
padding: 1em;
margin: 30px auto 0px;
border: none;
border-radius: 15px;
background-color: #3388dd;
outline: none;
color: #fff;
font-size: 18px;
font-weight: bold;
text-align: center;
cursor: pointer;
}
.open_inline_form:hover {
opacity: 0.8;
}
.bg_inline_form {
display: block;
position: fixed;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background-color: rgba(0, 0, 0, 0.5);
visibility: hidden;
opacity: 0;
pointer-events: none;
transition: 0.5s;
}
.bg_inline_form.js_active {
visibility: visible;
opacity: 1;
pointer-events: auto;
}
.inline_form {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
padding: 30px;
max-height: 90%;
background-color: #fff;
overflow-y: auto;
}
@media screen and (max-width: 767px) {
.inline_form {
width: calc(100% - 20px);
}
}
@media print, (min-width: 768px) {
.inline_form {
width: 90%;
max-width: 900px;
}
}
.close_inline_form {
position: absolute;
top: 10px;
right: 10px;
transform: rotate(45deg);
border: none;
background: none;
outline: none;
width: 30px;
height: 30px;
}
.close_inline_form::before,
.close_inline_form::after {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
background-color: #3388dd;
content: "";
}
.close_inline_form::before {
width: 60%;
height: 3px;
}
.close_inline_form::after {
width: 3px;
height: 60%;
}
.close_inline_form:hover {
cursor: pointer;
}
.inline_form_content {
display: table;
margin: 0px auto;
}
- CSSのコードです
- フォームと背景のオーバーレイを含む全体要素「bg_inline_form」は、「visibility: hidden;」と「opacity: 0;」で非表示にされています
- ボタンが押下されたときに「.js_active」が付与され、「visibility: visible;」と「opacity: 1;」となることで表示されます
Javascriptの実装
window.addEventListener('load', function() {
const bgForm = document.getElementById('bg_inline_form');
if(bgForm) {
const form = document.getElementById('mailformpro');
const formPath = form.getAttribute('action');
const openFormButtons = document.getElementsByClassName('open_inline_form');
for(let i = 0; i < openFormButtons.length; i++) {
openFormButtons[i].addEventListener('click', function(event) {
const dataType = this.getAttribute('data-type');
let formPathWithParam = formPath;
if(dataType) {
formPathWithParam = formPathWithParam + '?type=' + dataType;
}
form.setAttribute('action', formPathWithParam);
document.getElementById('mfpjs').setAttribute('src', formPathWithParam);
bgForm.classList.add('js_active');
}, false);
}
// オーバーレイエリアと×アイコンがクリックされたら、オーバーレイとウインドウをクローズ
function closeForm(event) {
bgForm.classList.remove('js_active');
}
bgForm.addEventListener('click', closeForm, false);
document.getElementById('close_inline_form').addEventListener('click', closeForm, false);
// ウインドウ内の要素をクリックしたときにクローズされないようバブリングを停止
document.getElementById('inline_form').addEventListener('click', function(event) {
event.stopPropagation();
}, false);
}
}, false);
- Javascriptのコードです
- ボタンをクリックしたとき、フォームの背景と×ボタンをクリックしたときのイベント処理を設定しています
const openFormButtons = document.getElementsByClassName('open_inline_form');
for(let i = 0; i < openFormButtons.length; i++) {
openFormButtons[i].addEventListener('click', function(event) {
const dataType = this.getAttribute('data-type');
let formPathWithParam = formPath;
if(dataType) {
formPathWithParam = formPathWithParam + '?type=' + dataType;
}
form.setAttribute('action', formPathWithParam);
document.getElementById('mfpjs').setAttribute('src', formPathWithParam);
bgForm.classList.add('js_active');
}, false);
}
- 配列に格納したボタン要素をループで回して、クリック時のイベント処理を設定しています
- ボタンの「data-type」属性の内容を取得し、フォームのパスの末尾に「?type=xxx」の形式で結合します
- 「data-type」が空(=1つ目のボタン)の場合は、結合は行わず、デフォルトのパスのままにします
- 結合したパス名でformの「action」属性とscriptの「src」属性を上書きします
- 最後に、フォームと背景のオーバーレイを含む全体要素「bg_inline_form」に対して「js_active」クラスを設定します
- 以上の処理で、ボタンを押下する度にフォームが表示され、メールフォームプロのパスが書き換わるようになります
// オーバーレイエリアと×アイコンがクリックされたら、オーバーレイとウインドウをクローズ
function closeForm(event) {
bgForm.classList.remove('js_active');
}
bgForm.addEventListener('click', closeForm, false);
document.getElementById('close_inline_form').addEventListener('click', closeForm, false);
// ウインドウ内の要素をクリックしたときにクローズされないようバブリングを停止
document.getElementById('inline_form').addEventListener('click', function(event) {
event.stopPropagation();
}, false);
- 背景のオーバレイと、ウインドウの×ボタンをクリックしたときのイベント処理です
- 「bg_inline_form」にボタンクリックで付与された「js_active」を削除します。これでフォームと背景が非表示になります
- これだけですと、ウインドウ内の要素をクリックしたときにも、背景がイベントを受理(バブリング)してしまい、ウインドウがクローズされてしまいます
- これを防止するため、ウインドウである「inline_form」にて「event.stopPropagation();」を行い、イベントが背景に伝達されないようにします
フォームの種類を区別してログに残したい
- ここまでの方法で擬似的に複数のフォームを設置することができます
- しかし、フォーム自体は一つのため、例えばメールの送信履歴はすべて同じログファイルに記録されてしまいます
- 後々、どのフォームにどれくらい問い合わせがあったかチェックするときに、すべて混同していては区別できません
- そこで、「hidden」タイプの入力項目を用意し、そこにフォームの種類情報を設定することで、ログファイル上で区別できるようになります
html
<form id="mailformpro" action="/mailformpro/mailformpro.cgi" method="POST">
<input type="hidden" name="お問い合わせ種別" id="form_type" value="">
<dl class="mailform">
<dt class="mfp"><span class="must">必須</span>お名前</dt>
<dd class="mfp">
<input type="text" name="お名前" size="40" required="required" placeholder="山田太郎">
</dd>
<dt class="mfp"><span class="must">必須</span>メールアドレス</dt>
<dd class="mfp">
<input type="email" data-type="email" data-parent="mailfield" name="email" size="40" required="required" placeholder="xxx@test.com">
</dd>
<dt class="mfp"><span class="must">必須</span>電話番号</dt>
<dd class="mfp">
<input type="tel" data-type="tel" name="電話番号" size="20" required="required" placeholder="0123-45-6789">
</dd>
</dl>
<div class="mfp_buttons">
<button type="submit">送信する</button>
</div>
<script type="text/javascript" id="mfpjs" src="/mailformpro/mailformpro.cgi" charset="UTF-8"></script>
</form>
- 変更点は一箇所だけ。「お問い合わせ種別」という名前の「hidden」形式のinputタグが追加されています
- この「value」属性をボタンクリックの度に書き換えることで、フォーム送信時にフォームの種別情報も一緒に送信されるようになります
Javascript
window.addEventListener('load', function() {
const bgForm = document.getElementById('bg_inline_form');
if(bgForm) {
const form_type = [
['', 'メールフォーム①'],
['aaa', 'メールフォーム②'],
['bbb', 'メールフォーム③']
];
const form = document.getElementById('mailformpro');
const formPath = form.getAttribute('action');
const openFormButtons = document.getElementsByClassName('open_inline_form');
for(let i = 0; i < openFormButtons.length; i++) {
openFormButtons[i].addEventListener('click', function(event) {
const dataType = this.getAttribute('data-type');
let formPathWithParam = formPath;
if(dataType) {
formPathWithParam = formPathWithParam + '?type=' + dataType;
}
form.setAttribute('action', formPathWithParam);
document.getElementById('mfpjs').setAttribute('src', formPathWithParam);
for(let j = 0; j < form_type.length; j++) {
if(dataType === form_type[j][0]) {
document.getElementById('form_type').setAttribute('value', form_type[j][1]);
}
}
bgForm.classList.add('js_active');
}, false);
}
// オーバーレイエリアと×アイコンがクリックされたら、オーバーレイとウインドウをクローズ
function closeForm(event) {
bgForm.classList.remove('js_active');
}
bgForm.addEventListener('click', closeForm, false);
document.getElementById('close_inline_form').addEventListener('click', closeForm, false);
// ウインドウ内の要素をクリックしたときにクローズされないようバブリングを停止
document.getElementById('inline_form').addEventListener('click', function(event) {
event.stopPropagation();
}, false);
}
}, false);
- Javascript側の変更点は2つです
const form_type = [
['', 'お問い合わせフォーム'],
['aaa', '資料ダウンロード申し込みフォーム''],
['bbb', 'セミナー参加申し込みフォーム']
];
- フォームの種別名を定義する二次元配列を用意します
- 一次元目には「data-type」属性の内容を、二次元目にはそれに紐づくフォームの種別名を格納します
for(let j = 0; j < form_type.length; j++) {
if(dataType === form_type[j][0]) {
document.getElementById('form_type').setAttribute('value', form_type[j][1]);
}
}
- ボタンクリック時のイベント処理にて、用意した配列の内容を参照します
- クリックしたボタンの「data-type」属性の内容と一致するものを探してフォームの種別名を取得。フォームに追加した「hidden」形式のinputタグ「form_type」のvalue属性に設定します
- このように「data-type」属性を使えば、フォームごとの細かい挙動を制御できます
- 呼び出したフォームによって入力項目を変えるといった制御も可能です
ご質問など受け付けています
記事の中でわかりにくかったところ、もっと知りたかったこと、間違っていることなど、何でもお気軽にご連絡ください。
ご連絡は下記フォームを利用いただくか、ツイッターアカウント@flat8migi宛てでもOKです。