2011-10-27 12 views
42

Recentemente ho scoperto che la pseudo-classe :invalid si applica agli elementi del modulo required non appena la pagina viene caricata. Ad esempio, se si dispone di questo codice:Ritardato HTML5: pseudo-classe non valida fino al primo evento

<style> 
input:invalid { background-color: pink; color: white; } 
input:valid { background-color: white; color: black; } 
</style> 
… 
<input name="foo" required /> 

Quindi la pagina verrà caricata con un elemento di input rosa vuoto su di esso. Avere una validazione incorporata in HTML5 è grandioso, ma non penso che la maggior parte degli utenti si aspettino che il modulo venga convalidato prima di avere la possibilità di inserire qualsiasi valore. Esiste un modo per ritardare l'applicazione della pseudo-classe fino a quando il primo evento non influisce su quell'elemento (form submit, blur, change, whatever appropriate)? È possibile farlo senza JavaScript?

risposta

27

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

Essendo solo vuole indicare che un campo non è valido una volta che ha attenzione, usiamo la pseudo-classe di messa a fuoco per far scattare lo stile non valido. (Naturalmente, segnalando tutti i campi obbligatori come non valido fin dall'inizio sarebbe una scelta cattiva progettazione.)

Seguendo questa logica, il codice sarebbe simile a questa ...

<style> 
    input:focus:required:invalid {background-color: pink; color: white;} 
    input:required:valid {background-color: white; color: black; } 
<style> 

Creato un violino qui: http://jsfiddle.net/tbERP/

Come si può intuire, e come vedrete dal violino, questa tecnica mostra solo lo stile di convalida quando l'elemento è attivo. Non appena si sposta la messa a fuoco, lo stile viene eliminato, indipendentemente dal fatto che sia valido o meno. Non è l'ideale con qualsiasi mezzo.

+10

"Non ideale con qualsiasi mezzo." Infatti. C'è un modo di applicare lo styling a contenuti validi, ma non necessari, dopo che l'elemento ha perso l'attenzione? Non ho elaborato un modo per farlo. –

+0

Potrei immaginare una classe pseduo (attualmente non esistente) per forme come "inoltrate", in modo che questo agisca come un selettore genitore per qualsiasi input contenuto, come '#myform: input inviato: richiesto: invalid'. Perché anche se questo scenario attuale non è intuitivo, non è necessariamente realistico aspettarsi che il CSS sappia che un campo non è valido in circostanze specifiche (perché non dovrebbe farlo subito, per quanto ne sa?), Quindi vuoi davvero legare lo stile di input allo stato del modulo, non all'input stesso (ad es. quando il campo richiesto è vuoto E viene inviato il modulo genitore). – Anthony

+0

Questa risposta: https: // stackoverflow.it/questions/41619497/how-to-make-pseudo-class-invalid-apply-to-an-input-after-submitting-a-form si occupa effettivamente di questo bene, penso, anche se richiede un po 'di javascript . Aggiunge solo una classe "inviata" al modulo (proprio come stavo suggerendo!) In modo che le regole di stile possano essere 'form.submitted input: required: invalid' – Anthony

1

Si potrebbe fare in modo che solo gli elementi che hanno una certa classe su di essi sono e, sono rosa. Aggiungi un gestore di eventi a ciascun elemento richiesto che aggiunge quella classe quando lasci l'elemento.

Qualcosa di simile:

<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> 

E, naturalmente, non funzionerà come è in IE8 o al di sotto, come (a) DOMContentLoaded è relativamente nuovo e non era standard quando IE8 è uscito, (b) IE8 utilizza attachEvent piuttosto che il DOM standard addEventListener, e (c) IE8 non sta andando a cura di :required in ogni caso, in quanto non tecnicamente supporta HTML 5.

17

Questo non è possibile in puro CSS, ma può essere fatto con JavaScript Si tratta di un jQuery example:

// 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>

+0

Questa è una soluzione semplice;) – fegemo

+0

Questa è la soluzione che preferisco ma non hai più bisogno di jQuery. Questo può essere fatto con un semplice Javascript. – micah

2

Durante l'utilizzo di HTML5 validazione dei form, provare a utilizzare il browser per rilevare per invalidi di presentazioni/campi, piuttosto che ri-inventare la ruota.

Ascolta l'evento invalid per aggiungere una classe di "non valido" al modulo. Con la classe "non valida" aggiunta, puoi andare in città con lo styling del modulo utilizzando i selettori CSS3 :pseudo.

Ad esempio:

// 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); 

Ora, semplicemente lo stile la vostra forma come vedete la misura in base alla classe 'non valido' Abbiamo allegato.

Ad esempio:

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); 
} 
+1

Ehm, non è questo che reinventa la ruota molto di più della domanda? – Ryan

+0

Reinventare la ruota? Questa è la ruota ... Sopra c'è un modo efficace per gestire gli stili di convalida dei form HTML5 mentre accoppiano CSS e JS per risolvere il problema che stava avendo. Ciò gli consente di modellare i suoi elementi di modulo non validi ed evitare il pseudo styling sul caricamento della pagina. Correggimi se sbaglio, ma direi che è un modo solido per affrontare il suo problema. –

2

occupati html5 invalid evento incendi su elementi del modulo prima che si verifichi l'evento submit per ogni elemento che non passa checkValidity. È possibile utilizzare questo evento per applicare una classe per esempio alla forma e alla visualizzazione circostanti: stili non validi solo dopo che si verifica questo evento.

$("form input, form select, form textarea").on("invalid", function() { 
    $(this).closest('form').addClass('invalid'); 
}); 

tuo CSS sarebbe quindi simile a questa:

:invalid { box-shadow: none; } 
.invalid input:invalid, 
.invalid textarea:invalid, 
.invalid select:invalid { border: 1px solid #A90909 !important; background-color: #EEC2C2; } 

La prima riga rimuove lo stile di default, in modo da formare elementi guardano neutrale al caricamento della pagina. Non appena si attiva l'evento non valido (quando un utente tenta di inviare il modulo), gli elementi vengono visibilmente resi non validi.

1

Ho creato un piccolo shim per gestire questo nella mia base di codici. Ho appena iniziato con il mio elemento <form/> con la proprietà novalidate e un attributo data-validate-on="blur". Questo guarda per il primo evento di quel tipo. In questo modo puoi ancora utilizzare i selettori nativi :invalid per lo stile del modulo.

$(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'); 
     }); 
    }); 
}); 
0

Un buon modo è quello di astratto :invalid, :valid con le classi CSS e poi alcuni Javascript per controllare se il campo di input è concentrata o meno.

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

1

Queste risposte non sono aggiornati. Ora puoi farlo controllando la pseudo-classe di un segnaposto con CSS.

input:not(:placeholder-shown):invalid { 
 
    background-color: salmon; 
 
}
<form> 
 
    <input type="email" placeholder="[email protected]" required> 
 
</form>

Si inizia con uno sfondo normale e diventa rosa come si inserisce l'indirizzo e-mail incompleta in esso.