遅延HTML5:最初のイベントまでは無効な疑似クラス

私は最近、:invalid 疑似クラスが、ページが読み込まれるとすぐに required フォーム要素に適用されることを発見しました。たとえば、次のコードがあるとします。


…
<input name="foo" required />

次に、空のピンクの入力要素がページに表示されます。 HTML5に検証機能が組み込まれているのは素晴らしいですが、ほとんどのユーザーはフォームを検証してから、値を入力する機会はありません。最初のイベントがその要素(form submit、blur、change、それが何であれ)に影響するまで、擬似クラスのアプリケーションを遅らせる方法はありますか? JavaScriptなしでこれを行うことは可能ですか?

48
私はコメントできないので、この補足を@ user3284463に追加します。 makeDirty は、ダーティークラスを切り替えるべきではなく、将来(青色、無効な、有効な)イベントに保持する必要があります。function makeDirty ){if(!e.target.classList.contains( 'dirty'))e.target.classList.add( 'dirty'); }
追加された 著者 Abir Stolov,

9 答え

http://www.alistapart.com/articles/forward-thinking-form-validation/

フィールドは一度無効になったことを示すだけなので   フォーカス擬似クラスを使用して無効なスタイリングをトリガーします。   (当然ながら、必要なすべてのフィールドを最初から無効とフラグを立てる   設計上の選択肢が貧弱です)。

このロジックに従って、あなたのコードは次のようになります...


<script>
  document.addEventListener('DOMContentLoaded', function() {
    var required = document.querySelectorAll('input:required');
    for (var i = 0; i < required.length; ++i) {
      (function(elem) {
        function removeClass(name) {
          if (elem.classList) elem.classList.remove(name);
          else
            elem.className = elem.className.replace(
              RegExp('(^|\\s)\\s*' + name + '(?:\\s+|$)'),
              function (match, leading) {return leading;}
          );
        }

        function addClass(name) {
          removeClass(name);
          if (elem.classList) elem.classList.add(name);
          else elem.className += ' ' + name;
        }

       //If you require a class, and you use JS to add it, you end up
       //not showing pink at all if JS is disabled.
       //One workaround is to have the class on all your elements anyway,
       //and remove it when you set up proper validation.
       //The main problem with that is that without JS, you see what you're
       //already seeing, and stuff looks hideous.
       //Unfortunately, you kinda have to pick one or the other.


       //Let non-blank elements stay "touched", if they are already,
       //so other stuff can make the element :invalid if need be
        if (elem.value == '') addClass('touched');

        elem.addEventListener('blur', function() {
          addClass('touched');
        });

       //Oh, and when the form submits, they need to know about everything
        if (elem.form) {
          elem.form.addEventListener('submit', function() {
            addClass('touched');
          });
        };
      })(required[i]);
    }
  });
</script>

もちろん、(a) DOMContentLoaded は比較的新しく、IE8が出てきたときには標準ではなかったので、IE8では attachEvent addEventListener ではなく、:required を気にするつもりはありません.HTMLを技術的にサポートしていないので5。

1
追加された

I created a small shim to deal with this in my codebase. I just start off with my <form/> element having the novalidate property along with a data-validate-on="blur" attribute. This watches for the first event of that type. This way you can still use the native :invalid CSS selectors for the form styling.

$(function() {
    $('[data-validate-on]').each(function() {
        var $form = $(this);
        var event_name = $form.data('validate-on');

        $form.one(event_name, ':input', function (event) {
            $form.removeAttr('novalidate');
        });
    });
});
1
追加された

良い方法は、:invalid、:valid をCSSクラスで抽象化し、入力フィールドがフォーカスされているかどうかを確認するJavaScriptを抽象化することです。

CSS:

input.dirty:invalid{ color: red; }
input.dirty:valid{ color: green; }

JS:

// Function to add class to target element
function makeDirty(e){
  e.target.classList.toggle('dirty');
}

// get form inputs
var inputs = document.forms[0].elements;

// bind events to all inputs
for(let input of inputs){
  input.addEventListener('invalid', makeDirty);
  input.addEventListener('blur', makeDirty);
  input.addEventListener('valid', makeDirty);
}

DEMO

0
追加された