Getting the page height with jQuery

I was recently adding an overlay (or modal) feature to one of my sites. This overlay feature required a blackout mask (when your webpage gets covered with an opaque black layer) to be shown over the content. Writing the CSS for this was a breeze, and writing the jQuery (or Javascript) for this was even easier. However, I did run into one little snag.

In current browsers I could do a position fixed on the blackout and define width and height at 100%. While in outdated browsers (Internet Explorer), position fixed does not work properly, so I had to resort to Javascript and position absolute. This was easy as I would grab the height of the page and apply it to the blackout CSS. During my testing I noticed that the blackout would only fill the viewport of the page, and the second you started scrolling you would see where the blackout cut off.

After some browsing of the jQuery API I discovered my problem. It seems that the window and document objects return different heights in jQuery. Window returns the height of the viewport (everything within view) while document returns the height of the HTML page (the whole page, including hidden content that requires scrolling). Furthermore, window and document can not use outerHeight() nor innerHeight(), they must simply use height().

$(window).height(); // returns height of browser viewport
$(document).height(); // returns height of HTML document

Here is how I remember which is which: document returns the height of the DOM (document object model) and window returns the height of the viewport (viewing out a window). I know many of you may of already known this, but it slipped past me and was quite a genius implementation of behalf of the jQuery team.

Book Review: jQuery Enlightenment

Before I dive on topic, I want to give you all a heads up that I will be posting a review of the book: "AJAX and PHP: Building Modern Web Applications 2nd Edition", by Packt Publishing. So far the book is great and has some nice chapters about jQuery, JSON, PHP and even XAMPP.

Now jQuery Enlightenment (jQE) isn't much of a book as it is a helpful PDF. It's not as long as your typical book, but it gets the job done in explaining jQuery and its core components. The topics that are covered in jQE range from Selectors, Traversal, DOM and Manipulation, Forms, Events, Plugins, AJAX, the Core and much more. The current edition of the book covers jQuery 1.3.2, and since 1.4 recently came out, I'm going to note any differences or problems that can be solved using 1.4 (if there are any).

The document is only a mere 123 pages (PDF pages to be precise), which may sound like a lot, but in actuality it isn't. Each chapter of jQE comes with code snippets, which have links to JsBin.com that allow you to run and test the snippet yourself. The snippets are also color coded to represent which areas of the code you should be focusing on and understanding. These features were probably the greatest thing about jQE and what sets it apart from regular books. It allows you to interact with the code first hand and makes it easier to understand once you see it in action (and you don't have to manually write it all too!). One caveat though is that the snippets use alert() for testing purposes, as they didn't want to rely on you having Firebug installed.

The book begins by talking about the jQuery core, of course. It states that jQuery should only be used in HTML standards mode, and not in quirks mode, as it has problems with rendering. One great aspect that I liked is its explanations of do's and don'ts and how to properly use jQuery to its full advantage. An example of this is to use the built in short hand code, and when to properly bind and invoke certain event handlers.

// You can get the current jQuery version by using the jQuery property
var version = $().jquery; // or $.fn.jquery

A feature that I rarely use (but probably should) is deep chaining. What I mean about deep chaining is using the find() function, paired with end(). I personally prefer just calling the functions separately on the specific jQuery objects. Regardless, jQE also made use of detailing out when and how this should be used and in what context (especially helpful for callbacks and special functions). While re-reading over the selectors chapters, I can't help but think to my self "A lot of this would be easier in 1.4 with the new functions, has() and not().", but you can still create your own selection filters (which is awesome).

// Define custom filter by extending $.expr[':']
$.expr[':'].positionAbsolute = function(element) {
	return $(element).css('position') === 'absolute';
};
var divs = $('div:positionAbsolute');

I always forget that you can create your own selection filters (just a reminder to myself!). Back on topic, jQE gets more in depth and accompanies it with more examples, so a must read if you are interested in such techniques. I bet you didn't know that you can nest filters as well:

var divs = $('div:not(:has(.jQuery))');
var ps = $('p').filter(':not(:first):not(:last)');

Moving on, the chapters on traversal are really well done, as it talks about rarely used functions like andSelf() and contents() (to me at least). However, I really feel like the forms chapter could of been a bit more in depth. It described how to properly select radios, checkboxes, selects, etc, but I felt as if something was missing. I noticed that when talking about getting/setting values for selects, that jQE might be wrong or out of date, as I am able to set the value of a select by passing the "value" tag of the option, and not the text. Maybe this has been updated in newer versions of jQuery, or I'm just blind. Besides that little mishap, it provides some great examples on how to select certain options based on the selection filters (pretty nifty!).

$('#select option:not(':selected')');

When talking about events and binds, it was pretty straight forward. Events in itself aren't that complicated to understand, especially in jQuery. However, there was one minor feature I didn't know about, and that was passing an empty bind function will trigger the previous bind.

// Alert will automatically trigger since we are passing an empty click()
$('a').click(function(){ alert('Its black magic!') }).click();

Actually, I just got a bit ahead of myself. There are some pretty exciting things you can do with events, like event specific namespacing, and using the event object functions (preventDefault(), stopPropagation(), etc). I won't get into this subject, as you should purchase jQE and find it out for yourself! Oh, did you also know that you can disable the right click menu in your browser (not in Opera, sorry guys!), by simply using jQuery? Me neither!

$(document).bind('contextmenu', function() { 
	return false;
});

Now for the bigger topics, Plugins, Effects amd AJAX. jQE covers the basics on how to properly write and create a basic skeleton for your plugins. It goes over the correct usage and context for this, how to apply the plugin to all selected elements with the each command, how to return and chain properly and how to easily extend and creating custom settings. Now that's basically all it talks about, which I think was too short. I've seen so many different variations and usages for jQuery plugins, and so many of them wrote it differently. For example, Ive seen people define functions within the each() loop, as well as outside the loop scope. I'm assuming this sets the visibility to private so that the functions can not be called, but what if I do want to call a plugin function?

$.fn.myPlugin.someFunction = function() { 
	// Do something 
}

Is it possible for me to call this function outside of the plugin, or does a plugin only package everything and do it automatically. There was too many "What if", "How does" type questions I was thinking to myself, and jQE was unable to answer. But these type of questions are probably best asked in larger more in depth books.

I don't want to keep boring you with minor details, and I would like to leave the chapters on AJAX and Effects alone (aka the exciting ones). By doing so, I hope you go purchase this document and read it for yourself. I promise you won't be disappointed.

Besides a few minor gripes and unanswered questions, jQE delivered everything I needed to know on how to properly use jQuery. It did its best to go into detail, and to also describe how the internals are working. I personally liked the fact that the document was littered with multiple examples on how to optimize and write fast code. A quick example for your enjoyment (and you may have not known that you can pass objects as an argument!).

$('a').css({'display': 'block', 'color': 'red'}).attr({'title': 'Title Txt', 'href': 'http://www.jquery.com'});

All in all, this was a great book to start learning jQuery. However, there was one thing I completely disliked, and it was when the book prefixed variables with a $ ($var), ugh! Sorry, this is Javascript, not PHP!

In closing, be prepared for my next review on AJAX and PHP: Building Modern Web Applications 2nd Edition, as I know some of my readers will enjoy it (yes you!).

Element creation in jQuery 1.4

Before I start, I'd like to say hats off to the jQuery team, as 1.4 is looking beautifully so far. I've already ran into about 3 problems that were fixed with the new features in 1.4, like the parentsUntil() function. However, the post today will be about the new element creation system using the core jQuery method, $(). In 1.4 you can now create an element by passing the tag name as the first parameter, and an object of attributes as the second. The parameters should be a named value pair of attributes to be appended to the element, like the ID, class, value, title, text, etc. View more about it in the official documentation.

var input = $('<input>', {
	id: 'FormUsername',
	name: 'username',
	type: 'text',
	value: 'Enter your username...',
	focusin: function() {
		$(this).val('');
	}
}).appendTo(someElement);

This new approach opens up tons of new opportunities and uses, compared to the previous usage of writing out the whole element, or doing it the old school way with document.createElement().

// We don't need you anymore outdated code!
var input = $('<input type="text" id="FormUsername" name="username" value="Enter your username..." />').focusin(function() {
	$(this).val('');
}).appendTo(someElement);
var input = document.createElement('input');

Just earlier today I needed a way to dynamically create specific elements, with a specific set of attributes. This new functionality allows me to easily do that by just passing an object, and wallah! Here's just a quick example of some of the usages. It can get quite handy when you need to loop through objects/arrays and create elements accordingly.

// Some data returned from an AJAX call
var data = jsonObj;
// Loop it and build the fields!
$.each(data, function(key, params) {
	var parent = $('<div>', {
		id: 'Comment_'+ params.id,
		text: params.message
	}).addClass(params.className);
	var child = $('<a>', {
		href: '/user/profile/'+ params.user_id,
		text: params.username
	}).prependTo(parent);
	parent.appendTo('#comments');
});

In the code above we are getting a list of comments as a JSON object, then iterating over the object and dynamically creating the elements. Albeit this is just a quick and dirty example, as it would be best to just have the AJAX spit out the HTML, but you get the picture.

You may have noticed that I used addClass() on the parent instead of declaring a param of "class". You can use class, but class must be quoted as it causes problems in IE (of course). Personally, I just stick to addClass() as it will not cause any problems in any browser. Furthermore, if you want to apply some content text (like the link text, not the title), you would pass a param of "text".

The new element creation is just one of the more awesome features in jQuery 1.4. I hope you guys enjoy it as much as I am; and if you are not yet, get to it! What are you waiting for??

AJAX calls in CakePHP: The JSON Response

The controller and HTTP response are now working correctly, so it is time to display the response message to the client. We will achieve this by utilizing jQuery to output our JSON. The plan is to show a success message if the JSON passed or display a list of errors if it has failed. To display the messages we need to create our HTML elements that will hold the responses.

<div id="responseSuccess" class="responseBox" style="display: none"></div>
<ul id="responseError" class="responseBox" style="display: none"></ul>

Before we can write our Javascript to handle the JSON, we need to first inspect the JSON response. Our JSON "data" message can come in 3 possible formats: a simple string, an array containing the error messages, or an object containing the error messages / post data with their key values. Below are a couple examples of how our JSON response could be formatted:

// Single string error
{"success":false,"data":"No username/password","code":-1}
// An array containing the errors
{"success":false,"data":["No username","No password"],"code":-1}
// Errors / Post data and their key
{"success":false,"data":{"username":"No username","password":"No password"},"code":-1}
{"success":true,"data":{"username":"Miles","password":"p4ssw0rd"}}

Now this poses a significant problem. If our response data can be sent as 3 possible formats, we need to write our Javascript to be able to handle all possible variations. We can do this by creating a loop for the arrays/objects and store the values in a custom array, and for the single string just return the message. The following code block can do just that, and all we need to do is place it within the "success" parameter of our AJAX call.

function login() {
	var data = $("#UserAddForm").serialize();
	$.ajax({
		type: "post",
		url: "/ajax/login/",
		data: data,
		dataType: "json",
		success: function(response, status) {
			// Response was a success
			if (response.success) {
				$("#responseSuccess").html(response.data).slideDown();
			// Response contains errors
			} else {
				var errors = [];
				if (typeof(response.data) == ("object" || "array")) {
					$.each(response.data, function(key, value) {
						var text = isNaN(key) ? key + ": " + value : value;
						errors.push("<li>"+ text +"</li>");
					});
				} else {
					errors.push("<li>"+ response.data +"</li>");
				}
				errors = errors.join("\n");
				$("#responseError").html(errors).slideDown();
			}
		}
	});
	return false;
}

Pretty simple right? We can improve on this code by adding a setTimeout() that will remove the response box after 5 seconds. Additionally we can add the AJAX error argument that is called if the AJAX mechanism fails as a whole.

// Remove box after 5 seconds
setTimeout(function() {
	$(".responseBox").slideUp();
}, 5000);
error: function(XMLHttpRequest, textStatus, errorThrown) {
	$("#responseError").html("<li>An unexpected error has occurred.</li>").slideDown();
}

Our Javascript is now complete, but we could improve on it yet again. Say you have multiple AJAX calls that all utilize the same type of callback mechanism. It would be a major pain and waste of time to write all that code over and over again. What we can do is separate the code into 3 separate functions, all handling certain aspects of the logic. Our final code may look something like the following.

/**
 * Fire an AJAX call to login the user
 */
function login() {
	var data = $("#UserAddForm").serialize();
	$.ajax({
		type: "post",
		url: "/ajax/login/",
		data: data,
		dataType: "json",
		success: function(response, status) {
			handleCallback(response, status);
		},
		error: function(XMLHttpRequest, textStatus, errorThrown) {
			handleError(XMLHttpRequest, textStatus, errorThrown);
		}
	});
	return false;
}
/**
 * Handle the AJAX callbacks
 */
function handleCallback(response, status) {
	// Response was a success
	if (response.success) {
		$("#responseSuccess").html(response.data).slideDown();
	// Response contains errors
	} else {
		var errors = [];
		if (typeof(response.data) == ("object" || "array")) {
			$.each(response.data, function(key, value) {
				var text = isNaN(key) ? key + ": " + value : value;
				errors.push("<li>"+ text +"</li>");
			});
		} else {
			errors.push("<li>"+ response.data +"</li>");
		}
		errors = errors.join("\n");
		$("#responseError").html(errors).slideDown();
	}
	// Remove box after 5 seconds
	setTimeout(function() {
		$(".responseBox").slideUp();
	}, 5000);
	return false;
}
/**
 * Handle an AJAX failure
 */
function handleError(XMLHttpRequest, textStatus, errorThrown) {
	$("#responseError").html("<li>An unexpected error has occurred.</li>").slideDown();
}

Now there are multiple ways for your to handle a JSON response, but the approach above is a pretty straight forward implementation of displaying a success or failure message. Be sure that when you write your AJAX requests, that the $.ajax() function has a dataType of json, or your JSON response will completely fail.

AJAX calls in CakePHP: The Controller

Now that you have setup the Javascript and view to properly fire off an AJAX call, it's time to process the call within the Controller. The AJAX call was firing off to AjaxController::login(), so lets begin by creating the action. What we need to do is check to see if the username and password is set (validation), then attempt to login the user by using the AuthComponent. If the login is successful, or even if it fails, we will return a JSON response.

Below would be a basic setup to accomplish what we need to do. However, in your actual application you would apply more strict validation and sanitization, but for the sake of the tutorial I will not.

function login() {
	$this->layout = 'ajax'; // Or $this->RequestHandler->ajaxLayout, Only use for HTML
	$this->autoLayout = false;
	$this->autoRender = false;
	$response = array('success' => false);
	if (!empty($this->data['User']['username']) && !empty($this->data['User']['password'])) {
		if ($this->Auth->login($this->data)) {
			$response['success'] = true;
			$response['data'] = $this->data['User'];
		} else {
			$response['data'] = 'Username/password combo incorrect';
			$response['code'] = 0;
		}
	} else {
		$response['data'] = 'No username/password';
		$response['code'] = -1;
	}
	$this->header('Content-Type: application/json');
	echo json_encode($response);
	return;
}

As an added bonus, I will supply an example of how to achieve the same result above using my AjaxHandlerComponent. The component does all the necessary preparations and output leaving you to write less code.

function login() {
	if ($this->AjaxHandler->valid($this->data['username'], true) && $this->AjaxHandler->valid($this->data['password'], true)) {
		if ($this->Auth->login($this->data)) {
			$this->AjaxHandler->response(true, $this->data);
		} else {
			$this->AjaxHandler->response(false, 'Username/password combo incorrect', 0);
		}
	} else {
		$this->AjaxHandler->response(false, 'No username/password', -1);
	}
	$this->AjaxHandler->respond();
	return;
}

Basically what we need to do, to get a proper JSON response is to build the response array. We create an array with a success variable that would be a true or false. If the success is true that means the core logic that we want completed was a success, else the AJAX logic failed and the user should try again. We also have a data index that would house the error/success message(s), an array of data to use, or anything else you might need. Lastly we have a code index which could be used to differentiate the levels of errors and their importance. Once we have our response array complete, we set the correct headers and respond it back while encoding it with json_encode().

On top of building the response we need to configure the controller a bit. We need to disable the view and layout from rendering or we will receive the "Missing View" errors within Cake, and we also need to remove the layout so that our response is not surrounded by HTML (unless you want to respond with HTML, but we are using JSON). We do this by setting autoLayout and autoRender to false -- furthermore we set the layout to ajax which would be required for HTML responses.

You must be thinking to yourself, "Wow that was easy, we are now done!", but you are wrong! We still have one final step, validating that the request is a legitimate AJAX call. To achieve this we will use the RequestHandler::isAjax() method. Since all of our AJAX calls are housed in the AjaxController, we can place this code in the beforeFilter() so it applies to all actions. If your AJAX actions are within your primary controllers, you will need to add a bit more logic.

I will be using the SecurityComponent in my examples, but you can use die() or something similar in place of blackHole(), like Controller::redirect().

// Must be disabled or AJAX calls fail
$this->Security->validatePost = false;
if (!$this->RequestHandler->isAjax()) {
	$this->Security->blackHole($this, 'You are not authorized to process this request!');
}
// Use the following code in place of blackHole()
// $this->redirect(null, 401, true);

The previous code should blackhole any request that does not contain the XMLHttpRequest header. To further build on this code, we can check to make sure the AJAX request is coming from the current domain, if not then kill it. Our final beforeFilter() should look something like the following.

function beforeFilter() {
	parent::beforeFilter();
	// Must be disabled or AJAX calls fail
	$this->Security->validatePost = false;
	if (!$this->RequestHandler->isAjax()) {
		$this->Security->blackHole($this, 'You are not authorized to process this request!');
	} else {
		if (strpos(env('HTTP_REFERER'), trim(env('HTTP_HOST'), '/')) === false) {
			$this->Security->blackHole($this, 'Invalid referrer detected for this request!');
		}
	}
}

The controller code should now be complete and ready for your amazing AJAX use. We could however improve it a little more by utilizing the RequestHandlerComponent and some of its methods, but ill leave that up to you to adventure into. In the next chapter we will go over the response and how to interact with the JSON.

AJAX calls in CakePHP: The Front-end

One of topics I always see pop up in the CakePHP Google Groups is how to correctly do AJAX calls in CakePHP. I will be splitting this up into 3 different entries, the first will be pertaining to the view/Javascript (front-end) and how to fire off the AJAX call, the second will deal with the controller action and how to process the request, and the final entry will be dealing with the response (in JSON format).

Additionally I will be using jQuery for all my Javascript interactions. Some developers ask me if I have ever used CakePHP's built in Javascript helpers, and I always so no. I don't find the benefit in using the helpers when it causes extra parsing in the front-end by running it through PHP objects, when you can simply write out the function name manually within the HTML template, which takes no processing!

Now lets begin by creating your forms within the templates. I will be doing a user login system to demonstrate the AJAX calls. Take note that I am applying a "return false" on the form's onsubmit attribute. This will stop the form from posting when a user hits enter, so that they must use the AJAX trigger.

<?php echo $form->create('User', array('onsubmit' => 'return false;'));
echo $form->input('username');
echo $form->input('password');
echo $form->end(); ?>
<button type="button" onclick="login();">Login</button>

The form is pretty straight forward, so lets start out by creating our login() function within the Javascript. The login() function will be firing an AJAX call to AjaxController::login(). Furthermore, I will NOT be doing any form input validation in the AJAX, feel free to figure it out yourself!

function login() {
	var data = $("#UserAddForm").serialize();
	/* Or no serialization (Read #2 below)
	var username = $("#UserUsername").val();
	var password = $("#UserPassword").val();
	var data = "username="+ username +"&password="+ password;
	*/
	$.ajax({
		type: "post",		// Request method: post, get
		url: "/ajax/login/",	// URL to request
		data: data,		// Form variables
		dataType: "json",	// Expected response type
		success: function(response, status) {
			// Will continue in part 3
		},
		error: function(response, status) {
			alert('An unexpected error has occurred!');
		}
	});
	return false;
}

There are a few key points I would like to discuss first about the code above, before continuing with the tutorial.

1) AJAX functions

In my example I am using jQuery's built in ajax() function. However, you can use the alternative post() function, but as a personal preference I like to use ajax(). (I will also post an article about the difference between get/post and when to use each one).

2) Form input names

By default if you use jQuery's serialize() function, it will convert all inputs into name/value pairs and wrap them into a query string. This means it also includes the "data[Model][field]" setup when posting to your AjaxController, which in turn means you can access the data at $this->data['Model']['field'].

If you want to do it the old fashion way (or when its not possible to serialize()), you can create the query string yourself by grabbing the value of each input and building the name/value pairs (You can see this in the example below). However, if you do not include the "data[Model][]" around each of the named variables, you cannot access the data in the controller with $this->data, you would have to use the $this->params['form']['field']. Below is a quick example of the possible jQuery data values and how to access them in CakePHP.

var data = "data[Model][field]=foobar";
$field = $this->data['Model']['field']; // Equals foobar
var data = "data[field]=foobar";
$field = $this->data['field']; // Equals foobar
var data = "field=foobar";
$field = $this->params['form']['field']; // Equals foobar

If you go the path of not wrapping your fields in data[] and are using my AjaxHandlerComponent, the component will automatically process and parse the jQuery posted data into the controllers $this->data.

3) Response type (dataType)

One major feature of jQuery is the "dataType" variable within its AJAX calls. If you are responding with a JSON object with the HTTP header of application/json, be sure to set the dataType to json or your response will fail -- this goes the same for XML. If your responding with plain text or HTML you can omit the dataType variable.

Pro Tip: If you are responding with a JSON content type, jQuery will automatically decode the JSON object for you (and apply it to the response argument for success, error, etc), so that you do not have to use a 3rd party library.

Now that we have the form and Javascript written, lets test our AJAX call. If you have Firebug installed (which you should), open it beforehand to check the HTTP request and response. If everything worked correctly so far, you should see the following HTTP request and response headers (Do note, your headers will be similar, and not exactly the same!).

// Request Headers
POST /ajax/login/ HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)
Accept: application/json, text/javascript, */*
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 73
// Response Headers
HTTP/1.x 200 OK
Server: nginx/0.8.15
Date: Thu, 01 Oct 2009 23:22:13 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.2.10
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
// Posted Variables
data[User][password] password
data[User][username] milesj

Basically what these headers are telling us is that our request was posted to /ajax/login/ and the server responded with an OK using the Content-Type of application/json. If you are unfamiliar with HTTP headers, I highly suggest you read the book "HTTP Developers Handbook, by Chris Shiflett.

That is all for now in this entry, stay tuned shortly for part 2 where I discuss the controller and action setup and how to properly respond to an AJAX call. Hope this helps you confused developers so far!

Toggling all checkboxes with JavaScript

Update You can view the comments for alternative and quicker ways to do this, enjoy!

Say you have a list of messages, and on the left of each message is a checkbox. This checkbox is used for a mass deletion or mass insert function here. Now to make it easier on the user, its nice to add a checkbox outside of the list that either checks them all, or dechecks them all. The following function can achieve that effect, using jQuery or regular JavaScript of course.

// Javascript
function toggleCheckboxes(current, form, field) {
	var val = current.checked;
	var cbs = document.getElementById(form).getElementsByTagName('input');
	var length = cbs.length;
	for (var i=0; i < length; i++) {
		if (cbs[i].name == field +'[]' && cbs[i].type == 'checkbox') {
			cbs[i].checked = val;
		}
	}
}
// jQuery
function toggleCheckboxes(current, form, field) {
	$("#"+ form +" :checkbox[name='"+ field +"[]']").attr("checked", current.checked);
}

Lets set up a quick example of how our form should be and how this function should be used properly. We will begin by adding the form tag with an id (required) and the message checkboxes.

<form action="" method="post" id="messageForm">
<input type="checkbox" name="messages[]" /> Message 1
<input type="checkbox" name="messages[]" /> Message 2
</form>

Let me explain the functions arguments before we finish up. The first argument should always be "this" so it can reference itself, the second argument would be the id of the containing form and the final argument would be the name of the checkboxes input name attribute (without the []). Now with that, we can finish this up by placing the following code anywhere on your page. Enjoy!

<label for="messages"><input type="checkbox" onclick="toggleCheckboxes(this, 'messageForm', 'messages');" /> Toggle all checkboxes</label>