Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Slick vs. Sizzle: The CSS Selector Engine Battle

Javascript frameworks like MooTools and jQuery are used on most modern websites. CSS selector engines are one of the most useful and widely used features in these frameworks. Because of this, selector performance is extremely important for modern web applications.


Both MooTools and jQuery have built their own stand alone selector engines for use in their respective projects. MooTools uses the Slick selector engine and jQuery uses the Sizzle selector engine.


Surprisingly, there are very few performance comparisons out there for these two engines. Below are the results of a selector engine performance test between MooTools 1.3.2 and jQuery 1.6.2. The original code for this test came from this post and you can check out the source code on jsFiddle.



jQuery seems faster than MooTools for almost any type of selector. The one big exception is the ".note" selector, which also happens to be one of the most commonly used. Given that, the overall performance of a webapp between these two frameworks is somewhat up in the air.

Simple AJAX with jQueryUI and PHP

This will be a short tutorial on how to incorporate AJAX interaction into a PHP site using jQuery and the jQueryUI framework.


Imagine we have a page that lets users manage a list of books that is stored in a database.  We want them to be able to easily edit the books via ajax without having to go to another page. Below is an example of what we want.



Here's the database table we'll use plus a few sample books.


CREATE TABLE `books` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(30) NOT NULL,
  `genre` enum('fantasy','mystery','nonfiction') NOT NULL,
  `description` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE = InnoDB;

INSERT INTO `book` (`id`, `title`, `genre`, `description`) VALUES
(1, 'The Lord of the Rings', 'fantasy', 'The Lord of the Rings is an epic fantasy novel written by philologist and University of Oxford professor J. R. R. Tolkien (from Wikipedia).'),
(2, 'The Maltese Falcon', 'mystery', 'The Maltese Falcon is a 1930 detective novel by Dashiell Hammett, originally serialized in the magazine Black Mask (from Wikipedia).'),
(3, 'Economics in One Lesson', 'nonfiction', 'Economics in One Lesson is an introduction to free market economics written by Henry Hazlitt and published in 1946, based on Frédéric Bastiat''s essay Ce qu''on voit et ce qu''on ne voit pas (English: "What is Seen and What is Not Seen") (from Wikipedia).');


First, let's create the PHP page that pulls these books from the database and displays them to the user. Later, we'll add javascript code to this page to make the edit link use AJAX to interact with the database.

//display.php
<div class='books'>
 <?php
 //connect to database
 mysql_connect('localhost', 'mysql_user', 'mysql_password');
 mysql_select_db('dbname');

 //get all books
 $query = "SELECT * FROM books";
 $result = mysql_query($query) or die("Error selecting books");

 //display books
 while($row = mysql_fetch_assoc($result)) {
 ?>
  <div class='book' id='book_<?php echo $row['id']; ?>'>
   <a class='edit' href='#'>edit</a>
   <h3 class='title'><?php echo $row['title']; ?></h3>
   <p><em class='genre'><?php echo $row['genre']; ?></em></p>
   <p class='description'><?php echo $row['description']; ?></p>
  </div>
 <?php
 }
 ?>
</div>

The next page to create is the edit.php page that the ajax link will call.


//edit.php
<?php
//connect to database
mysql_connect('localhost', 'mysql_user', 'mysql_password');
mysql_select_db('dbname');

//pull info from $_POST and sanitize it
$id = mysql_real_escape_string($_POST['id']);
$title = mysql_real_escape_string($_POST['title']);
$genre = mysql_real_escape_string($_POST['genre']);
$description = mysql_real_escape_string($_POST['description']);

//update in database
$query = 'Update books SET title="'.$title.'", genre="'.$genre.'", description="'.$description.'" WHERE id="'.$id.'"';
mysql_query($query);

//generate json code
echo json_encode(array(
 'id'=>$id,
 'title'=>$title,
 'genre'=>$genre,
 'description'=>$description
));
?>

When the user clicks the edit link for a book, we want a dialog box to pop up with a form that lets the user edit the data. We want the form to submit to the edit.php page via AJAX. Finally, we want the page to update to reflect the changes.


To do this, we first create the html for the dialog box. The submit button will be handled by jQuery, so we don't need to add it here. This goes at the bottom of the display.php page.


<div id='edit_dialog'>
 <form action='edit.php' method='post'>
  <input type='hidden' name='id' />

  Title: 
  <input type='text' name='title' /><br />
  
  Genre:
  <select name='genre'>
   <option value='fantasy'>Fantasy</option>
   <option value='mystery'>Mystery</option>
   <option value='nonfiction'>Nonfiction</option>
  </select><br />
  
  Description:
  <textarea name='description' cols='30' rows='3'></textarea>  
 </form>
</div>

Now we add the jQuery code to the display.php page to tie everything together. This requires jQuery, jQueryUI with the dialog widget, and a jQueryUI theme to be loaded. This goes somewhere on the display.php page.


$(document).ready(function() {
 //Create dialog
 $edit_dialog = $("#edit_dialog").dialog({
  autoOpen:false, 
  title:"Edit Book", 
  modal:true, 
  buttons:[
   {text: "Submit", click: function() { $('form',$(this)).submit(); }},
   {text: "Cancel", click: function() { $(this).dialog("close"); }},
  ]
 });
 
 //Submit action for dialog form
 $("#edit_dialog form").submit(function() {
  var form = $(this);
  //post form data to form's action attribute
  $.post($(this).attr('action'), $(this).serialize(),function(data) {   
   //get DOM element of updated book
   var book = $('#book_'+data.id);
  
   //update title
   $('.title',book).html(data.title);
   
   //update genre
   $('.genre',book).html(data.genre);
   
   //update description
   $('.description',book).html(data.description);
  
   //close the dialog
   $("#edit_dialog").dialog('close');
  },'json');
  
  //stop default form submit action
  return false;
 });

 //when the edit link is clicked
 function edit_link_action() {
  //get closest book div
  var book = $(this).closest('.book');
  
  //get id from div
  var id = book.attr('id').split('_');
  id = id[id.length-1];
  
  //set id in form
  $('#edit_dialog input[name="id"]').val(id);
  
  //set current title in form
  $('#edit_dialog input[name="title"]').val($('.title',book).html());
  
  //set current genre in form
  $('#edit_dialog select[name="genre"]').val($('.genre',book).html());
  
  //set current description in form
  $('#edit_dialog textarea[name="description"]').val($('.description',book).html());
  
  //open dialog
  $edit_dialog.dialog('open');
  
  //stop default link action
  return false;
 }
 
 //attach action to edit links
 $(".edit").click(edit_link_action);
});

Once all the parts are put together, you should have a fully functioning AJAX site. Below is the complete code for the display.php page.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
 <script type='text/javascript' src='jquery-1.4.4.min.js'></script>
 <script type='text/javascript' src='jquery-ui-1.8.9.custom.min.js'></script>
 <link rel='stylesheet' href='jquery-ui-1.8.9.custom.css' />
 <script type='text/javascript'>
  $(document).ready(function() {
   //Create dialog
   $edit_dialog = $("#edit_dialog").dialog({
    autoOpen:false, 
    title:"Edit Book", 
    modal:true, 
    buttons:[
     {text: "Submit", click: function() { $('form',$(this)).submit(); }},
     {text: "Cancel", click: function() { $(this).dialog("close"); }},
    ]
   });
   
   //Submit action for dialog form
   $("#edit_dialog form").submit(function() {
    var form = $(this);
    //post form data to form's action attribute
    $.post($(this).attr('action'), $(this).serialize(),function(data) {   
     //get DOM element of updated book
     var book = $('#book_'+data.id);
    
     //update title
     $('.title',book).html(data.title);
     
     //update genre
     $('.genre',book).html(data.genre);
     
     //update description
     $('.description',book).html(data.description);
    
     //close the dialog
     $("#edit_dialog").dialog('close');
    },'json');
    
    //stop default form submit action
    return false;
   });

   //when the edit link is clicked
   function edit_link_action() {
    //get closest book div
    var book = $(this).closest('.book');
    
    //get id from div
    var id = book.attr('id').split('_');
    id = id[id.length-1];
    
    //set id in form
    $('#edit_dialog input[name="id"]').val(id);
    
    //set current title in form
    $('#edit_dialog input[name="title"]').val($('.title',book).html());
    
    //set current genre in form
    $('#edit_dialog select[name="genre"]').val($('.genre',book).html());
    
    //set current description in form
    $('#edit_dialog textarea[name="description"]').val($('.description',book).html());
    
    //open dialog
    $edit_dialog.dialog('open');
    
    //stop default link action
    return false;
   }
   
   //attach action to edit links
   $(".edit").click(edit_link_action);
  });
 </script>
</head>
<body>
 <div class='books'>
  <?php
  //connect to database
  mysql_connect('localhost', 'mysql_user', 'mysql_password');
  mysql_select_db('dbname');

  //get all books
  $query = "SELECT * FROM books";
  $result = mysql_query($query) or die("Error selecting books");

  //display books
  while($row = mysql_fetch_assoc($result)) {
  ?>
   <div class='book' id='book_<?php echo $row['id']; ?>'>
    <a class='edit' href='#'>edit</a>
    <h3 class='title'><?php echo $row['title']; ?></h3>
    <p><em class='genre'><?php echo $row['genre']; ?></em></p>
    <p class='description'><?php echo $row['description']; ?></p>
   </div>
  <?php
  }
  ?>
 </div>
 
 <div id='edit_dialog'>
  <form action='edit.php' method='post'>
   <input type='hidden' name='id' />

   Title: 
   <input type='text' name='title' /><br />
   
   Genre:
   <select name='genre'>
    <option value='fantasy'>Fantasy</option>
    <option value='mystery'>Mystery</option>
    <option value='nonfiction'>Nonfiction</option>
   </select><br />
   
   Description:
   <textarea name='description' cols='30' rows='3'></textarea>  
  </form>
 </div>
</body>
</html>

Reducing Javascript and CSS Load Times

I was making a complex ajax web application and ran into problems with load times. In some cases, it was taking up to 7 or 8 seconds to load a page. I found out the culprit was multiple large javascript and css files. Here's how I was able to get my load times under a second with a few changes. All of the examples below are for javascript files, but they apply equally to css files.

Combine javascript and CSS files

There is overhead each time the browser has to load an external file, so reducing the number of server calls can speed up page loads. Originally, I put all of my javascript scripts in one large file. This helped page load times, but made it difficult to edit individual scripts. I then switched to a PHP solution.

I created the following PHP page, which combines multiple javascript files on the fly.

<?php
//set content type
header('Content-type: text/javascript');

//pull list of comma-separated files from $_GET
$js_files = explode(',',urldecode($_REQUEST['files']));

//read each file
foreach($js_files as $js_file) {
 echo "\n\n\n/*******************$js_file********************/\n";
 $file = '/path/to/js/directory/'.$js_file.".js";
 if(file_exists($file)) readfile($file);
}
?>

Here is how you would load javascript files in the head section of page.

<!-- Using PHP's urlencode function -->
<?php
$files = array("jsfile1","jsfile2","jsfile3");
?>
<script type='text/javascript' src='/path/to/js/directory/javascript.php?files=<?php
 echo urlencode(implode(',',$files));
?>'></script>

<!-- No PHP, hard code commas as "%2C" -->
<script type='text/javascript' src='/path/to/js/directory/javascript.php?files=jsfile1%2Cjsfile2%2Cjsfile3'></script>

This reduced my load times to about 5 or 6 seconds.

Take Advantage of Parallel Downloading

This partially contradicts the previous tip when I said less files were always better. Most browsers are capable of downloading a limited number of javascript and css files at the same time. For example, Firefox will usually download up to 3 files simultaneously from a single host.

If you have 1 or 2 large javascript files, you should put them in their own script tags and combine the rest of the scripts as before. This way, the browser doesn't have to wait for the large script to download before fetching the other ones. Here's an example.

<!-- Large js file -->
<script type='text/javascript' src='/path/to/js/directory/javascript.php?files=largefile'></script>

<!-- Multiple smaller files -->
<script type='text/javascript' src='/path/to/js/directory/javascript.php?files=jsfile1%2Cjsfile2%2Cjsfile3'></script>

Even though you are only loading one file in the first case, you should still use the php script to take advantage of the later tips.

This reduced my load times further to about 2 or 3 seconds.

Compress Javascript and CSS files

The basic idea behind this is to reduce the size of javascript and css files by removing comments and extra white spaces among other things. There are two ways to do this, each with their advantages and disadvantages.

The first is to compress the files directly. The advantages here are speed and reduced server load. The server doesn't have to waste time compressing each file at runtime. The big disadvantage is that compressed files are almost impossible to edit. This method works best for 3rd party scripts, such as javascript frameworks, that you aren't going to be editing yourself. Most frameworks offer compressed versions directly, but you can also compress any file yourself with http://jscompress.com/ for javascript files and http://www.cssdrive.com/index.php/main/csscompressor/ for css files.

The other method is realtime compression. The advantage is files remain editable and the development process is much easier. The disadvantage is that the server must re-compress each script at runtime, which takes time and processing power. This method is best for scripts which you edit often. There is a great php script for doing this called minify that works for js and css files. They have plenty of documentation on the site and it's pretty easy to implement into the php script we created above.

Compressing files can reduce the size by anywhere from 10% to 50% or more. As an example, the uncompressed jquery framework is 160kb and the compressed version is 70kb. This can potentially cut loading times in half, but the actual gain is probably less than that.

Take Advantage of Caching

A lot of times, javascript and css files don't change very often and it doesn't make sense to load them on each page view. With a few simple changes to our php script, we can make the browser cache these pages. This provides the biggest improvement in load times.

<?php
//set content type
header('Content-type: text/javascript');

//if the nocache parameter is not explicitly set
if(!$_REQUEST['nocache']) {
 //store in cache for 1 day (86400 seconds)
 header('Expires: '.gmdate('D, d M Y H:i:s', time()+86400).'GMT');  
 header('Cache-Control: max-age=86400'); 
 header('Pragma: max-age=86400'); 
}

...

If you have some file which changes frequently or is generated at the server side, you can pass "nocache=true" in the script tag source.

One problem you may notice is that if you make a change to a javascript file, a user may not get the latest version for a full day, which could break the site in the meantime. Luckily, there is an easy solution.

If the script src changes, a browser will always reload the script, even if it was cached. Since we're already passing parameters in the script url, we can add "version=#" and increment this number whenever we make a change. That way, the script will be reloaded the next time the page is.

The first time the webpage is loaded, there is no added benefit, but the load times of subsequent pages was reduced to less than a second.

If you can think of any other tips to reduce page load times, let me know.

Fixing jQuery UI Autocomplete

jQuery UI 1.8 was recently released and it included a much needed autocomplete widget. For the most part, this widget works fine, but there is an annoying bug that makes it not quite ready for a production environment. Basically, if a user clicks on an option and doesn't release the mouse button fast enough, the option is not selected. You can see the bug in action on the jQuery UI autocomplete demo.

Thankfully, there is a workaround.

Here is what we would like to be able to do:

$("#autocomplete").autocomplete({
   source: 'search.php',
   select: function(event, ui) {
      alert(ui.item.id);
   }
});

Here is the bug-fixed version I came up with:

//global variable that stores the last focused option
var search_option = false;

$("#autocomplete").autocomplete({
   source: 'search.php',
 
   //when an item is focused, store item in the global variable
   focus: function(event, ui) {
      search_option = ui.item;
   },
 
   //when an item is selected with the keyboard, trigger
   //the mouse down event for consistency
   select: function(event, ui) {
      search_option = ui.item;
      $("#autocomplete").autocomplete('widget')
      .trigger('mousedown.choose_option');
   }
})

//bind the select event to mousedown
.autocomplete('widget').bind('mousedown.choose_option',function() {
   //immediately closes autocomplete when option is selected
   $("#autocomplete").autocomplete('close');
 
   //perform desired action
   alert(search_option.id);
});

Obviously, this isn't a very elegant solution, but I didn't want to mess around with the actual autocomplete code. Hopefully, this is fixed in the next release. Until then, this will have to do.

My Experience with JQuery

I had a project recently where I needed to make an online contact management website with similar functionality to Outlook and ACT!.

I wrote all the javascript from scratch for the first version of the site. I ended up writing over 1000 lines of code to add various features, such as ajax search, autocomplete, input masking, and security.

The code was getting too complex to manage so I decided to look for an alternative. I came across several javascript libraries, including mootools and YUI. I tried each of these, but the learning curve was too steep. I would spend hours just trying to implement a simple feature. This ended up being worse than my custom code.

The next library I tried was jQuery. At first this looked just as bad as the others, but after fooling around with it for a few hours, I fell in love. The language is very simple to understand. It all consists of a single $() function that replaces and improves document.getElementById(). Here are some examples.

//Select the element with id "test"
$("#test")
//Select elements with a class of "style1"
$(".style1")
//Select all <p> and <blockquote> tags
$("p, blockquote")
//Select all input fields inside of a form
$("form input")

Most selections that works in CSS work with the $() function. All jQuery functions start with a selection like this. Different functions are chained together after this to perform tasks. For example:

//Change the color of all <p> tags to red and 
//add the word "hello" to the end of each.
$("p").css('color','red').append('hello');

In the previous example, this paragraph would turn into:

In the previous example, this paragraph would turn into:hello

The built-in functions can acomplish a lot, but the real power of jQuery comes from the plugins. jQuery is one of the few frameworks that completely supports 3rd part plugins. Some common ones add things like tabs, accordions, autocomplete, tooltips, rich text editing, and so on.

All you need to use one of these plugins is to include the script. Here's an example using the tooltips plugin.

<script type='text/javascript' src='jquery.js'></script>
<script type='text/javascript' src='jquery.tooltips.js'></script>
<script type='text/javascript'>
//Add a tooltip to every element with class 'tooltip'
$(".tooltip").tooltip();

//Add a tooltip with custom options
$(".custom").tooltip({ 
    track: true, //follow the mouse
    delay: 0, //show tooltip instantly
    fade: 250 //fade tooltip out
});
</script>

Here's a list of the plugins I used for my contact management site:

  • Meio Mask - This conforms entered input to a specified format or "mask". For example, if you enter a phone number, no matter how you enter it, it will always look like "(123) 456 - 7890". I used this to standardize entered data and to make searching easier.
  • Tooltip - This plugin lets you add tooltips to any element. They can be anywhere from simple text to advanced layouts with images. I used this on any icons to provide a nice user interface.
  • Autocomplete - Provides an easy way to add autocomplete fields to your site. I used this for my ajax search and to suggest city and country names to reduce misspellings and standardize data.
  • Editable Combo Box - This lets you type your own value in a select box. I used this along with some server side scripting to allow users to easily add options to drop down menus.
  • Date Picker - This creates pop-up calendars for entering dates. I used this on all my date fields to provide an alternate way to enter data.
  • Tabs - This creates an element with tabs containing different content. I used this to fit more information in a single place.

The uncompressed jQuery framework with these plugins is close to 200kb. This is a little much to load for every page. Luckily, there are ways to reduce the size by more than half. The easiest way is to use the Javascript Minifier. This removes all comments and unnecessary spaces and linefeeds.

Using Javascript with Textfields

I'm going to look at different ways to manipulate textboxes using javascript. All of these examples are things I've had to use for various projects.

Here's what I'll cover:

  • Selecting text on focus
  • Creating a live preview
  • Keyboard shortcuts (ie. ctrl+b to bold text)
  • Advanced macros

Selecting Text On Focus

Let's start with the easy one. Here's the scenario: you have HTML code in a textbox that you want people to copy and paste. When the user clicks the textbox, the text should be highlighted.

<textarea onFocus='this.select();'>Click to select</textarea>
Example:

Creating a Live Preview

Here's the scenario: You allow users to create their own html template. You want them to see a live preview of the rendered HTML code as they type.

First, the javascript.

//Puts html in the preview pane
function updatePreview(html) {
  //Get preview element
  target = document.getElementById('preview');
  //Replace element's contents with passed text
  target.innerHTML = html;
}

Now, the html.

<!--Text area that user types in-->
<textarea onKeyUp='updatePreview(this.value);'></textarea>

<!--Element where preview is displayed-->
<div id='preview'></div>
Example:
Preview
No Text
Type HTML code here:

Keyboard Shortcuts

Here's the scenario: When a user fills out a textbox, you want their progress to be saved when they hit ctrl+s (Control + S), the standard keyboard shortcut for "save".

To actually save the data to a database, Ajax is required. I may get to this in a later tutorial, but for now, I'll assume you have a javascript function "saveData()" that does this. Here's the javascript.

//Find out which key is pressed
function interpretKey(e) {
  //Get window event (handle different browsers)
  e = (e) ? e : window.event;

  //Get key code (handle different browsers)
  key = (e.keyCode) ? e.keyCode : event.which;
  
  if(e.ctrlKey) //Control Key is pressed
    if(key==83) //S key is pressed
      saveData(); //Save the data
}

And here's the HTML.

<textarea onKeyDown='interpretKey(event);'></textarea>
Example:

Advanced Macros

A macro is a function that performs several tasks. They are often used to automate actions that humans repeatedly perform. I'm going to use the keyboard shortcuts we just made to preform macros.

Let's say you often type the following skeleton for an HTML file in a textfield:

<html>
<head>
  <title>title</title>
</head>

<body>

</body>
</html>

You want to automate this so you don't have to type it every time. Let's make the keyboard shortcut "Alt+1" type this for you.

First, the javascript.

//Define array of macros
var macros = new Array;

//Define first macro
macros[0] = {
  //Name of macro
  "name":
    "HTML Skeleton",
  //Key that triggers Macro
  "key":
    49, // "1" key
  //Text to insert into textbox
  "text": 
    "<html>\n"+
    "<head>\n"+
    "  <title>title</title>\n"+
    "</head>\n"+
    "<body>\n\n</body>\n"+
    "</html>",
  //Where to place cursor after inserting (from start of insert)
  "cursor_offset":
    52 //Places cursor 52 characters from start (Between the <body> tags)
};
function handleMacro(e) {
  //Get window event (handle different browsers)
  e = (e) ? e : window.event;

  //Get key code (handle different browsers)
  key = (e.keyCode) ? e.keyCode : event.which;
  
  if(e.altKey) { //Alt Key is pressed, check for macros
    for(i=0;i<macros.length;i++) {
      if(macros[i].key == key) { //One of the macros matches the key pressed
        //Do the macro
        addText01(macros[i].text,macros[i].cursor_offset);
    }
  }
  }
}
function addText01(text,offset) {
  //Get textbox element
  textbox = document.getElementById("textbox");
  
  //Get current cursor position.  This is where the text will be inserted.
  cursorPosition = getCursorPosition(textbox);
  if(cursorPosition==-1)
    return false;
  
  //Get the current text in the textbox
  currentText = textbox.value;
  
  //Generate new value with new text inserted
  newText = currentText.substr(0,cursorPosition) + text + currentText.substr(cursorPosition);
  textbox.value = newText;
  
  //Get the new cursor position
  if(offset || offset=='0') //Offset defined
    newCursorPosition = offset;
  else
    newCursorPosition = text.length;
    
  //Set the new cursor position
  setCursorPosition(textbox,cursorPosition+newCursorPosition);
  
  return true;
}
function getCursorPosition(node) {
//Firefox support
  if(node.selectionStart) return node.selectionStart;
//Catch Exception (unsupported browser)
  else if(!document.selection) return 0;
//IE support
    //Define character to search for
  var c = "\001";
  //Create empty range
  var sel  = document.selection.createRange();
  //Duplicate range
  var dul  = sel.duplicate();
  var len  = 0;
  //Move duplicate range to node
  dul.moveToElementText(node);
  //Set selected value to character
  sel.text = c;
  //Search for character
  len  = (dul.text.indexOf(c));
  //Delete character
  sel.moveStart('character',-1);
  sel.text = "";
  //Return character position
  return len;
}
function setCursorPosition (node, pos) {
// Firefox support
  if (node.selectionStart || node.selectionStart == '0') {
    node.selectionStart = pos;
    node.selectionEnd = pos;
    return;
  }
  
// IE Support
    // Create empty selection range
  var sel = document.selection.createRange ();
  // Move selection start and end to 0 position
  sel.moveStart ('character', -node.value.length);
  // Move selection start and end to desired position
  sel.moveStart ('character', pos);
  sel.moveEnd ('character', 0);
  sel.select ();
}

Now for the HTML.

<textarea id='textbox' onKeyDown='handleMacro(event);'></textarea>

Using this technique, you can easily define multiple macros. For a list of javascript key codes, check out http://www.cambiaresearch.com/c4/702b8cd1-e5b0-42e6-83ac-25f0306e3e25/Javascript-Char-Codes-Key-Codes.aspx

Example:

AJAX Form Validation

Many sites today validate form inputs as the user types. These validations are usually simple, like checking if a username is available, but contribute to a great user interface. I'm going to walk through how to do this with PHP and AJAX, and the advantages and disadvantages.

I'm going to make a simple form with two inputs, a username and a password. I'm then going to validate the inputs as the user types using 2 different methods.

Let's start with the form.

<html>
<head>
  <title>Form</title>
</head>
<body>
<form>
  Username:
  <input type='text' id='username' />
  <br />Password:
  <input type='password' id='password' />
</form>
</body>
</html>

The first field we'll validate is the password field. We'll create a validatePassword() javascript function that makes sure the password is at least 6 characters long.

<script type='text/javascript'>
function validatePassword() {
  var field = document.getElementById('password');

  var test = true;

  //If password is less than 6 characters
  if(field.value.length < test =" false;" backgroundcolor =" 'green';" backgroundcolor =" 'red';">

Now we need to add a keyup event to our password input.

<input type='password' id='password'
onKeyUp='validatePassword();' />

Now we are going to validate the username by making sure it's available. We can't do this just using javascript since we have to check a database, so we use AJAX and PHP instead. Here's the php page (validateUsername.php).

<?php
//include mysql config file
include 'mysql.php';

//get passed username
$username = $_REQUEST['username'];

//sanitize passed username
$username = mysql_real_escape_string($username);

//make sure username is not empty
if(empty($username))
  exit("false");

//query the database for matches
$query = "SELECT id FROM users WHERE username='$username'";
$return = mysql_query($query) or
  die ("Error getting matches: " . mysql_error());

//If a match exists, return false, else return true
if(mysql_num_rows($return)>0)
  echo 'false';
else
  echo 'true';
?>

If the username 'jsmith' is already taken, validateUsername.php?username=jsmith would output 'false'. Otherwise it would output 'true'. Now we need ajax to interact with this page. I'm going to use Prototype for the ajax to make the code easier to understand.

<script type='text/javascript' src='prototype-1.6.0.2.js'></script>
<script type='text/javascript'>
function validateUsername()
{
  //get username input
  var field = document.getElementById('username');

  //Don't use ajax if username is empty
  if(field.value.length == 0)
  {
    field.style.backgroundColor = 'red';
    return;
  }

  //Initialize new ajax request
  new Ajax.Request('validateUsername.php', {
    method: 'get',
    parameters: {
      username: field.value
    },
    //If a response is sent back
    onSuccess: function(transport){
      //get response text
      var response = transport.responseText;

      if(response=='true') //validation passed
        field.style.backgroundColor = 'green';
      else //validation failed
        field.style.backgroundColor = 'red';
    }
  });
}
</script>

Once again we need to add a keyup event to our input.

<input type='text' id='username'
onKeyUp='validateUsername();' />

Now we have all out parts. Before I put it all together and show you a demo, understand that validating a form with Ajax should be the last resort. The only time you should use Ajax is if you must interact with a database. Anything else is unnecessary load on your servers. I do feel, however, that using Ajax where needed is well worth the server load.

Here is a link to a demo. Below is the complete source of the html page. The php source is above.

<html>
<head>
  <title>Form</title>

  <script type='text/javascript'>
  function validatePassword() {
    var field = document.getElementById('password');

    var test = true;

    //If password is less than 6 characters
    if(field.value.length < 6)
   test = false;

    if(test) //validation passed
    {
     //Change input background green
     field.style.backgroundColor = 'green';
    }
    else  //Validation failed
    {
   //Change input background red
   field.style.backgroundColor = 'red';
    }
  }
  </script>
  <script type='text/javascript' src='prototype-1.6.0.2.js'></script>
  <script type='text/javascript'>
  function validateUsername()
  {
    //get username input
    var field = document.getElementById('username');

    //Don't use ajax if username is empty
    if(field.value.length == 0)
    {
      field.style.backgroundColor = 'red';
      return;
    }

    //Initialize new ajax request
    new Ajax.Request('validateUsername.php', {
      method: 'get',
      parameters: {
        username: field.value
      },
      //If a response is sent back
      onSuccess: function(transport){
        //get response text
        var response = transport.responseText;
 
        if(response=='true') //validation passed
          field.style.backgroundColor = 'green';
        else //validation failed
          field.style.backgroundColor = 'red';
      }
    });
  }
  </script>
</head>
<body>
<form>
  Username:
  <input type='text' id='username'
onKeyUp='validateUsername();' />
  <br />Password:
  <input type='password' id='password'
onKeyUp='validatePassword();' />
</form>
</body>
</html>