2010-04-13 33 views
69

Tengo un problema extraño con la validación que estoy escribiendo en un formulario. Es un botón 'Comprobar nombre de usuario' al lado de una entrada. El valor predeterminado de entrada es el nombre de usuario, por ejemplo, 'betamax'. Cuando presiono 'Comprobar nombre de usuario' pasa la expresión regular y envía el nombre de usuario al servidor. El servidor se comporta como se esperaba y devuelve '2' para indicar a los javascript que están enviando su propio nombre de usuario.Javascript regex devuelve verdadero ... luego falso ... luego verdadero ... etc.

Luego, cuando hago clic en el botón nuevamente, la expresión regular falla. No se envía nada al servidor obviamente porque la expresión regular ha fallado. Si presiono el botón nuevamente, la expresión regular pasa y luego el nombre de usuario se envía al servidor.

¡Literalmente no puedo entender lo que haría que esto ocurra! ¡No tiene sentido para mí!

Edición: He probado el problema en Firefox y Chrome (Mac)

Este es mi código:

$j("#username-search").click(checkUserName); 

function checkUserName() { 
    var userName = $j("#username").val(); 


    var invalidUserMsg = 'Invalid username (a-zA-Z0-9 _ - and not - or _ at beginning or end of string)'; 
    var filter = /^[^-_]([a-z0-9-_]{4,20})[^-_]$/gi; 
    if (filter.test(userName)) { 
     console.log("Pass") 
     $j.post(
     "/account/profile/username_check/", 
     { q: userName }, 
     function(data){ 
      if(data == 0) { 
       $j("#username-search-results").html("Error searching for username. Try again?"); 
      } 
      else if(data == 5) { 
       $j("#username-search-results").html(invalidUserMsg); 
      } 
      else if(data == 4) { 
       $j("#username-search-results").html("Username too short or too long."); 
      } 
      else if(data == 2) { 
       $j("#username-search-results").html("This is already your username."); 
      } 
      else if(data == 3) { 
       $j("#username-search-results").html("This username is taken."); 
      } 
      else if(data == 1){ 
       $j("#username-search-results").html("This username is available!"); 
      } 
     }); 
    } else { 
     console.log("fail") 
     $j("#username-search-results").html(invalidUserMsg); 
    } 

    return false; 

} 

El HTML:

<input name="username" id="username" value="{{ user.username }}" /> 
<input type="button" value="Is it taken?" id="username-search"> 
<span id="username-search-results"></span> 

Respuesta

130
/^[^-_]([a-z0-9-_]{4,20})[^-_]$/gi; 

Usted está utilizando un g (global) RegExp. En JavaScript, las expresiones regulares globales tienen estado: las llamas (con exec, test etc.) la primera vez, obtienes la primera coincidencia en una cadena dada. Llámalos de nuevo y obtendrás el próximo partido, y así sucesivamente hasta que no obtengas ninguna coincidencia y se restablezca al comienzo de la siguiente cadena. También puede escribir regex.lastIndex= 0 para restablecer este estado.

(Esto es, por supuesto, una pieza absolutamente terrible del diseño, garantizado para confundir y causar errores extraños. Bienvenido a JavaScript!)

se puede omitir el g de su RegExp, ya que sólo se está probando para una partido.

Además, no creo que desee [^-_] en la parte delantera y posterior. Eso permitirá cualquier carácter en cada extremo, es decir. *plop! sería válido. Probablemente estés pensando en las afirmaciones de mirar hacia adelante/mirar hacia atrás, pero no están disponibles en JavaScript. (Bueno, se supone que debe ser anticipado, pero está roto en IE.) Sugerir en su lugar:

/^[a-z0-9][a-z0-9_-]{2,18}[a-z0-9]$/i 
+5

¡Aprendí algo nuevo hoy! Nunca he tratado con RegEx en JS antes. :) – Powerlord

+3

Eso es todo. Normalmente incluyo/g por costumbre, pero creo que ya no volveré a hacerlo. ¡Gracias! – betamax

+0

+1 Me gustaría decir que es únicamente para el uso de la palabra "regexen", pero es una gran respuesta en todos los aspectos ;-) –

2
[a-z0-9-_] 

Este es mal, el último - debe estar al principio o al final.

[a-z0-9_-] 

Si eso podría causar este problema o no, no sé.

Notas adicionales:

Los caracteres primero y último se les permite ser cualquier carácter que no es - o _ en lugar de limitarse a a-z0-9

a-z0-9 no incluye caracteres en mayúsculas. Necesitas a-zA-Z0-9 para eso. a-zA-Z0-9_ se puede acortar a \w en la mayoría de los motores RegEx. No lo he probado en JavaScript.

+0

Gracias por la sugerencia. ¿Por qué exactamente importa el orden? Desafortunadamente, eso no resolvió el problema que estoy viendo. Acabo de probarlo en Chrome (estaba usando Firefox) y hace lo mismo. – betamax

+0

'-' es un personaje especial en grupos ... como puede ver, ya que lo usa para' a-z'. Debido a esto, se define como solo un literal '-' como el primer o último carácter de un RegEx. Una vez dicho esto, es posible que deba cambiarlo en '[^ -_]' también (a '[^ _-]'). – Powerlord

+0

Vaya, me acabo de dar cuenta de que puse '/ w' en lugar de' \ w' en mi respuesta. Debería ser arreglado ahora. – Powerlord

Cuestiones relacionadas