二重送信制御

/*
* COPYRIGHT (C) 2010 NEC CORPORATION
*
* ALL RIGHTS RESERVED BY NEC CORPORATION, THIS PROGRAM
* MUST BE USED SOLELY FOR THE PURPOSE FOR WHICH IT WAS
* FURNISHED BY NEC CORPORATION, NO PART OF THIS PROGRAM
* MAY BE REPRODUCED OR DISCLOSED TO OTHERS, IN ANY FORM
* WITHOUT THE PRIOR WRITTEN PERMISSION OF NEC CORPORATION.
*
* NEC CONFIDENTIAL AND PROPRIETARY
*/

/**
* @fileOverview
* 二重送信禁止 JavaScript 部品です.
*/

var sde = sde || {};

/**
* @namespace
* <p>二重送信禁止 JavaScript 部品です.
* 送信ボタンのダブルクリックなどによる二重送信を禁止します。</p>
*
* <p>sde.doubleSubmission.start メソッドを呼び出すと制御を開始します。
* ただし、HTML 中の要素が作成された後に呼び出す必要があります。
* このため、通常は以下のように jQuery.ready または jQuery.load
* で登録します。</p>
*
* <pre>
* jQuery(document).ready(sde.doubleSubmission.start);
* または
* jQuery(window).load(sde.doubleSubmission.start);
* </pre>
*
* <p>load イベント処理中に送信を行うような場合は、
* それより前に sde.doubleSubmission.start メソッドを
* 実行しておく必要があります。</p>
*
* <p>JavaScript で動的に form 要素を追加した場合は、
* sde.doubleSubmission.start メソッドを再度呼び出す必要があります。
* また、IE でアップロード用(enctype属性が"multipart/form-data")の
* フォーム配下に submit ボタンを動的に追加した場合も
* 同様に再度呼び出す必要があります。</p>
*
* <p>form 要素の class 属性に
* "sde_doubleSubmission_allowed" が含まれていれば
* 二重送信を許可します。</p>
*
* <p>また、sde.doubleSubmission.setAllowed(true) と設定した場合も
* 二重送信を許可します。</p>
*/
sde.doubleSubmission = {};

/**
* 二重送信を許可するなら true、禁止するなら false
* (デフォルトは false).
*
* @private
*/
sde.doubleSubmission.allowed = false;

/**
* 次回の送信を許可するなら true、禁止するなら false
* (デフォルトは false).
*
* @private
*/
sde.doubleSubmission.nextSubmissionAllowed = false;

/**
* 送信中なら true、そうでなければ false
*
* @private
*/
sde.doubleSubmission.blocked = false;

/**
* ブロック処理関数(未送信から送信中に変更した場合に呼び出す関数)
*
* @private
*/
sde.doubleSubmission.blockFunction = null;

/**
* ブロック解除処理関数(送信中から未送信に変更した場合に呼び出す関数)
*
* @private
*/
sde.doubleSubmission.unblockFunction = null;

/**
* 二重送信エラー処理関数
* (送信ボタンのダブルクリック等、送信中に送信しようした場合に呼び出す関数)
*
* @private
*/
sde.doubleSubmission.doubleSubmissionErrorFunction = null;

/**
* アップロードエラー処理関数
* (アップロードするファイル名が相対パスやスペース等の間違ったファイル名で
* アップロードに失敗した場合に呼び出す関数)
*
* @private
*/
sde.doubleSubmission.uploadErrorFunction = null;

/**
* onsubmit イベントの fireEvent 実行中なら true、そうでなければ false
*
* @private
*/
sde.doubleSubmission.onsubmitEventFiring = false;

/**
* 二重送信を許可するなら true、禁止するなら false
* (デフォルトは false) を返します.
*
* @return 二重送信を許可するなら true、
* 禁止するなら false
*/
sde.doubleSubmission.isAllowed = function () {
return sde.doubleSubmission.allowed;
};

/**
* 二重送信を許可するなら true、禁止するなら false
* (デフォルトは false) を設定します.
*
* @param value 二重送信を許可するなら true、
* 禁止するなら false
*/
sde.doubleSubmission.setAllowed = function (value) {
sde.doubleSubmission.allowed = value;
};

/**
* 次回の送信を許可するなら true、禁止するなら false
* (デフォルトは false) を返します.
*
* @return 次回の送信を許可するなら true、
* 禁止するなら false
*/
sde.doubleSubmission.isNextSubmissionAllowed = function () {
return sde.doubleSubmission.nextSubmissionAllowed;
};

/**
* <p>次回の送信を許可するなら true、禁止するなら false
* (デフォルトは false) を設定します.</p>
*
* <p>true に設定すると、次回の送信1回だけに限って、
* 二重送信であっても送信を許可し、その後この値は false に戻ります。
* また、その際に送信中かどうかの値(isBlockedが返す値)
* は変更しません。</p>
*
* @param value 次回の送信を許可するなら true、
* 禁止するなら false
*/
sde.doubleSubmission.setNextSubmissionAllowed = function (value) {
sde.doubleSubmission.nextSubmissionAllowed = value;
};

/**
* 送信中なら true、そうでなければ false
* を返します.
*
* @return 送信中なら true、そうでなければ false
*/
sde.doubleSubmission.isBlocked = function () {
return sde.doubleSubmission.blocked;
};

/**
* 送信中なら true、そうでなければ false
* を設定します.
*
* @param value 送信中なら true、そうでなければ false
*/
sde.doubleSubmission.setBlocked = function (value) {
if (sde.doubleSubmission.blocked === value) {
// 値の変更がない場合は何もしない
return;
}

sde.doubleSubmission.blocked = value;

if (sde.doubleSubmission.blocked) {
if (sde.doubleSubmission.blockFunction) {
sde.doubleSubmission.blockFunction();
}
} else {
if (sde.doubleSubmission.unblockFunction) {
sde.doubleSubmission.unblockFunction();
}
}
};

/**
* ブロック処理関数(未送信から送信中に変更した場合に呼び出す関数)
* を返します.
*
* @return ブロック処理関数。null なら呼び出さない。初期値は null
*/
sde.doubleSubmission.getBlockFunction = function () {
return sde.doubleSubmission.blockFunction;
};

/**
* ブロック処理関数(未送信から送信中に変更した場合に呼び出す関数)
* を設定します.
*
* @param value ブロック処理関数。null なら呼び出さない。初期値は null
*/
sde.doubleSubmission.setBlockFunction = function (value) {
sde.doubleSubmission.blockFunction = value;
};

/**
* ブロック解除処理関数(送信中から未送信に変更した場合に呼び出す関数)
* を返します.
*
* @return ブロック解除処理関数。null なら呼び出さない。初期値は null
*/
sde.doubleSubmission.getUnblockFunction = function () {
return sde.doubleSubmission.unblockFunction;
};

/**
* ブロック解除処理関数(送信中から未送信に変更した場合に呼び出す関数)
* を設定します.
*
* @param value ブロック解除処理関数。null なら呼び出さない。初期値は null
*/
sde.doubleSubmission.setUnblockFunction = function (value) {
sde.doubleSubmission.unblockFunction = value;
};

/**
* 二重送信エラー処理関数
* (送信ボタンのダブルクリック等、送信中に送信しようした場合に呼び出す関数)
* を返します.
*
* @return 二重送信エラー処理関数。null なら呼び出さない。初期値は null
*/
sde.doubleSubmission.getDoubleSubmissionErrorFunction = function () {
return sde.doubleSubmission.doubleSubmissionErrorFunction;
};

/**
* 二重送信エラー処理関数
* (送信ボタンのダブルクリック等、送信中に送信しようした場合に呼び出す関数)
* を設定します.
*
* @param value 二重送信エラー処理関数。null なら呼び出さない。初期値は null
*/
sde.doubleSubmission.setDoubleSubmissionErrorFunction = function (value) {
sde.doubleSubmission.doubleSubmissionErrorFunction = value;
};

/**
* アップロードエラー処理関数
* (アップロードするファイル名が相対パスやスペース等の間違ったファイル名で
* アップロードに失敗した場合に呼び出す関数)
* を返します.
*
* @return アップロードエラー処理関数。null なら呼び出さない。初期値は null
*/
sde.doubleSubmission.getUploadErrorFunction = function () {
return sde.doubleSubmission.uploadErrorFunction;
};

/**
* アップロードエラー処理関数
* (アップロードするファイル名が相対パスやスペース等の間違ったファイル名で
* アップロードに失敗した場合に呼び出す関数)
* を設定します.
*
* @param value アップロードエラー処理関数。
* null なら呼び出さない。初期値は null
*/
sde.doubleSubmission.setUploadErrorFunction = function (value) {
sde.doubleSubmission.uploadErrorFunction = value;
};

/**
* 二重送信禁止の制御を開始します.
* HTML 中の要素が作成された後に呼び出す必要があります。
*/
sde.doubleSubmission.start = function () {

for (var i = 0; i < document.forms.length; i++) {
var form = document.forms[i];

// フォームをカスタマイズ
sde.doubleSubmission.customizeForm(form);

if (sde.doubleSubmission.needsUploadErrorHandling(form)) {
// IEでアップロードを行うフォームの場合

// フォーム配下の全 submit ボタンをカスタマイズ
for (var j = 0; j < form.elements.length; j++) {
var control = form.elements[j];

if (control.tagName.toLowerCase() === 'input' &&
control.type === 'submit') {
// submit ボタンの場合
// submit ボタンをカスタマイズ
sde.doubleSubmission.customizeSubmitButton(control);
}
}
}
}

};

/**
* <p>指定のフォームをカスタマイズします.</p>
*
* @private
* @param form フォーム
*/
sde.doubleSubmission.customizeForm = function (form) {
if (form.sde_doubleSubmission_customized) {
// すでにカスタマイズ済みなら何もしない
return;
}
form.sde_doubleSubmission_customized = true;

// onsubmit のカスタマイズ
if (form.onsubmit) {
form.sde_doubleSubmission_onsubmit_original = form.onsubmit;
}
/** @ignore */
form.onsubmit = function () {
return sde.doubleSubmission.handleOnsubmit(this);
};

// submit メソッドのカスタマイズ
form.sde_doubleSubmission_submit_original = form.submit;
/** @ignore */
form.submit = function () {
sde.doubleSubmission.handleSubmit(this);
};

if (jQuery.browser.msie) {
// IEの場合
// fireEvent メソッドのカスタマイズ
form.sde_doubleSubmission_fireEvent_original = form.fireEvent;
/** @ignore */
form.fireEvent = function (sEvent, oEvent) {
return sde.doubleSubmission.handleFireEvent(
this, sEvent, oEvent);
};
}
};

/**
* <p>フォームの onsubmit のタイミングでの処理を行います。</p>
*
* @private
* @param form フォーム
* @return 送信を許可するなら true、禁止するなら false
*/
sde.doubleSubmission.handleOnsubmit = function (form) {
if (form.sde_doubleSubmission_onsubmit_original) {
try {
var ret = form.sde_doubleSubmission_onsubmit_original();
if (ret === false) {
// 本来の onsubmit で false を返した場合は送信しない
return false;
}
} catch (e) {
// onsubmit で例外発生しても以下の処理を行う
}
}

if (sde.doubleSubmission.onsubmitEventFiring) {
// onsubmit イベントの fireEvent 実行中なら送信中フラグは変更しない

// 送信を許可
return true;
}

if (sde.doubleSubmission.isAllowedForm(form)) {
// 二重送信を許可している場合

// 送信を許可
return true;

} else {
// 二重送信を禁止している場合

if (sde.doubleSubmission.isBlocked()) {
// 送信中の場合

// 二重送信エラー処理
sde.doubleSubmission.handleDoubleSubmissionError();

// 送信を禁止
return false;

} else {
// 未送信の場合

// 送信中に変更
sde.doubleSubmission.setBlocked(true);

// 送信を許可
return true;

}
}
};

/**
* <p>フォームの submit メソッドのタイミングでの処理を行います。</p>
*
* @private
* @param form フォーム
*/
sde.doubleSubmission.handleSubmit = function (form) {

if (sde.doubleSubmission.isAllowedForm(form)) {
// 二重送信を許可している場合

try {
// 本来の submit メソッドを呼び出す。
form.sde_doubleSubmission_submit_original();
} catch (e1) {
if (sde.doubleSubmission.needsUploadErrorHandling(form)) {
// アップロードエラー処理
sde.doubleSubmission.handleUploadError();
} else {
throw e1;
}
}

} else {
// 二重送信を禁止している場合

if (sde.doubleSubmission.isBlocked()) {
// 送信中の場合

// 二重送信エラー処理
sde.doubleSubmission.handleDoubleSubmissionError();

} else {
// 未送信の場合

// 送信中に変更
sde.doubleSubmission.setBlocked(true);

try {
// 本来の submit メソッドを呼び出す。
form.sde_doubleSubmission_submit_original();
} catch (e2) {
// 未送信に戻す
sde.doubleSubmission.setBlocked(false);

if (sde.doubleSubmission.needsUploadErrorHandling(form)) {
// アップロードエラー処理
sde.doubleSubmission.handleUploadError();
} else {
throw e2;
}
}

}
}
};

/**
* アップロードエラー時の処理が必要なフォームかどうかを返します.
*
* @private
* @param form フォーム
* @return アップロードエラー時の処理なら true、そうでなければ false
*/
sde.doubleSubmission.needsUploadErrorHandling = function (form) {
return jQuery.browser.msie && form.enctype === "multipart/form-data";
};

/**
* 二重送信を許可しているかどうかを返します.
*
* @private
* @param form フォーム
* @return 二重送信を許可しているなら true、そうでなければ false
*/
sde.doubleSubmission.isAllowedForm = function (form) {
if (sde.doubleSubmission.nextSubmissionAllowed) {
sde.doubleSubmission.nextSubmissionAllowed = false;
return true;
}
return sde.doubleSubmission.allowed ||
jQuery(form).hasClass("sde_doubleSubmission_allowed");
};

/**
* <p>フォームの fireEvent メソッドのタイミングでの処理を行います。</p>
*
* <p>IE で fireEvent メソッドを使用して
* onsubmit イベントが発生させられた場合、
* 送信は行われず、イベントだけが発生します。</p>
*
* <p>このため、onsubmit イベントの fireEvent メソッド実行中は、
* 送信中フラグを変更しないようにします。</p>
*
* <p>そうしないと、fireEvent() メソッドでイベント発生させた後に
* submit() メソッドで送信を行おうとした場合に
* 二重送信とみなされてしまいます。</p>
*
* @private
* @param form フォーム
* @param sEvent イベント名
* @param oEvent イベントオブジェクト
* @return fireEvent メソッドの戻り値
*/
sde.doubleSubmission.handleFireEvent = function (form, sEvent, oEvent) {
if (sEvent && sEvent.toLowerCase() === 'onsubmit') {
// onsubmit イベントの場合

var state = sde.doubleSubmission.onsubmitEventFiring;

// onsubmit イベントの fireEvent 実行中フラグを on
sde.doubleSubmission.onsubmitEventFiring = true;

// 本来の fireEvent メソッドを呼び出す
var result = form.sde_doubleSubmission_fireEvent_original(
sEvent, oEvent);

// onsubmit イベントの fireEvent 実行中フラグを元に戻す
sde.doubleSubmission.onsubmitEventFiring = state;

return result;

} else {
// それ以外のイベントの場合

// 本来の fireEvent メソッドを呼び出す
return form.sde_doubleSubmission_fireEvent_original(
sEvent, oEvent);

}
};

/**
* <p>指定の submit ボタンをカスタマイズします.</p>
*
* <p>IE でアップロードを行うフォーム用の処理です。</p>
*
* @private
* @param submitButton submit ボタン
*/
sde.doubleSubmission.customizeSubmitButton = function (submitButton) {
if (submitButton.sde_doubleSubmission_customized) {
// すでにカスタマイズ済みなら何もしない
return;
}
submitButton.sde_doubleSubmission_customized = true;

if (submitButton.onclick) {
submitButton.sde_doubleSubmission_onclick_original =
submitButton.onclick;
}
/** @ignore */
submitButton.onclick = function () {
sde.doubleSubmission.handleOnclickOfSubmitButton(this);
return false;
};
};

/**
* <p>submit ボタンの onclick のタイミングでの処理を行います。</p>
*
* <p>IE でアップロードを行うフォーム用の処理です。</p>
*
* <p>IEでは
* アップロードするファイルのパスが相対パスなどの場合に、
* 送信時にエラーとなって送信されません。</p>
*
* <p>この場合には送信中フラグを false に戻さないと
* 再送信できなくなるので、
* 送信中フラグを false に戻すようにしています。</p>
*
* <p>けれど、単に submit ボタンのクリックで送信した場合には
* エラー発生を把握できません。
* このため、submit ボタンの click イベント処理で
* 同じ name, value 属性の非表示の submit ボタンを作成し、
* その submit ボタンの click メソッドを呼び出して、
* 例外を catch します。</p>
*
* @private
* @param submitButton submit ボタン
*/
sde.doubleSubmission.handleOnclickOfSubmitButton = function (submitButton) {

if (submitButton.sde_doubleSubmission_onclick_original) {
try {
var ret = submitButton.sde_doubleSubmission_onclick_original();
if (ret === false) {
// 本来の onclick で false を返した場合は送信しない
return;
}
} catch (e) {
// onclick で例外発生しても以下の処理を行う
}
}

// 指定submitボタンと同じname,valueの非表示submitボタンを作成
var hiddenSubmit = document.createElement("input");
hiddenSubmit.type = "submit";
hiddenSubmit.name = submitButton.name;
hiddenSubmit.value = submitButton.value;
hiddenSubmit.style.display = 'none';

// 非表示submitボタンをフォームの子に追加
submitButton.form.appendChild(hiddenSubmit);

// 送信中フラグの現在の状態を取得
var state = sde.doubleSubmission.isBlocked();

var failed = false;
try {
// 非表示submitボタンをクリック
hiddenSubmit.click();
} catch (e2) {
failed = true;
}

// 非表示submitボタンをフォームの子から削除
submitButton.form.removeChild(hiddenSubmit);

if (failed) {
// 非表示submitボタンのクリックで例外が発生した場合

// 送信中フラグを元の状態に戻す
sde.doubleSubmission.setBlocked(state);

// アップロードエラー処理
sde.doubleSubmission.handleUploadError();
}

};

/**
* 二重送信エラー処理を行います。
*
* @private
*/
sde.doubleSubmission.handleDoubleSubmissionError = function () {

if (sde.doubleSubmission.doubleSubmissionErrorFunction) {
// 関数登録されていれば呼び出す
sde.doubleSubmission.doubleSubmissionErrorFunction();
}

};

/**
* アップロードエラー処理を行います。
*
* @private
*/
sde.doubleSubmission.handleUploadError = function () {

if (sde.doubleSubmission.uploadErrorFunction) {
// 関数登録されていれば呼び出す
sde.doubleSubmission.uploadErrorFunction();
}

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值