AJAX Username Availability Checker Using MooTools

By  on  
MooTools Username Checker

Another one of my popular, early blog posts has been AJAX Username Availability Checker Using MooTools 1.2. Looking back now, the code is atrocious and very inflexible. I've taken some time to update the post to be more reliable, clean, and speedy.

The HTML

<p><strong>Please provide your desired username: &nbsp;&nbsp;&nbsp;</strong>
	<input type="text" name="username" id="username" size="30" class="basis" />
</p>

The foundation of the system is the INPUT element with a specific ID. No other elements are required. The eventual IMG element will be generated by MooTools.

The CSS

.basis		{ padding:5px; border:1px solid #ccc; }
.available	{ border:1px solid #008000; background:#90ee90; }
.taken		{ border:1px solid #fc0; background:#fffea1; }

You'll want to create three CSS classes: one that is always applied to the input, another class which represents an available username, and one last class to represent a taken username. Green is always good to use for positive results. As for how you denote a taken username, please don't be a #f00.

The MooTools JavaScript

var AvailabilityChecker = new Class({

	//implements
	Implements: [Options,Events],

	//options
	options: {
		trigger: 'keyup',
		offset: { x:0, y:0 },
		minLength: 5,
		availableClass: 'available',
		takenClass: 'taken',
		availableImage: '',
		takenImage: '',
		url: 'ajax-username-check.php'
	},
	
	//initialization
	initialize: function(element,options) {
		//set options
		this.setOptions(options);
		this.element = document.id(element);
		this.lastValue = this.element.value;
		this.cache = {};
		//create the image which will display to the side
		var pos = this.element.getCoordinates();
		this.image = new Element('img',{
			src: '',
			styles: {
				'z-index': 100000,
				position: 'absolute',
				top: pos.top + this.options.offset.y,
				left: pos.left + pos.width + this.options.offset.x
			}
		}).inject(document.body);
		//workers and removers
		this.comparer = function(response) {
			this.cache[this.element.value] = response;
			var state = (response == '1') ? 'available' : 'taken';
			this.element.addClass(this.options[state + 'Class']);
			this.image.set('src',this.options[state + 'Image']);
			return state;
		};
		this.remover = function() {
			this.element.removeClass(this.options.availableClass).removeClass(this.options.takenClass);
		};
		//create the request which will be frequently used
		this.request = new Request({
			url: this.options.url,
			method: 'get',
			link: 'cancel',
			onRequest: this.remover.bind(this),
			onComplete: this.comparer.bind(this)
		});
		//add listener
		this.element.addEvent(this.options.trigger,function() {
			var value = this.element.value;
			if(value.length >= this.options.minLength && value != this.lastValue) {
				this.validate(this.lastValue = value);
			}
		}.bind(this));
	},
	
	//a method that does whatever you want
	validate: function(value) {
		this.fireEvent('check');
		if(this.cache[value] != undefined) {
			return this.comparer(this.cache[value]);
		}
		else {
			return this.request.send('username=' + value + '&ajax=1');
		}
		return this;
	}
	
});

//USAGE!
window.addEvent('domready', function() {
	var validator = new AvailabilityChecker('username',{
		trigger: 'keyup',
		availableImage: 'checkmark.jpg',
		takenImage: 'warning.jpg',
		offset: { x: 4, y: 4 },
		minLength: 4,
		url: '<?php echo $_SERVER["PHP_SELF"]; ?>'
	});
});

The original class featured a host of problems. No element was required, a new Request was being generated every keystroke, results weren't cached. Ugh. Those have all been fixed and I've added event functionality to the class. I've also implemented many new MooTools best practices.

I know the class doesn't feature many methods and still isn't ultimately flexible but the truth is that this type of widget can be very specific. What this class aims to accomplish to provide you with a basic class you can build from.

Recent Features

  • By
    Vibration API

    Many of the new APIs provided to us by browser vendors are more targeted toward the mobile user than the desktop user.  One of those simple APIs the Vibration API.  The Vibration API allows developers to direct the device, using JavaScript, to vibrate in...

  • By
    Camera and Video Control with HTML5

    Client-side APIs on mobile and desktop devices are quickly providing the same APIs.  Of course our mobile devices got access to some of these APIs first, but those APIs are slowly making their way to the desktop.  One of those APIs is the getUserMedia API...

Incredible Demos

Discussion

  1. A nice bit of code. Although in opera the (green) tick shows with the box still yellow for davidwal after showing the yellow with an exclamation mark as expected for davidw. Maybe its just slow to change I couldn’t seem to work it out.

  2. Thanks.
    Good Work.

  3. Isn’t this a bit of overkill for something so simple and straight forward?

  4. @Adriaan: I can’t respond without you qualifying that statement or submitting better code

  5. dailce

    Great work as always!

  6. @David: Don’t get me wrong, the code is solid and it’s probably best to use classes for anything you would reuse often, I’m just saying, that for something that would most likely only be used once on an entire site, it would be less code to just write a simple JSON request function that checks the value on keyup, and updates a result div or span.

    Your code is always pretty solid, so this is probably just nitpicking ;)

  7. dave

    Great work – just reiterating comments above regarding yellow/green.

    Using IE7, if you type “davidw” you get a yellow BG and associated icon. If you delete the “w” from “davidw”, the icon changes but the BG remains yellow.

    Just letting you know – otherwise very nice!

  8. hamburger

    Hi David,
    Great work. I’am using your old version without any problems but i think i have to move now to the newer one.
    To make your post complete may be you can also provide a .PHP – Sample?
    I’am sure that will be great for beginers.

  9. Alex

    You’ve already responded David ;)

  10. @dave: I noticed the same thing, I would recommend replacing the current add listener function with:

    //add listener
    this.element.addEvent(this.options.trigger,function() {
    	var value = this.element.value;
    	if(value.length >= this.options.minLength && value != this.lastValue) {
    		this.validate(this.lastValue = value);
    	}else{
    		if(this.element.hasClass(this.options.availableClass)){
    			this.element.removeClass(this.options.availableClass);
    		}else if(this.element.hasClass(this.options.takenClass)){
    			this.element.removeClass(this.options.takenClass);
    		}
    	}
    }.bind(this));
    

    @ Adrian I agree its a bit of overkill for username/email/whatever availability however it is always nice to have a toolkit with everything you need at your disposal :)

  11. FerJo

    I agree with that post that was asking for a PHP sample… It may be very simple, but without any idea of what it’s the format/data of the output of the php file…

    That would be SO appreciated ! ;)

  12. Save the below text as what ever you declare in this variable: url: ‘ajax-username-check.php’

    Replace your_table_name with the table name you are using.

    replace your_user_name_field with the field you are using.

    Don’t forget to include your database connection file or declare the database connection above the code.

    0){
    echo ‘0’;
    }else{
    echo ‘1’;
    }
    ?>

    There are so many ways to do this, the method above will be compatible with this script. No warranties implied just a very basic example use at your own risk.

  13. hmmm my code was parsed out…

    I think it may have been the opening PHP statement, make sure you open and close PHP

    $username = $_GET['username'];
    $sql = "SELECT * FROM your_table_name WHERE your_user_name_field='".mysql_real_escape_string($username)."'";
    $result = @mysql_query($sql);
    if(@mysql_num_rows($result)>0){
    echo '0';
    }else{
    echo '1';
    }
  14. Nice sample but I would be careful about sending each and every keystroke to the server to validate the username. Instead of sending each keystroke you can use the onblur event. Here is the article which I wrote:

    http://www.highoncoding.com/Articles/439_Performing_Instant_UserName_Availability_Check_Using_JQuery_Ajax_API.aspx

  15. @Mohammad,

    I agree you should probably check for the minimum length requirement. However displaying a message because it isn’t long enough while still in the field is a little overkill, maybe onblur. Then i would simply show the error class with the error reason.

    however if your site/server is having issues sending 2 or 3 extra ajax request, you should probably consider switching hosts.

  16. Stefan

    i keep getting that the username is unavailable (using tim wickstrom and own code) so dave please post yours :P

  17. Mark

    I’m looking at the listener.. if the number of characters entered into the field fall below the minLength, the graphic should be switched back to the default.

    I’ve added this and a blank image so safari doesn’t show a blank placeholder.

    //add listener	
    this.element.addEvent(this.options.trigger,function() {
    	var value = this.element.value;
    	if(value.length >= this.options.minLength && value != this.lastValue) {
    		this.validate(this.lastValue = value);
    	}else if(value.length < this.options.minLength ) {
    		this.image.set('src','src_images/blank.png');
    	}else{
    		if(this.element.hasClass(this.options.availableClass)){
    			this.element.removeClass(this.options.availableClass);
    		}else if(this.element.hasClass(this.options.takenClass)){
    			this.element.removeClass(this.options.takenClass);
    		}
    	}
    	
    }.bind(this));
  18. Clayton

    Hey, so I used the above php code and I can see in firebug that the response is “1” but the field keeps reverting to the taken class.

    Any ideas?

  19. Clayton

    Its ok I got it to work.

    I had to re-write a bit of the php script and then it took me awhile to notice the ” when creating the new object options.url.

  20. 123456

    This is tiwari si good .

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!