Skip to content

イベントの振り分けと false による中止条件 ​

第1版作成 最終更新 (日本時間)
確認バージョン1.5.8.1

$p.events に関数を置くだけでは、その戻り値が処理を止めるかは決まりません。_event.js が関数を探して結果をまとめ、_form.js や _ajax.js などの呼び出し元が false を見て中止するかを決めます。

DOM の change を扱う 項目イベントと、ここで扱う $p.events の名前による呼び出しは別です。

eventArgs は引数を包むだけ ​

eventArgs(url, methodType, data, $control, _async, ret, json) は、新しいオブジェクトに7つの値を入れます。イベントを登録・発火する関数ではありません(引数の組み立て)。

プロパティ内容と確認点
url処理先の URL。send の初期段階では null
methodTypeget・post などのメソッド
data渡されたデータへの参照。初期段階や GET では null の場合がある
$control操作元の jQuery オブジェクト。呼び出し経路によってはない
async非同期指定。ただしイベントの位置によっては既定値の補完前
ret呼び出し元の結果値。通信完了前と後を区別する
json成功応答など。常に命令配列が入るわけではない

オブジェクトや jQuery 要素をコピーする処理はありません。args.data を変えると、呼び出し元と同じオブジェクトを変えることになります(eventArgs)。

execEvents は3段階で呼ぶ ​

例えば event が before_send、コントロールが id="Update" data-action="Update" なら、次の順に呼び出します(振り分け)。

  1. $p.events.before_send
  2. $p.events.before_send_Update(ID)
  3. ID と data-action が異なる場合だけ、アクション名のイベント

文字列は大文字小文字を含めて、そのまま連結します。data-action がない場合でも ID と異なると判定され、末尾が _undefined の名前を探す経路があります。$control がない引数では、共通イベントだけです。

図を読み込み中…

共通イベントの false でも後続ハンドラは実行する ​

execEvents の内部では、各ハンドラが 厳密に false を返したときだけその結果を false にします。未登録や undefined の戻り値は true 扱いです。

ID・アクション別の呼び出しは exec(名前) && result の順なので、既に result が false でも exec を実行します。すべての名前を呼んだうえで、一つでも false なら最終結果が false です。共通ハンドラの false は、後続ハンドラを呼ばない指定ではありません(集約の実装)。

中止できる位置は呼び出し元で決まる ​

イベントfalse による通常処理の中止条件・位置
before_setDataできるsend 内、バッファ取得前
after_setDataできるsend 内、バッファ取得後。ただし必須項目の収集前
before_validateできるsend 内、validate クラスがある場合
after_validateできるsend 内、検証成功後
before_sendできるajax 内、CAPTCHA 準備後・確認ダイアログ前
after_sendできない呼び出し元が結果を使わない。通信完了の合図でもない
before_set・after_setできないdispatch の前後。戻り値を中止条件に使わない
ajax_before_send などの ajax_*できないexecEvents を呼ぶが戻り値を中止条件に使わない

根拠は イベントのラッパー、send、ajax、dispatchです。controlAutoPostBack は send を経由しないため、最初の4つの send 内イベントは呼びません(別の送信経路)。

after_setData という名前でも、DOM の全項目の収集が終わった位置ではありません。setMustData は send の後段です。

更新ボタンだけを同期的に確認する例 ​

次のブラウザ側のスクリプトを新規・編集画面へ配置します。data-action="Update" の操作で、確認をキャンセルしたら通信を止めます。通常の更新ボタンが対象で、検証用レコードで確認してください。

js
$p.events.before_send_Update = function (args) {
    return window.confirm('この内容で更新しますか?');
};

キャンセル時には、この before_send の中止判定で $p.ajax が false を返します。既存のハンドラがある場合は 複数処理の登録で追加します。本体の data-confirm による確認がある操作では、それも後に実行されるため、二重確認の有無を確かめます(確認の順序)。

非同期の false では中止しない ​

例えば async function () { return false; } の即時の戻り値は Promise です。execEvents は Promise の完了を待たず、=== false を判定するため、この書き方では中止できません(厳密な判定)。

非同期の事前確認をするなら、最初の処理では同期的に false を返していったん中止し、確認完了後に明示的に再実行する設計が必要です。そのときは再確認のループや二重送信を防ぐ状態管理も用意します。ここでは、同期待機型の確認例に限定しています。

名前の振り分けだけを保存せずに試す ​

次はブラウザコンソール用です。DOM に接続していないボタンを用い、独自のイベント名で3つのハンドラを試します。send や ajax は呼びません。

js
(function () {
    const names = ['manualEventLab', 'manualEventLab_TestButton', 'manualEventLab_Update'];
    const previous = names.map(function (name) { return $p.events[name]; });
    const order = [];
    try {
        $p.events[names[0]] = function () { order.push('共通'); return false; };
        $p.events[names[1]] = function () { order.push('ID'); };
        $p.events[names[2]] = function () { order.push('action'); };
        const $button = $('<button/>').attr({ id: 'TestButton', 'data-action': 'Update' });
        const result = $p.execEvents(names[0], $p.eventArgs('/test', 'post', {}, $button, true));
        console.log(order); // 共通、ID、action の順
        console.log(result); // false
    } finally {
        names.forEach(function (name, index) {
            if (previous[index] === undefined) delete $p.events[name];
            else $p.events[name] = previous[index];
        });
    }
})();

この例と、false の集約・同一 ID/action の省略・Promise の扱いは、本体 JavaScript で確認しています。実機の更新操作は未検証です。

関連ページ ​

変更履歴

第1版フロント基盤JSのイベント・通信・日時処理を詳しく解説