Yahoo! User Interface library(YUI)

December 18, 2008

AJAX

«»

A Login System Fronted by YUI

In our fi rst Connection example we looked at a simple GET request to obtain a remote XML fi le provided by the BBC. In this example, let’s look at the sending, or Posting of data as well.

W e can easily create a simple registration/login system interface powered by the Connection utility. While the creation of session tokens or a state-carrying system is beyond the scope of this example, we can see how easy it is to pass data to the server as well as get data back from it.

Again, we’ll need to use a full web server set up, and this time we can also include a mySQL database as the end target for the data posted to the server. You’ll probably want to create a new table in the database for this example.

In order to focus just on the functionality provided by the YUI, our form will have no security checks in place and data entered into the form will go directly into the database. Please do not do this in real life!

Security in a live implementation should be your primary concern and any data that goes anywhere near your databases should be validated, double-checked, and then validated again if possible, and some form of encryption is an absolute must. The MD5 hashing functions of PHP are both easy to use and highly robust.

Create a new table in your database using the mySQL Command Line Interface and call it users or similar. Set it up so that a describe request of the table looks like that shown in the screenshot overleaf:

For the example, we’ll need at least some data in the table as well, so add in some fake data that can be entered into the login form once we’ve fi nished coding it. A couple of records like that shown in the fi gure below should suffi ce.

Sta rt off with the following basic web page:


	<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
					"http://www.w3.org/TR/html4/strict.dtd">
	<html lang="en">
	   <head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8">
		<title>Yui Connection Manager Example 2</title>
		<script type="text/javascript" src="images/2008/12/yahoo/yui/yahoo-dom-event.js"></script>
		<script type="text/javascript" src="images/2008/12/yahoo/yui/connection-min.js"></script>
	   </head>
	   <body>
		<form id="signin" method="get" action="#">
		    <fieldset>
			<legend>Please sign in!</legend>
			<label>Username</label><input type="text" id="uname" name="uname">
			<label>Password</label><input type="password" id="pword" name="pword">
			<button type="button" id="login">Go!</button>
			<button type="reset">Clear</button>
		    </fieldset>
		</form>
		<form id="register" method="post" action="#">
		    <fieldset>
			<legend>Please sign up!</legend>
			<label>First name:</label><input type="text" name="fname">
			<label>Last name:</label><input type="text" name="lname">
			<label>Username:</label><input type="text" name="uname">
			<label>Password:</label><input type="password" name="pword">
			<button type="button" id="join">Join!</button>
			<button type="reset">Clear</button>
		    </fieldset>
		</form>
	   </body>
	</html>

The <head> section of the page starts off almost exactly the same as in the previous example, and the body of the page just contains two basic forms. I won’t go into specifi c details here. The mark up used here should be more than familiar to most of you. Save the fi le as login.html.

We can also add some basic styling to the form to ensure that everything is laid out correctly. We don’t need to worry about any fancy, purely aesthetic stuff at this point, we’ll just focus on getting the layout correct and ensuring that the second form is initially hidden.

In a new page in your text editor, add the following CSS:


	fieldset {
	   width:250px;
	   padding:10px;
	   border:2px solid lightblue;
	}
	label {
	   margin-top:3px;
	   width:100px;
	   float:left;
	}
	input {
	   margin-top:2px;
	   *margin-top:0px;
	}
	button {
	   float:right;
	   margin:5px 3px 5px 0px;
	   width:50px;
	}
	#register {
	   display:none;
	}

Save the fi le as login.css and view it in your browser. The code we have so far should set the stage for the rest of the example and appear as shown in the fi gure below:

Now let’s move on to the real nuts and bolts of this example—the JavaScript that will work with the Connection Manager utility to produce the desired results. Directly before the closing </body> tag, add the following <script>:


	<script type="text/javascript">
	   //create namespace object
	   YAHOO.namespace("yuibook.login");

	   //define the submitForm function
	   YAHOO.yuibook.login.submitForm = function() {
	     //have both fields been completed?
	     if (document.forms[0].uname.value == "" ||
		document.forms[0].pword.value == "") {
		alert("Please enter your username AND password to login");
		return false;
	     } else {
		//define success handler
		var successHandler = function(o) {
		   alert(o.responseText);

		   //if user not found show register form
		   if (o.responseText == "Username not found") {
			YAHOO.util.Dom.setStyle("register", "display", "block");
			document.forms[0].uname.value = "";
			document.forms[0].pword.value = "";
		   }
	        }
	   	//define failure handler
		var failureHandler = function(o) {
		   alert("Error " + o.status + " : " + o.statusText);
		}
	   	//define callback object
	   	var callback = {
		   success:successHandler,
		   failure:failureHandler
		}
		//harvest form data ready to send to the server
		var form = document.getElementById("signin");
		YAHOO.util.Connect.setForm(form);

		//define a transaction for a GET request
		var transaction = YAHOO.util.Connect.asyncRequest("GET", "login.php", callback);
	     }
	   }
	   //execute submitForm when login button clicked
	   YAHOO.util.Event.addListener("login", "click", YAHOO.yuibook.login.submitForm);
	</script>

We use the Event utility to add a listener for the click event on the login button. When this is detected the submitform() function is executed. First of all we should check that data has been entered into the login form. As our form is extremely small, we can get away with looking at each fi eld individually to check the data has been entered into it.

Don’t forget that in a real-world implementation, you’d probably want to fi lter the data entered into each fi eld with a regular expression to check that the data entered is in the expected format, (alphabetical characters for the fi rst and last names, alphanumerical characters for the username, and password fi elds).

Provided both fi elds have been completed, we then set the success and failure handlers, the callback object and the Connection Manager invocation. The failure handler acts in exactly the same way as it did in the previous example; the status code and any error text is alerted. In this example, the success handler also sends out an alert, this time making use of the o.responseText member of the response object as opposed to responseXML like in the previous example.

If the function detects that the response from the server indicates that the specified username was not found in the database, we can easily show the registration form and reset the form fi elds.

Next, we defi ne our callback object which invokes either the success or failure handler depending on the server response. What we have so far is pretty standard and will be necessary parts of almost any implementation involving Connection.

Following this we can make use of the so far unseen .setForm() method. This is called on a reference to the fi rst form. This will extract all of the data entered into the form and create an object containing name:value pairs composed of the form fi eld’s names and the data entered into them. Please note that your form fi elds must have name attributes in addition to id attributes for this method to work.

Once this has been done, we can initiate the Connection Manager in the same way as before. Save the HTML page as login.html or similar, ensuring it is placed into a content-serving directory accessible to your web server.

As you can see the .setForm() method is compatible with GET requests. We are using the GET method here because at this stage all we are doing is querying the database rather than making physical, lasting changes to it. We’ll be moving on to look at POST requests very shortly.

Now we can look briefl y at the PHP fi le that can be used to process the login request. In a blank page in your text editor, add the following code:


	<?php
	   $host = "localhost";
	   $user = "root";
	   $password = "mypassword";
	   $database = "mydata";
	   $uname = $_GET["uname"];
	   $pword = $_GET["pword"];
	   $server = mysql_connect($host, $user, $password);
	   $connection = mysql_select_db($database, $server);
	   $query = mysql_query("SELECT * FROM users WHERE username LIKE '$uname%'");
	   $rows = mysql_num_rows($query);
	   if ($rows != 0)
	   {
		$row = mysql_fetch_array($query);
		$pass = $row['password'];
		if ($pass != $pword)
		   echo "Password incorrect";
		else
		   echo "Hello ".$row['firstname'].", thanks for signing in";
	   }
	   else
	   {
		echo "Username not found";
	   }
	   mysql_close($server);
	?>

Here we set up the variables required to query our database and then extract any records where the username entered into our form matches the username associated with a user. There should only be one matching record, so we can then compare the stored password with that entered into our form.

All we’re doing here is passing back an appropriate message to be displayed by our successHandler function back in the HTML page. Normally, after entering the correct credentials, the visitor would be redirected to their account page or some kind of personal home page, but a simple alert gives us everything we need for this example. Save the above fi le as login.php in the same directory as the web page and everything should be good to go.

Try it out and refl ect upon the ease with which our task has been completed. Upon entering the username and password of one of our registered users, you should see something similar to the fi gure below:

So that covers GET requests, but what about POST requests? As I mentioned before, the .setForm() method can be put to equally good use with POST requests as well. To illustrate this, we can add some additional code which will let unregistered visitors sign up.

Add t he following function directly before the closing </script> tag:


	//define registerForm function
	   YAHOO.yuibook.login.registerForm = function() {
		//have all fields been completed?
		var formComp = 0;
		for (x = 1; x < document.forms[1].length; x++) {
		   if (document.forms[1].elements[x].value == "") {
			alert("All fields must be completed");
			formComp = 0;
			return false;
		   } else {
			formComp = 1;
		   }
		}
		if (formComp != 0) {
		   //define success handler
		   var successHandler = function(o) {
		     	//show succes message
		     	alert(o.responseText);
		   }
		   //define failure handler
		   var failureHandler = function(o) {
			alert("Error " + o.status + " : " + o.statusText);
		   }
		   //define callback object
			var callback = {
			   success:successHandler,
			   failure:failureHandler
			}
			//harvest form data ready to send to the server
			var form = document.getElementById("register");
			YAHOO.util.Connect.setForm(form);
			//define transaction to send stuff to server
			var transaction = YAHOO.util.Connect.asyncRequest(
			"POST", "register.php", callback);
		}
	   }
	   //execute registerForm when join button clicked
	   YAHOO.util.Event.addListener("join", "click",
			YAHOO.yuibook.login.registerForm);

In the same way that we added a listener to watch for clicks on the login button, we can do the same to look for clicks on the join button. Again we should check that data has been entered into each fi eld before even involving the Connection Manager utility. As there are more fi elds to check this time, it wouldn’t be effi cient to manually look at each one individually.

We use a for loop and a control variable this time to cycle through each form field; if any fi eld is left blank the formComp control variable will be set to 0 and the loop will exit. We can then check the state of formComp and provided it is not set to 0, we know that each fi eld has been fi lled in.

The success and failure handlers are again based on simple alerts for the purpose of this example. We again use the .setForm() method to process the form prior to sending the data. We can then proceed to initiate the Connection Manager, this time supplying POST as the HTTP method and a different PHP fi le in the second argument of the .asyncRequest() method.

All we need now is another PHP fi le to process the registration request. Something like the following should suffi ce for this example:


	<?php
	   $host = "localhost";
	   $user = "root";
	   $password = "mypassword";
	   $database = "mydata";
	   $fname = $_POST["fname"];
	   $lname = $_POST["lname"];
	   $uname = $_POST["uname"];
	   $pword = $_POST["pword"];
	   $server = mysql_connect($host, $user, $password);
	   $connection = mysql_select_db($database, $server);
	   $query = mysql_query("INSERT INTO users VALUES ('$fname', '$lname', '$uname', '$pword')");
	   echo "Thanks for joining us ".$fname;
	   mysql_close($server);
	?>

As we’re using POST this time, we can use the $_POST superglobal to pull our values out, and can then run a simple INSERT query to add them to the database. Upon entering an unrecognized name into the fi rst form, the registration form should then be displayed, as in the following screenshot:

If you register a new user now and then take a look at your database with the mySQL Command Line Client, you should see the new data appear in your database:

Summary

The YUI Connection Manager utility provides an almost unequalled interface to AJAX scripting methods used today among the many JavaScript libraries available. It handles the creation of a cross-platform XHR object and provides an easy mechanism for reacting to success and failure responses among others.

It handles common HTTP methods such as GET and POST with equal ease and can be put to good use in connection (no pun intended) with a PHP (or other form of) proxy for negotiating cross-domain requests.

What you will learn from this book

  • Explore the YUI Library—utilities, controls, core files, and CSS tools
  • Install the library and get up and running with it
  • Handle DOM manipulation and scripting
  • Get inside Event Handling with YUI
  • Create consistent web pages using YUI CSS tools
  • Work with Containers—implementation, skinning, adding transitions, and tabs
  • Debug, maintain, and update applications with the Logger control
  • Examples included in the book:
    • Calendar interface
    • Autocomplete
    • Creating panels
    • Dialogs
    • Custom tooltips
    • Forms
    • Split button
    • TreeView Control
    • Browser History Manager with Calendar
    • Simple animation
    • Custom animation
    • Creating tabs and adding content dynamically
    • Dragging and dropping
    • Implementing sliders
    • Logger at work
    • Logging custom classes

More details about YUI Book

The Yahoo! User Interface (YUI) Library is a set of utilities and controls, written in JavaScript, for building richly interactive web applications using techniques such as DOM scripting, DHTML, and AJAX. The YUI Library also includes several core CSS resources. All components in the YUI Library have been released as open source under a BSD license and are free for all uses.

This book covers all released components whether utility, control, core file, or CSS tool. Methods of the YAHOO Global Object are used and discussed throughout the book.

The basics of each control will be presented, along with a detailed example showing its use to create complex, fully featured, cross-browser, Web 2.0 user interfaces.

Besides giving you a deep understand of the YUI library, this book will expand your knowledge of object-oriented JavaScript programming, as well as strengthen your understanding of the DOM and CSS.

You will learn to create a number of powerful JavaScript controls that can be used straight away in your own applications.

email

«»

Comments

comments