在第一个事件之前延迟HTML5:无效的伪类
我最近发现:invalid
伪类在页面加载后立即应用于required
表单元素。 例如,如果你有这样的代码:
<style> input:invalid { background-color: pink; color: white; } input:valid { background-color: white; color: black; } </style> … <input name="foo" required />
然后你的页面将加载一个空的粉红色的input元素。 对HTML5进行validation是非常好的,但我不认为大多数用户希望表单在他们有机会input任何值之前进行validation。 有什么办法可以延迟伪类的应用,直到影响该元素的第一个事件(表单提交,模糊,更改,任何合适的)为止? 没有JavaScript可以做到这一点?
http://www.alistapart.com/articles/forward-thinking-form-validation/
由于我们只是想表示一个字段在焦点时是无效的,我们使用焦点伪类来触发无效的样式。 (当然,从一开始就将所有必填字段标记为无效将是一个糟糕的deviseselect。)
遵循这个逻辑,你的代码看起来像这样…
<style> input:focus:required:invalid {background-color: pink; color: white;} input:required:valid {background-color: white; color: black; } <style>
在这里创build一个小提琴: http : //jsfiddle.net/tbERP/
正如你所猜测的,正如你将从小提琴中看到的那样,这种技术只在元素具有焦点时才显示validation样式。 一旦将焦点移开,样式将被丢弃,无论其是否有效。 不以任何方式理想。
这在纯CSS中是不可能的,但可以用JavaScript来完成。 这是一个jQuery的例子 :
// use $.fn.one here to fire the event only once. $(':required').one('blur keydown', function() { console.log('touched', this); $(this).addClass('touched'); });
/** * All required inputs initially are yellow. */ :required { background-color: lightyellow; } /** * If a required input has been touched and is valid, it should be white. */ .touched:required:valid { background-color: white; } /** * If a required input has been touched and is invalid, it should be pink. */ .touched:required:invalid { background-color: pink; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <p> <label> Name: <input type="text" required> *required </label> </p> <p> <label>Age: <input type="text"> </label> </p>
在使用HTML5表单validation时,尝试使用浏览器来检测无效提交/字段,而不是重新发明轮子。
聆听invalid
事件,向表单中添加一个“无效”类。 添加“无效”类后,您可以使用CSS3 :pseudo
select器为表单创build样式。
例如:
// where myformid is the ID of your form var myForm = document.forms.myformid; var checkCustomValidity = function(field, msg) { if('setCustomValidity' in field) { field.setCustomValidity(msg); } else { field.validationMessage = msg; } }; var validateForm = function() { // here, we're testing the field with an ID of 'name' checkCustomValidity(myForm.name, ''); if(myForm.name.value.length < 4) { checkCustomValidity( // alerts fields error message response myForm.name, 'Please enter a valid Full Name, here.' ); } }; /* here, we are handling your question above, by adding an invalid class to the form if it returns invalid. Below, you'll notice our attached listener for a form state of invalid */ var styleInvalidForm = function() { myForm.className = myForm.className += ' invalid'; } myForm.addEventListener('input', validateForm, false); myForm.addEventListener('keyup', validateForm, false); myForm.addEventListener('invalid', styleInvalidForm, true);
现在,只要根据我们所附的“无效”课程简单地devise您的表格。
例如:
form.invalid input:invalid, form.invalid textarea:invalid { background: rgba(255, 0, 0, .05); border-color: #ff6d6d; -webkit-box-shadow: 0 0 6px rgba(255, 0, 0, .35); box-shadow: 0 0 6px rgba(255, 0, 0, .35); }
在submit
事件发生之前,对于没有通过checkValidity的每个元素,都会在表单元素上触发一个html5 invalid
事件。 例如,您可以使用此事件将类应用于周围的表单,并仅在发生此事件后才显示:无效的样式。
$("form input, form select, form textarea").on("invalid", function() { $(this).closest('form').addClass('invalid'); });
你的CSS会看起来像这样:
:invalid { box-shadow: none; } .invalid input:invalid, .invalid textarea:invalid, .invalid select:invalid { border: 1px solid #A90909 !important; background-color: #EEC2C2; }
第一行删除了默认样式,所以表单元素在页面加载时看起来是中性的。 一旦无效事件触发(当用户尝试提交表单),元素将被视为无效。
你可以这样做,只有那些具有特定类别的元素才是粉红色的。 添加一个事件处理程序到每个需要的元素,当你离开元素时添加这个类。
就像是:
<style> input.touched:invalid { background-color: pink; color: white; } input.touched:valid { background-color: white; color: black; } </style> <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>
当然,它不会像IE8或以下版本那样工作,因为(a) DOMContentLoaded
是相对较新的,当IE8发布时不是标准的,(b)IE8使用attachEvent
而不是DOM标准的addEventListener
, c)IE8不会关心:required
无论如何,因为它在技术上不支持HTML 5。
我在代码库中创build了一个小垫片来处理这个问题。 我刚刚开始使用具有novalidate
属性的<form/>
元素以及data-validate-on="blur"
属性。 这就注意到这种types的第一个事件。 这样,你仍然可以使用native :invalid
cssselect器进行表单样式设置。
$(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'); }); }); });
一个好方法是抽象:invalid, :valid
用CSS类:invalid, :valid
,然后用一些JavaScript来检查input字段是否被聚焦。
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