25

電話番号と米国の郵便番号フィールドにjQuery ValidateMasked Inputの両方を使用するフォームがあります。

たとえば、米国の郵便番号の場合、Masked Input は数字のみの入力を許可し、"99999" または "99999-9999" (9 は任意の数字) のいずれかの形式を強制します。Validate ルールでも同じことが必要です。しかし、実際には有効であるべきフィールドが Validate によって無効としてマークされる場合があります。

コード仕様

jQuery Validate が郵便番号フィールドで使用している正規表現は^\d{5}$|^\d{5}\-\d{4}$.

Masked Input で適用しているマスクは.mask('99999?-9999')

再現する手順

次の操作を行うと、それらの間の競合が発生します。

  • 無効な郵便番号 (3 桁など) を入力してください
  • タブでフィールドから離れます。マスクされた入力は入力を消去し (予期される動作)、jQuery Validate は空白であるため無効としてマークします (これも予期されます)。
  • 郵便番号フィールドに戻り、有効な5 桁の郵便番号を入力します。
  • タブでフィールドから離れます。まだ無効としてマークされています。これは予想外です。

9 桁の郵便番号を入力すると、この問題は発生しません。

仮説

このエラーは、5 桁の zip の場合、Masked Input が一時的に "-____" を挿入して、オプションでダッシュとさらに 4 桁を入力できることをユーザーに示すためだと思います。これはぼかしで削除されますが、アンダースコアが許可されていないため、削除される前にフィールドが検証されて失敗します。

この仮説は、フォームが後で再検証された場合に zip フィールドがパスするという事実によって裏付けられています。私はこれを2つの方法で行いました:

  • フォームを送信することにより; 送信ボタンがクリックされ、zip フィールドが通過し、フォームが送信されると、すべてのフィールドが再検証されます。

  • blurその特定のフィールドを再検証するイベントを設定する。例えば:

    $("#zipcode").blur(function(){ $(this).closest('form').validate().element($(this)); });

これはハッキーな解決策として役立ちますが、満足できるものではありません。なぜなら、1) デフォルト設定はすでにぼかし時に再検証されているため、これが繰り返され、2) 通常の Validate ルール以外に追加のコードが必要になるためです。

他の誰かがこの問題に遭遇しましたか? 追加のぼかしイベント リスナーを設定するよりも洗練されたソリューションはありますか?

更新: ハッキング ソリューションの適用

上記のハッキーなソリューションを適用しても、思ったほどうまくいきません。たとえば、これは機能しません:

$appDiv.delegate('input,select,textarea','blur',function(){
  $(this).closest('form').validate().element($(this));
});

...これもしません:

$('input,select,textarea').live('blur',function(){
  $(this).closest('form').validate().element($(this));
});

...しかし、これは:

$('input,select,textarea').each(function(){
  $(this).blur(function(){
    $(this).closest('form').validate().element($(this));
  });
});

これらの要素は AJAX によって読み込まれる.eachため、フォーム セクションが読み込まれるたびにバージョンを実行する必要があります。

4

7 に答える 7

11

私は次の解決策を試しましたが、それは魅力のように機能します。

$("[data-input-type=phone]", "body")
  .mask("(999) 999 99 99")
  .bind("blur", function () {
    // force revalidate on blur.

    var frm = $(this).parents("form");
    // if form has a validator
    if ($.data( frm[0], 'validator' )) {
      var validator = $(this).parents("form").validate();
      validator.settings.onfocusout.apply(validator, [this]);
    }
  });

問題を引き起こすのは、イベントの順序付けです。要素がマスクされると、 maskedinput プラグインによって検証されますがblur、同じ要素は、focusoutmaskedinput のぼかしの前に呼び出されるイベント (IE 以外のブラウザーでのぼかしのラッパー) で検証プラグインによって検証されます。

この状況では"(___) ___ __ __"、バリデーターが値をチェックするときに入力要素に値があります。コードが maskedinput の blur イベントに達すると、有効な入力ではないため、プラグインが値をテストしてクリアします。

検証結果は、検証ケースごとに異なる場合があります。たとえばrequired、要素に値があるため、ルールは成功します。number入力を空のままにしても、必須でないフィールドは失敗します。これは、次のようなマスク"999"がテストされる可能性があるためです。12_

上記のコードは、マスクされた入力のフォームに検証が添付されているかどうかをテストし、フォーカスアウト イベント ハンドラーを呼び出します。私たちのハンドラーは最新のものとしてアタッチされているので、うまくいけば最後に呼び出されます。

警告、コードは検証プラグインの動作をコピーするだけです。おそらく 10 年間は機能しますが、検証プラグインが現在とは異なることを行うことを決定した場合、失敗する可能性があります。

心から

于 2012-03-14T09:14:38.743 に答える
10

私は実際、この正確な質問に対する答えを探していました。より信頼性の高い回避策を見つけ出すことになりました。

私は郵便番号に対して独自のバリデーターメソッドを定義しているので、値からプレースホルダーを削除した後、郵便番号の長さが6の場合にハイフンを削除するように変更しました。

次のように見えました。

$.validator.addMethod("zipcode", function(postalcode, element) {
            //removes placeholder from string
            postalcode = postalcode.split("_").join("");

            //Checks the length of the zipcode now that placeholder characters are removed.
            if (postalcode.length === 6) {
                //Removes hyphen
                postalcode = postalcode.replace("-", "");
            }
            //validates postalcode.
            return this.optional(element) || postalcode.match(/^\d{5}$|^\d{5}\-\d{4}$/);
        }, "Please specify a valid zip code");

したがって、検証中の郵便番号には、入力プラグインによってプレースホルダーが追加され、入力された郵便番号に 5 桁の数字 (ハイフンを含めて 6 桁) しかない場合はハイフンが削除されます。したがって、適切に検証されます。

于 2011-02-02T00:27:56.270 に答える
7

mask() 関数にフックし、追加のロジックを追加して、デフォルトのマスクのぼかしロジックの後に独自のぼかしロジックを起動するだけです。

//Store the original mask function
var origMaskFn = $.fn.mask;

$.fn.mask = function (mask, settings) {

    //Call the original function applying the default settings
    origMaskFn.apply(this, [mask, settings]);

    //Manually validate our element on blur to prevent unobtrusive messages
    //from showing before the mask is properly scrubbed
    $(this).bind('blur', function () {
        var $form = $(this).parents('form');
        if (!$form.exists())
            return;

        var validator = $form.validate().element($(this));
    });
}

また、「exists()」関数に気付くかもしれません。これは、jQuery セレクターでよく使用するものです。

//Function to detect if a jQuery elements exists.  i.e.:
//      var $element = $(selector);
//      if($element.exists()) do something...

$.fn.exists = function () {
    return this.length !== 0;
}
于 2012-12-05T21:10:08.500 に答える
5

同様の問題があり、デフォルトのプレースホルダー文字を空の文字列に変更して解決しました。

私はを使用してい.mask('9?99');て、単純な「数値」ルールで検証していましたが、同じ種類の競合がありました。

マスク宣言を.mask('9?99',{placeholder:''});and... に変更しました。これ以上の競合はありません。:)

あなたの場合、-マスクプラグインによって常にフォームに挿入される郵便番号のため、問題が発生する可能性があります。正規表現を(両方のケースでダッシュに一致する)に変更できると思います^\d{5}\-$|^\d{5}\-\d{4}$。その後、検証する必要があります。

とにかく、あなたはしばらく前に投稿しましたが、おそらくこれはもう必要ありませんが、おそらく他の誰かを助けるでしょう. :)

于 2011-08-18T22:24:06.500 に答える
1

綴じる順番は関係ありますか?たとえば、

$(function() {
  var $form = $("#myForm"), $zip = $("#zip");
  $zip.mask("99999?-9999");
  $form.validate();
});

$(function() {
  var $form = $("#myForm"), $zip = $("#zip");
  $form.validate();
  $zip.mask("99999?-9999");
});

バインディングは順番に起動する必要があると思います。

于 2010-12-09T14:28:22.487 に答える
0

私は同じ問題に直面しており、適切な解決策を得るために2時間を費やしました. 最後に、適切なコードを作成しました。あなたはそれを使用することができます

郵便番号の場合。

$.validator.addMethod("zipcode", function(postalcode, element) {
            //removes placeholder from string
            postalcode = postalcode.replace(/[^0-9]/g, "");
            //validates postalcode.
            return this.optional(element) || postalcode.match(/^\d{5}$|^\d{5}\-\d{4}$/);
        }, "Please specify a valid zip code");

郵便番号の長さを増減したい場合は、postalcode.match(/^\d{5}$|^\d{5}-\d{4}$/); を変更します。あなたの条件に従う数。

電話の場合も同じコードが使用されますが、postalcode.match(/^\d{10}$|^\d{10}-\d{9}$/); のような数字のみを変更する必要があります。

$.validator.addMethod("phone_length", function(phoneno, element) {
                //removes all special characters
                phoneno= phoneno.replace(/[^0-9]/g, "");
                return this.optional(element) || phoneno.match(/^\d{10}$|^\d{10}\-\d{9}$/);
            }, "Please enter a valid phone");

このコードが大いに役立つことを願っています。呼び出し方法を知りたい場合は、検証フィールドにzipcode:trueを追加するだけです

于 2020-02-03T19:00:20.477 に答える