jquery - Javascript Regex gibt zuerst true zurück.. dann false.. dann wieder true.. usw.
Ich habe ein seltsames Problem mit der Validierung, die ich in einem Formular schreibe. Es gibt einen 'Benutzernamen prüfen'-Button neben einem Eingabefeld. Der Standardwert des Eingabefelds ist der Benutzername, zum Beispiel 'betamax'. Wenn ich auf 'Benutzernamen prüfen' klicke, besteht er den Regex-Test und sendet den Benutzernamen an den Server. Der Server verhält sich wie erwartet und gibt '2' zurück, um dem JavaScript mitzuteilen, dass sie ihren eigenen Benutzernamen übermitteln.
Dann, wenn ich den Button erneut klicke, schlägt der Regex fehl. Nichts wird offensichtlich an den Server gesendet, weil der Regex fehlgeschlagen ist. Wenn ich den Button erneut drücke, besteht der Regex und dann wird der Benutzername an den Server gesendet.
Ich kann buchstäblich nicht herausfinden, was dazu führen würde, dass es das tut! Es ergibt für mich keinen Sinn!
Bearbeiten: Ich habe das Problem in Firefox und Chrome (Mac) getestet
Das ist mein Code:
$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;
}
Das 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>
Antwort #1
/^[^-_]([a-z0-9-_]{4,20})[^-_]$/gi;
Du verwendest ein g (globales) RegExp. In JavaScript haben globale Regexen einen Zustand: Wenn du sie das erste Mal aufrufst (mit exec, test usw.), erhältst du das erste Vorkommen in einem bestimmten String. Rufst du sie erneut auf, erhältst du das nächste Vorkommen und so weiter, bis kein Treffer mehr gefunden wird und es wird zum Anfang des nächsten Strings zurückgesetzt. Du kannst auch regex.lastIndex=0 schreiben, um diesen Zustand zurückzusetzen.
(Dies ist natürlich ein absolut schreckliches Stück Design, garantiert verwirrend und verursacht seltsame Fehler. Willkommen bei JavaScript!)
Du kannst das g aus deinem RegExp weglassen, da du nur auf einen Treffer testest.
Also, ich glaube nicht, dass du [^-_] am Anfang und Ende haben möchtest. Das würde jedes beliebige Zeichen an jedem Ende erlauben, also wäre z. B. *plop! gültig. Du denkst wahrscheinlich an Lookahead-/Lookbehind-Assertions, aber diese sind in JavaScript nicht verfügbar. (Naja, Lookahead soll verfügbar sein, aber es ist in IE kaputt.) Vorschlag stattdessen:
/^[a-z0-9][a-z0-9_-]{2,18}[a-z0-9]$/i
