2009-07-02 1 views
21

Utilizziamo l'eccellente validator plugin for jQuery qui su Stack Overflow per eseguire la convalida dell'input sul lato client prima che venga inviata al server.Problema di convalida JavaScript con caratteri internazionali

Generalmente funziona bene, tuttavia, questo ci fa graffiare la testa.

Il seguente metodo validatore viene utilizzato sul/modulo di risposta chiedere il campo del nome utente (si noti che è necessario essere disconnesso per vedere questo campo sul sito dal vivo: è in ogni pagina /question e la pagina /ask)

$.validator.addMethod("validUserName", 
    function(value, element) { 
    return this.optional(element) || 
    /^[\w\-\s\dÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜäëïöüçÇßØøÅåÆæÞþÐð]+$/.test(value); }, 
    "Can only contain A-Z, 0-9, spaces, and hyphens."); 

Ora, questo regex sembra strano ma è abbastanza semplice:

  • l'inizio della stringa (^)
  • soddisfa una di queste ..
    • carattere di parola (\ w)
    • trattino (-)
    • spazio (\ s)
    • cifre (\ d)
    • folli i caratteri delle lingue luna (AEIOU ecc)
  • ora corrisponde alla fine della stringa ($)

Sì, abbiamo incontrato nel problema Internationalized Regular Expressions. La definizione JavaScript di "carattere parola" non include caratteri internazionali.

Ecco la parte strana: anche se abbiamo preso la briga di aggiungere manualmente tonnellate dei caratteri internazionali validi alla regex, lo non funziona. Non è possibile inserire questi caratteri internazionali nella casella di input per il nome utente senza ottenere il ..

può contenere solo A-Z, 0-9, spazi e trattini

.. ritorno convalida!

Ovviamente la convalida è lavorare per le altre parti del regex .. così .. cosa succede?

L'altra strana parte è che questa convalida funziona nella console JavaScript del browser ma non quando viene eseguita come parte del nostro standard * .js include.

/^ [\ w- \ sÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜäëïöüçÇßØøÅåÆæÞþÐð] + $/ .test ('ÓBill de hora') === vero

Abbiamo eseguito in alcuni problemi di caratteri internazionali davvero bizzarri in Codice JavaScript prima, con conseguente hack molto, molto brutto. Vorremmo capire cosa sta succedendo qui e perché. Per favore, illuminaci!

+0

Questo potrebbe essere un problema di codifica dei caratteri? Ad esempio, una pazza luna "" proveniente dall'utilizzatore non è un "Ä" nella tua espressione regolare? – balpha

+0

Non conosco la risposta, ma è un buon modo per scrivere una domanda. –

+0

@Onorio Jeff difende sempre le domande ben scritte, quindi è meglio che lo faccia anche lui :-) Ma hai certamente ragione. – balpha

risposta

35

penso che i metodi di e-mail e l'URL di validazione sono un buon riferimento qui, per esempio. il metodo email:

email: function(value, element) { 
    return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); 
}, 

The script to compile that regex.

In altre parole, sostituendo l'elenco arbitrario di caratteri "luna pazza" con questo potrebbe aiutare:

[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF] 

Fondamentalmente questo evita i problemi di codifica dei caratteri che avete altrove sostituendo i caratteri esigenze di codifica con più generale definizioni. Sebbene non sia necessariamente più leggibile, finora è più breve della tua lista completa.

+0

giusto per chiarire perché questo ha funzionato . Se il tuo file .js è racchiuso in una codifica di caratteri, tutti i caratteri all'interno delle espressioni regex al suo interno verranno rappresentati su quella codifica, anche se la tua pagina web utilizza un'altra codifica. Nei miei progetti ho semplicemente codificato TUTTO che può contenere stringhe internazionali in UTF-8. Questo include i file .js. Quello che probabilmente è successo a Jeff è che i suoi file .js sono stati codificati in un set di caratteri e la sua pagina è stata analizzata con un altro set di caratteri, le sue richieste/risposte HTTP probabilmente codificate con lo stesso set di caratteri della pagina. Questo spiega perché ha funzionato sul debugger. – Hoffmann

+0

Un'altra cosa, prova alert ("áéíóú") se mostra che il tuo file javascript è codificato nella stessa codifica della tua pagina. Un'altra soluzione è semplicemente includere i javascript con:

2

I caratteri internazionali elencati fanno parte dell'ASCII esteso.quelli aggiunti da te non lo sono certamente.

2

Visto che la dichiarazione funziona nella console, questo potrebbe essere necessario il modo in cui i file .js vengono salvati (ad esempio ascii o UTF-8) e che il browser li sta caricando in questo modo e nel processo vengono tradotti i caratteri?

+0

JS non sa nulla di UTF-8, anche se la codifica è impostata così. – dusoft

+0

Ma il browser lo fa, vero? Cosa succede se il file viene caricato come UTF-8 e il motore JS del browser interpreta erroneamente i caratteri perché il browser ha caricato il file in modo errato? – Colin

+2

Sì, il browser se ne frega. Se si salva un "Ä" come non Unicode, il risultato sarà un flusso di byte UTF-8 non valido. Pertanto, non può mai corrispondere a un flusso di byte UTF-8 corrispondente a "Ä". – Boldewyn

3

Qual è la codifica del carattere del file JS?

Per QNames XML Io uso questo RegExp:

/** 
* Definition of an XML Name 
*/ 
var NameStartChar = "A-Za-z:_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D"+ 
        "\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF"+ 
        "\uF900-\uFDCF\uFDF0-\uFFFD\u010000-\u0EFFFF"; 
var NameChar = NameStartChar+"\\-\\.0-9\u00B7\u0300-\u036F\u203F-\u2040"; 
var Name = "^["+NameStartChar+"]["+NameChar+"]*$"; 
RegExp (Name).test (value); 

Funziona come un fascino anche con i caratteri internazionalizzate. Nota l'escape. A causa di ciò, sono in grado di limitare il file JS ai caratteri ASCII. Pertanto non ho problemi quando si tratta di set di caratteri ISO-8859 rispetto a UTF-8.

Questo non è più vero se si utilizzano codifiche di caratteri in cui ASCII non è un sottoinsieme reale (ad esempio, in Asia UTF-16).

Cheers,

+0

Come ho capito, le regole del validatore si trovano in un file JS esterno. Poi scommetto che quel file è nella codifica sbagliata (cioè non UTF-8). – Boldewyn

+0

Sto aprendo il file su disco in Notepad2 e sembra corretto - identico a quello che vedi sopra in ANSI e quando passo a codifiche Unicode, UTF-8, anche identiche. –

+0

Questo non può essere. Un ANSI 'Ä' (== ISO-8859-1) ha una rappresentazione a singolo byte 'C4', mentre UTF-8 'Ä' appare in un editor esadecimale come 'C3 84'. Cosa intendi con 'interruttore'? È una vera conversione tra le codifiche? – Boldewyn

13

Questa non è davvero una risposta, ma non ho ancora 50 rappresentanti per aggiungere un commento ... Può essere attribuito a problemi di codifica.

Yea "ECMA non dovrebbe preoccuparsi di codifica ..." bla bla, e se siete su firefox, vai a Visualizza> Codifica caratteri> occidentale (ISO-8859-1) quindi provare a utilizzare il nome campo.

Funziona bene per me dopo aver cambiato manualmente la codifica (concesso il resto della pagina non piace l'interruttore di codifica,: P)

(su IE8 si può andare a Page> Codifica> dell'Europa occidentale (Windows) per ottenere lo stesso effetto)

+0

ha ragione, questo rende magicamente il Nome: lavoro di validazione (!) –

2

Usa qualcosa come Fiddler o Charles (non della parte della rete di Firebug, o qualsiasi altra cosa che in realtà all'interno del browser) per esaminare ciò che è effettivamente provenienti oltre il filo. È quasi sicuramente un problema di codifica: il file è stato salvato in alcuni set di caratteri Microsoft e viene inviato come UTF-8, o forse il contrario.

Nel caso di JS RegExps è possibile, come sottolinea Boldewyn, evitare questi problemi specificando il punto di codice Unicode per i caratteri desiderati che si trovano al di fuori dell'intervallo US-ASCII. Sarebbe comunque meglio assicurarsi che non si mischino le codifiche tra il luogo in cui il file è stato salvato e il luogo in cui è servito, comunque.

+0

gzip sul filo, così scomodo da fare –

+0

Sia Fiddler che Charles può occuparsene. IIRC Fiddler (almeno nella versione 2) offrirà un pulsante nell'area di visualizzazione Risposta per consentire all'utente di visualizzare il contenuto non compresso. – NickFitz

2

In ritardo al gioco qui, ma ho appena usato questa espressione e sembrava funzionare bene per me.Sembra essere abbastanza completo e relativamente semplice:

var re = /^[A-zÀ-ÿ\s\d-]*$/g; 
 
var str1 = 'casa-me,pois 99 estou farto! Eis a lista:uma;duas;três'; 
 
var str2 = 'casa-me pois 99 estou farto Eis a lista uma duas três'; 
 

 
alert(re.test(str1)); 
 
alert(re.test(str2));