Introduction
While I'm normally associated with Silverlight and WPF development, I do occasionally journey across the divide into developing more standard web based applications. For many years, I hand crafted JavaScript code and built up the usual library of browser checks, hacks and workarounds to try to develop websites that worked the same in Internet Explorer as they did in Firefox, Safari and the likes. About 18 months ago, I was introduced to the joys of jQuery and I haven't looked back when working with JavaScript.
"So Pete. Why do you like jQuery so much?" I hear you asking (you may not know you're asking, but you are). Well, according to the jQuery homepage:
"jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript."
If that was all there was to jQuery, then I'd be impressed, but there's more. It is highly extensible, and there is a rich community infrastructure of developers creating plugins and extensions for all sorts of features. If you want to show a datepicker, no problem. Want to display a draggable item? No problem.
In this article, I'm going to take us on a whirlwind tour of jQuery and hopefully help you get a better understanding of what it is and how it can be used.
Getting Started
Obviously, we can't develop the code we want against jQuery if we haven't downloaded it. The latest version can be found here (I'm currently using version 1.4.4). There is a minified version of the library which you may consider using when you deploy the website because it has been heavily compressed, but I would recommend initially installing the uncompressed version so that you can step into it and get a better understanding of it when you are debugging.
Note: Don't look to use the packed version of the library. This is a compressed version which has to be uncompressed at the client side, which will add significant overhead to the load time.
Once it's downloaded, we need to copy it into our website and add references to it. I typically like to organise my folders to have a top level js folder in the website, with jQuery being deployed in a subdirectory of this. Assuming you want to follow this convention, you'd add a reference to jQuery into a website page using:
<script src="js/jQuery/jquery-1.4.4.js" type="text/javascript"></script>
With this in place, we're ready to start using jQuery.
Jumping In At the Deep End
In our first example, we're going to use events and animation to see just how easy jQuery is. First of all, let's take a look at the code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" >
<head>
<title>First jQuery Sample</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="./js/jQuery/jquery-1.4.4.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#animateHide").click(function(){
$("#para1").hide('slow');
$("#para1").show('slow');
});
$("#justHide").click(function()
{
$("#para1").hide();
});
});
</script>
</head>
<body>
<p><span id="para1">Hello there</span></p>
<button type="button" id="animateHide">Animate hide</button>
<button type="button" id="justHide">Just hide</button>
</body>
</html>
So, What Does This Do, and How Does it Work?
In this sample, we've added two buttons that are going to hide the span. One of the buttons animates the hide so that the span disappears (and then reappears when the element has completed the hide operation). The second button just hides the element, which is equivalent to setting its CSS display to none.
One thing that may surprise you here is that we don't have an onclick in either of the button definitions, yet if you click on the buttons in the web page, they do respond to the click event. How do they do that?
If we take a look at the header, we see a section that starts with $(document).ready(function() {
. This section is really important, and it introduces us to our first bit of actual jQuery. The $ tag (which is an alias for jQuery) tells jQuery to act on the element inside the brackets. It effectively supersedes the getElementById
and getElementsByTagName
JavaScript methods. This means that we can use the same syntax to retrieve a tag as we can to retrieve an element by the id or class. Now, that's pretty cool in its own right, but it goes further.
A common thing we need to do is to wait for the webpage to complete loading before we can manipulate elements in the DOM (bear with me please, this is relevant and not fluff to pad out the article). Traditionally, this would have been coded using window.onload=function(){ /* Do something */}
. jQuery provides a helpful ready method which waits for the document to complete loading:
$(document).ready(function() {
Once the page has finished loading, the DOM elements are in place for us to manipulate. Remember that we have two buttons that need click handlers allocating to them; jQuery provides a click event handler for us to hook into. As I stated before, the $ tag allows us to choose an element or group of elements. Here we're going to use this tag to find the elements that match the ids of the buttons, hook up to the event handlers we're interested in. In order to get an element based on the id, we use the pattern $("#<<elementname>>);
if we want to get a set of elements based on their class, we use $(".<<elementname>>)
. The use of # and . to specify id and class should be familiar from CSS.
Note: The mechanism for selecting elements is known as a selector. The use of the tag name, the class selector and the id selector are only some of a more powerful set of selectors available to jQuery. We'll go into more detail later on.
In the ready
function, we select the two buttons and attach the click event handler to them using the click function. This code is treated specially by jQuery which tracks the creation of events so that they are automatically removed for us, preventing leaks in IE due to the DOM not being able to automatically unload elements because there are references to events in their. Internally, jQuery uses attachEvent
and detachEvent
to manage the events. The following code is executed internally by jQuery to add the onclick
functionality:
if ( div.attachEvent && div.fireEvent ) {
div.attachEvent("onclick", function click() {
jQuery.support.noCloneEvent = false;
div.detachEvent("onclick", click);
});
div.cloneNode(true).fireEvent("onclick");
}
Finally, our click handlers actually have to do something. Again, we search for the element with the id
of para1
using $("#para1")
and we call the methods hide
(and show
in the case of the animateHide
function). The parameters in the hide
and show
methods are optional, as we'll find that a lot of jQuery parameters are.
Beating the Carp out of textareas
Okay, that's enough of that example. It's time for us to write something a little bit more practical. In this example, we're going to write some code that limits the amount of text that we can enter in a multiline textbox (something that you can't do on the textarea alone).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>Second jQuery Sample</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="./js/jQuery/jquery-1.4.4.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
var length = 20;
$("#multiline").keyup(function(){ checkMaxLength($(this),length); });
$("#multiline").change(function(){ checkMaxLength($(this),length); });
});
function checkMaxLength(element, length) {
var maxLength = length;
var currentLength = element.val().length;
if (currentLength > maxLength)
element.text(element.val().substring(0, length));
}
</script>
</head>
<body>
<textarea id="multiline" rows="3" cols="20">Type</textarea>
</body>
</html>
This functionality builds on what we've already learned about events and selectors. Let's break it down and see what's going on in there.
$("#multiline").keyup(function(){ checkMaxLength($(this),length);});
$("#multiline").change(function(){ checkMaxLength($(this),length);});
In the ready
event, we are hooking the textarea keyup and change methods to the same function (checkMaxLength
). We do this so that the user cannot enter more than 20 characters, either by typing them in or attempting to paste beyond the limit. But wait, what is this strange $(this)
element in the call to checkMaxLength
? We need some way to let the checkMaxLength
method know what element we are actually working on; $(this)
gives us the element that is in context when this is evaluating. In a simple case like this, we could use $("#multiline")
to achieve the same effect, but what happens if we want to append this check to all textareas? We couldn't use the id specifier, so we use $(this)
to provide some context for the element.
Inside the method checkMaxLength
, we retrieve the value of the textarea from the passed in element using the val()
function, and depending on the results of the length test, we replace the text using the .text()
method.
It Doesn't Just Support Dutch Football
You can't go anywhere in web development nowadays without hearing about AJAX. If the hype is to be believed, AJAX will turn an Austin Allegro of a site into a Ferarri 458. A responsive, leaping gazelle of a site, positively brimming with vim and vigour. This means, of course, that any serious web development library needs to support AJAX. Surprise, surprise, jQuery does support it, and it is as easy to use as the other elements of jQuery.
Let's pull together a quick sample, and see how it works. As we are not going to be writing any server side code for the purposes of this article, we need a source of data that we can query over the web. Fortunately, Twitter provides a handy API that we can query so we'll use that to get the latest posts and display them in a web page. This is a more complex example, but the building blocks are still the same, so we should have no problems with the new concepts in them.
Right, here's the code in all HTMLy goodness:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>First jQuery Sample</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="./js/jQuery/jquery-1.4.4.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#getTweets").click(function(){ getTweets("chris_maunder"); });
});
function getTweets (user){
var tweetString = "http://api.twitter.com/1/statuses/user_timeline/"
+ user + ".json?callback=?";
$.ajax(
{
url:tweetString,
dataType: 'json',
success: function(data) {
$("#result .tweets").empty();
$.each(data, function() {
$("#result .tweets")
.hide()
.append('<div>' + this.text + '</div>')
.fadeIn();
$("#user")
.hide()
.empty()
.append('<img src=' + data[0].user.profile_image_url + ' />')
.append('<a href="' + data[0].user.url + '">' + data[0].user.name + '</a>')
.fadeIn();
});
},
xhr: window.XMLHttpRequest ? function()
{ return new window.XMLHttpRequest(); }
: function() { try { return new window.ActiveXObject("Microsoft.XMLHTTP"); }
catch(e) {} }
});
}
</script>
</head>
<body>
<div>
<button type="button" id="getTweets">
Get latest</button></div>
<h1 class="tweets">Tweets</h1>
<div id="result">
<div id="user" ></div>
<div class="tweets"></div>
</div>
</body>
</html>
As we can see, there's more going on here but it's still fairly straightforward. The core of the functionality is in the $.ajax
method, so we'll break that down and see what's going on (there is a shortcut for calling a JSON method in jQuery called getJSON
, but as the purpose of this part is dealing with AJAX in raw form, we aren't using it here).
We can see that the Ajax function (along with many other jQuery functions) uses key/value pairs to store details of the parameters. The first entry is the URL which we have set up beforehand to point to the Twitter status timeline for Chris Maunder. Next we state that we want to use JSON for the data we are receiving from the server. The value of this depends on the type of data we are going to receive, and could be a type such as HTML, XML, jsonp or script.
The interesting part of this function is the success section. Here we are creating a function that the API will callback into (big hint here, it's known as a callback function and we find lots of them scattered over jQuery). As we've done before, we are going to manipulate the underlying DOM elements in this function. The first thing we do in here is to remove previous tweets, ensuring that we don't get the same tweet in the list twice.
As you are probably aware, we can receive multiple tweets back from the server. This means that we need to iterate over the collection of tweets. Fortunately, jQuery provides a very handy set of methods for dealing with collection data, and we use the each
function to iterate over the JSON. Inside this function, we extract the tweet text we are interested in, and append it into the item that belongs to the class tweets. The careful among us have noticed that the class has been used in two locations; by specifying that it's #result .tweets
, we tell jQuery to append this information inside the tweets
class that's contained in the div
with the id
result. This is part of the reason that jQuery is so powerful - by doing this, we've cut down on a lot of manual code that we'd have to write.
Note: To fill in the user information, we only need to use the first returned element because this data is the same for each post for this user.
There's an xhr
parameter which allows us to specify how the XML Http Request object is created. There have been some memory leak issues in the past with AJAX calls in jQuery, and specifying this code overcomes the issues.
Obviously, using jQuery in a production environment would normally entail use of error handling and validation, but hopefully this gives you an idea of how to construct the basics of an AJAX application using jQuery.
Final Thoughts
So, there we go. A quick introduction to the power of jQuery, and a guide to just how easy it is to use it to create rich and powerful websites. I hope that you like it, and that it inspires you to see how you can push your sites forwards.
History
- 22nd December, 2010: Initial post