Event delegation is a very important part of writing efficient code for handling events in JavaScript. We looked at JavaScript events in this section here and looked at some other components of it when exploring things like the publish/subscribe pattern in creating JavaScript event channels.
What is event delegation? Well, in general the concept of event delegation could be thought of as assigning a single event handler to handle multiple items.Event delegation is not necessarily a requirement for handling JavaScript events, but it certainly is a good practice and a good habit to apply to your JavaScript code.
We’ll take a look at this below using jQuery in our example. Let’s say we had a simple menu like the following.
<!DOCTYPE html>
<head>
<title>Event Delegation jQuery | 9bit Studios</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
</head>
<body>
<div id="menu">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Portfolio</a>
<a href="#">Projects</a>
</div>
</body>
</html>
So how would we add events to our <a> elements? Certainly we could do something like the following…
<!DOCTYPE html>
<head>
<title>Event Delegation jQuery | 9bit Studios</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
</head>
<body>
<div id="menu">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Portfolio</a>
<a href="#">Projects</a>
</div>
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery('#menu a').on('click', function(e){
console.log(e.target);
});
});
</script>
</body>
</html>
In doing this, we have added events to each of the individual <a> elements. While this certainly works it becomes a bit messier when you start to dynamically add elements to the DOM. In modern web applications, dynamic, interactive, client-side updating of content is certainly a very common implementation that you come across. Let’s say we wanted to add a button to dynamically add new items to our menu…
<!DOCTYPE html>
<head>
<title>Event Delegation jQuery | 9bit Studios</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
</head>
<body>
<div id="menu">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Portfolio</a>
<a href="#">Projects</a>
</div>
<a id="addNew" href="#">+ Add New Menu Item</a>
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery('#menu a').on('click', function(e){
console.log(e.target);
});
jQuery('#addNew').on('click', function(e){
var html = '<a href="#">New Item</a>';
jQuery('#menu').append(html);
});
});
</script>
</body>
</html>
When you add a few new menu items what happens when you click on the newly created items? Nothing. Why is that? Because when we ran our code to add the events to each individual <a> elements those newly added elements did not exist (and thus never got event handlers attached to them).
What could we do to solve this? Well, we could certainly run the code to add event handlers again, but as our codebase gets bigger and more complex handling things this way gets a bit on the messy side.
What should we do then? As it turns out a better way to approach this is to add the event to something that will always be there and won’t change. In this case, it’s our <div id=”menu”> container. By adding the click event to the this container, it servers as the delegate for all of our <a> elements. We can then do the following…
<!DOCTYPE html>
<head>
<title>Event Delegation jQuery | 9bit Studios</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
</head>
<body>
<div id="menu">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Portfolio</a>
<a href="#">Projects</a>
</div>
<a id="addNew" href="#">+ Add New Menu Item</a>
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery('#menu').on('click', 'a', function(e){
console.log(e.target);
});
jQuery('#addNew').on('click', function(e){
var html = '<a href="#">New Item</a>';
jQuery('#menu').append(html);
});
});
</script>
</body>
</html>
Notice the syntax of displaying the a selector after the. As is described in the jQuery docs for the .on() method…
If selector is omitted or is null, the event handler is referred to as direct or directly-bound. The handler is called every time an event occurs on the selected elements, whether it occurs directly on the element or bubbles from a descendant (inner) element.
When a selector is provided, the event handler is referred to as delegated. The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector. jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
So now what happens when you click on a newly created <a> element in our menu. Voila! The event is captured. Huzzah! We now never have to worry about adding (or removing) any events for our dynamically created elements because we have used event delegation to handle it for us. A single function takes care of all future updates. It’s a one and done kinda thing.
Hopefully, this discussion has helped you better understand what event delegation is and where it might be useful. Until next time, happy delegating!
Previously, in an earlier installment we discussed some initial considerations for creating an application in Express.js following the Model View Controller (MVC) design pattern. We’ll pick up where we left off in what follows. The focal point will center around middleware and configuration…
Middleware
One of the things that we are going to want to implement in our application is middleware. There is a pretty good list of Express.js middleware in the Express.js project. Middleware is an important component of Express.js applications. You couple probably think of a middleware function or method as a function that runs on every request/response cycle at whatever point you want to specify. For example, if you wanted to see if the current user who is making the request is authenticated on every single request, you might have this authentication check run in a middleware function before issuing the response. That’s just one example, but there are many other pieces of functionality that you can run within middleware functions.
So let’s add some of the common Express.js middlewares. One useful middleware utility that we can use is a logging component. This will give us information about all of the requests made as our application runs. Express.js uses something called Morgan to accomplish this.
To add middleware, we’re going to want to add it to our package.json file as a dependency. So let’s update our package.json file to look like the following
{
"name": "MVC-Express-Application",
"description": "An Express.js application using the MVC design pattern...",
"version": "0.0.1",
"dependencies": {
"express": "4.4.4",
"express-handlebars": "1.1.0",
"morgan": "1.1.1",
}
}
Don’t forget that we have to install our new module as well. Fortunately, Node.js and npm make this easy. All we have to do is run $ npm install again and all of our packages will be updated…
$ npm install
Now that our dependency is installed, we need to add a reference to it in our main application file…
var logger = require('morgan');
Let’s add the following lines of code to our main app.js file…
/* Morgan - https://github.com/expressjs/morgan
HTTP request logger middleware for node.js */
app.use(logger({ format: 'dev', immediate: true }));
Now if we run our application and look at our CLI window we can see all the requests being output on every request response cycle. And just like that, we have made use of our first middleware.
Read More »
One of the more important pieces of any client-side JavaScript framework is the routing of requests when users navigate to different places. Basically a JavaScript router in a client-side application will listen for changes in the hash location and update the data and UI in the page accordingly, making all of the API calls that it needs to do so. But how is this feat accomplished? How do we match a route pattern defined in a JavaScript framework to an actual route navigated to by the user? This is something we will look at in what follows.
Normally, when you talk about matching you immediately think to look at regular expressions. However, the way that routes are defined in client side applications often have patterns that are a little bit different that the actual routes that will be navigated to by users. What do we mean by this? We talked about routing in Backbone.js here. Basically a Backbone.js router is set up like the following…
var Router = Backbone.Router.extend({
routes: {
"": "home", // url:event that fires
"new": "createNew"
"edit/:id": "editItem",
"download/*anything": "downloadItem"
},
home: function() {
alert('We have loaded the home view');
},
createNew: function() {
alert('We are going to create something new');
}
editItem: function(idParam) {
alert('We are going to edit entry number ' + idParam);
}
});
var router = new Router;
In this setup, when a user navigates to a particular route, the function defined in the routes object will run. So if a user were to navigate to the route #/edit/4, the editItem function will run passing in the id 4.
Read More »
Express.js is probably currently the most popular Node.js framework for building web applications and APIs. It has a good history, a good community around it, lots of modules built for it, and a fairly solid reputation.
In what follows we’re going to walk through how to build an Express.js application using the Model View Controller (MVC) design pattern. It’s likely that we’ll do this tutorial in multiple parts.We’ll start out with a simple application structure and then we’ll move on by adding more complex concepts like authentication, dynamic routing, and reading from and writing to a database.
To start, it’s a good idea to have some background on both Node.js and Express so you know some of the terminology and philosophy behind what is being discussed. If you are not entirely familiar with Express.js there is an introduction to it here. And if you’re not entirely familiar with Node.js there is a primer on Node.js here.
At the time of this writing Express is at version 4.X. If you are reading this at a later point, it’s possible that the latest version differs quite significantly from this. Be sure to check out the Express.js homepage to find information on how to properly set things up using the most current version of Express. However, it may be the case that the steps followed in this tutorial will not be fully compatible with the most recent version of Express.js
package.json
To start we’re going to want to create a package.json file. You can read more about pakcage.json here. package.json will define some metadata type things like the name and version of the application, but most importantly, it will specify what modules you will need to download and run the application. You can read more about modules in Node.js here as well as in any good introduction to Node.js. Express is itself a Node.js module and it makes use of other Node.js modules. Some modules like “http” are core Node.js modules (part of the Node.js core) and some like express.js are third-party. Core Node.js modules will always be available to your application because it is running on Node.js
So our sample package.json file will look like the following…
{
"name": "MVC-Express-Application",
"description": "An Express.js application using the MVC design pattern...",
"version": "0.0.1",
"dependencies": {
"express": "4.4.4",
}
}
One item of note: the name of any given package cannot have any spaces. This is to ensure that installation of packages is easy and consistent across all environments.If people were ever wanting to install our application as a module on npm (if we ever put our application on npm) by running $ npm install MVC-Express-Application it would not work if the package was named MVC Express Application. If we ran $ npm install MVC Express Application, the CLI would get confused.
Now if we run the following from the directory where our package.json file resides
$ npm install
all of the dependencies that we have specified will be downloaded and installed into a “node_modules” directory. The great thing about this is that if we need to update the versions of our modules or add new ones, we can just add or edit this package.json file and run “npm install” again. The npm installer will figure out all of the files needed. We are limited to the modules we are installing right now, but we will be adding a lot more to this later.
Application
Next we’ll want to create an “app.js” file. This file is the kickoff/entry point of our application when it starts up. This is akin to the main() function you’d find in C++ or Java.
The first components we’re going to want to add are here…
var express = require('express');
This loads up the express module. We can now refer to it in our code.
A lot of the modules we’ll be loading up are part of the Express.js project itself. There are many useful items that our application will be utilizing at various times throughout our application. As is described in the Node.js documentation on modules, Node.js modules can be loaded via references to filenames so long as those filenames are not named the same as reserved core Node.js modules, e.g. the “http” module.
Read More »
One of the most important parts of any programming language is the ability to extend objects, creating your own objects and objects that inherit from those objects. In class-based languages like Java or PHP you’ll see the “extends” keyword being used to set up inheritance between different objects.
JavaScript, however, is structured quite a bit different than class-based languages because it is a prototype-based language. For a more detailed look at JavaScript inheritance see this article here. Additionally, opposed to having different types assigned to variables, in JavaScript everything is an object (and, as a result, everything can be extended)
.
In what follows we’ll take a brief look at JavaScript extend functions. Note that this is a little bit different than inheritance. Extend functions in JavaScript could maybe be thought of merging 2 objects, rather than one object inheriting from another. We’ll refer to these as the target object and an extending object. Remember in JavaScript that an object literal is essentially a collection of key/value pairs. Recall too that in JavaScript object keys can also have functions for their values as well. So if a “key” in our extending object already exists on the target object the value for the key in the extending object will overwrite the value for the key in the target object.
The function to extend an object will look something like what is below…
function extend(targetObject, extendingObject){
for(var key in extendingObject) {
targetObject[key] = extendingObject[key];
}
}
Let’s take a look at how this works in practice. Say we have an object called “robot,” that has a couple of properties…
var robot = {
size: 'small',
gas: 100,
mode: 'helpful',
move: function() {
console.log('Walk')
}
};
Now let’s say we want to extend our robot with some “upgrades”. New properties (keys) will be added to the object and existing properties will overwrite the values for the current object. Will give the robot some more gas (overwriting the robot’s current value), and give it a new mode (setting) and give it a rocket launcher,
var upgrades = {
gas: 200,
mode: 'crush kill destroy',
rocketLauncher: function(){
console.log('BOOM');
}
};
Pass this into the extend function…
extend(robot, upgrades);
And now our robot object looks like the following…
var robot = {
size: 'small',
gas: 200,
mode: 'crush kill destroy',
move: function() {
console.log('Walk')
},
rocketLauncher: function(){
console.log('BOOM');
}
};
Now that we’ve set our robot to “crush kill destroy” it’s a good thing we’ve kept the size at “small.” Hopefully it will be easier to take out if it turns on us.
Let’s take a look at the popular Underscore.js libary’s extend function…
_.extend = function(obj) {
each(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) {
obj[prop] = source[prop];
}
}
});
return obj;
};
Aside from a little bit of conditional checking and variance in how it’s called, the core functional purpose is essentially the same as the function we wrote above.
You’ll often see the extend function used to pass in different options or settings when calling certain jQuery plugins.
$(window).load(function() {
$('.flexslider').flexslider({
animation: "slide",
animationLoop: false,
itemWidth: 210,
itemMargin: 5,
minItems: 2,
maxItems: 4
});
});
Within the plugin there will be some default settings, but an object literal can get passed in when calling the jQuery plugin that will overwrite the default settings by using the jQuery extend function. This is an easy way to implement custom settings for a jQuery plugin.
So as we have seen, extend functions in JavaScript are a common and useful way to merge two objects together for a variety of purposes. Hopefully you’ll be able to use this when writing some of your JavaScript based applications.