I want some javascript + ajax to check username availability on fly. And I have some troubles...
L开发者_Python百科et's imagine the situation when we're checking username availability on blur event.
What if we're getting such scenario...
- a) user entered username "kir"
- b) focuses on another element
- c) ajax request started (requesting availability of "kir" username)
- d) user focuses on username and enter one more letter "kirA" (response from c) isn't recieved yet)
- e) focuses on another element
- f) ajax request started (requesting availability of "kirA" username)
- g) we're getting answer from c) and
telling user that username is available, but it not (because we're telling about "kir", but not "kirA")
.
What should I do to avoid such situation? Use some kind of randomly generated tokens to check validity of answer?
Thank you
You need some sort of mapping between the XHR request object and the username query it contained. Or in the server's response to the AJAX query, include the username as well. A response may look like:
{
username: "kir",
available: false
}
In the callback, verify if the current textbox value is same as the returned username. If yes, then show the error, otherwise just ignore that response.
You should the XHR when you create a new one.
var ongoingRequest = null;
function test() {
if(ongoingRequest != null) {
ongoingRequest.abort();
}
ongoingRequest = $.ajax( ... );
}
You could add extra functionality to validate once more when you get the response:
$.ajax({
...
data: { query: query },
success: (function(q) {
return function(result) {
if( $('#myTxt').val() != q) {
// the textbox value is not the same as the query was
// at the time of creating this response!
return false;
}
...
}
})(query)
});
you just need the right scope of the async-request-variable!
if you create a new request, just check if there's already one, if yes: set it to null/cancel it, and go on!
another variant would be: block the ui, load a spinner-icon, block the input, ... (not that nice solutions...)
edit:
i think ajax/... is a nice thing, but when it comes down to adding more and more properties to a request, you should be a bit careful. even more when you can come up with a nicer solution (and you don't need any explicit ui-interaction like userA is not available
)
This is what I use for that purpose:
JAVASCRIPT:
$(document).ready(function() {
$("#username").blur(function() {
//remove all the class add the messagebox classes and start fading
$("#username_status").removeClass().addClass('username_status').text('Checking username').fadeIn("slow");
//verify entered username
$.post("path to php file",{ user_name:$(this).val() } ,function(data) {
// username not avaiable
if (data=='no') {
$("#username_status").fadeTo(200,0.1,function() {
$(this).html('Username in use').addClass('username_status_error').fadeTo(900,1);
});
// username available
}else if (data=='yes') {
$("#username_status").fadeTo(200,0.1,function() {
$(this).html('username available').addClass('username_status_ok').fadeTo(900,1);
});
// username field empty
}else if (data=='empty') {
$("#username_status").fadeTo(200,0.1,function() {
$(this).html('username field is empty').addClass('username_status_error').fadeTo(900,1);
});
// username check error
}else{
$("#username_status").fadeTo(200,0.1,function() {
$(this).html('fail to check username').addClass('username_status_error').fadeTo(900,1);
});
}
});
});
});
PHP FILE TO POST WITH AJAX:
<?php
require_once ('db_connect.php'); // include the database connection
if ($_POST['user_name']!="") {
// check if username is available from login table
$query = sprintf(" select * from login where username = '%s' ", mysql_real_escape_string($_POST['user_name']));
if (mysql_query($query)) {
if (mysql_num_rows(mysql_query($query))>0) {
echo "no";
}else{
echo "yes";
}
}else{
echo "error";
}
}else{
echo "empty";
}
?>
AND HTML FORM:
<form name="login-form" id="login-form" class="clients_form" method="post" action="form post link">
<ol>
<li>
<label for="login_usr" class="OF_name">Username:<span class="mandatory">*</span><br></label>
<input tabindex="1" accesskey="u" name="username" type="text" maxlength="30" id="username">
</li>
<li>
<label for="login_pwd" class="OF_email">Password:<span class="mandatory">*</span><br></label>
<input tabindex="2" accesskey="p" name="password" type="password" maxlength="15" id="password">
</li>
<li class="buttons">
<input class="btn" tabindex="3" accesskey="l" type="submit" name="cmdlogin" value="Login">
<input class="btn" name="cancel" type="button" value="Cancel" onclick="location.href='cancel link'">
</li>
</ol>
<br><br><br>
</form>
This is a simple sample that I've created to show you, but should be working fine...
When the user leaves the username field, the AJAX will post the PHP file to verify database, if the user returns to the username field, again, wend it leaves it, Ajax will post.
Hope this helps!
You could disable the input while the ajax is in progress.
Or, you can do "g) we're getting answer from c) and telling user that username kir
is not available"
Anurag's first suggestion (keeping the request data along with the query) is more optimal for the general case thatn returning the username. If you send several long parameters, you don't want them to unnecessarily use your bandwith and increase response time.
Quick example, keeping the record of what you send:
function checkUserName(){
var uName=$('#uname').val(); // get it immediately stored into the variable
$.ajax( {url: '...', data: {username: uName}, success: function(data){
if(data.is_available)
alert(uName + " is available."); // this instance of the variable is still in scope, even the checkUserName function has been re-called since
});
}
This code can still be optimized but you get the idea. If you're using this kind of thing often, you should read about scope in javascript (closures, etc).
精彩评论