Share Tweet Reccomend

jQuery Event Delegation

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="https://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="https://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="https://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="https://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!

, ,
Share Tweet Reccomend

Responsive Grid Rowspan

If you have been doing anything with front-end web development since ca. 2010 you will have no doubt come across the concept of responsive web development and along with it, responsive grids. Responsive grids are great and, as of early 2015, have become completely ubiquitous across the Internet. Whether you are using Twitter Bootstrap or ZURB Foundation or any one of the numerous lesser-known responsive grid systems they all provide a nice way to clreate flexible fluid web layouts that display well on all devices.

Fluid responsive grids are not without their drawbacks, however, Their structure tends to bring about some challenges in doing some more complex positioning of content. For example, if one column in a group of columns placed next to each other in a row has more content than adjacent columns, you can have some unwanted effects in your layout. For example, in the example below (using Twitter Bootstrap), we can see that with more content in the right column the left column will get pushed down.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Responsive Grid Rowspan</title>
<link rel="stylesheet" type="text/css" href="css/style1.css" />
</head>

<body>
    <div class="row">
        <div class="col-lg-8">
            <div class="inner">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
            </div>
        </div>
        <div class="col-lg-4">
            <div class="inner" style="background:#999;">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
                <p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-lg-8">
            <div class="inner">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
              <p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
            </div>
        </div>
        <div class="col-lg-4">
            <div class="inner">
              <p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
            </div>
        </div>

    </div>
</body>
</html>

It would be great if we could have sort of a “rowspan” effect where we could fit the content nicely together. Fortunately, with a little reordering of the columns and floating the column right, this can be done in an elegant CSS only manner. We’ll move the grid in the second row into the same row as our column with a lot of content. From there we can apply a float:right to the second column.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Responsive Grid Rowspan</title>
<link rel="stylesheet" type="text/css" href="css/style1.css" />
</head>

<body>
    <div class="row">
        <div class="col-lg-8">
            <div class="inner">

                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
            </div>
        </div>
        <div class="col-lg-4 rowspan">
            <div class="inner" style="background:#999;">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
                <p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
            </div>
        </div>
        <div class="col-lg-8">
            <div class="inner">
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras ut justo vel ante fringilla accumsan quis et est. In euismod convallis porta. Mauris condimentum sapien erat, et scelerisque velit dapibus ut. Cras et blandit justo. In laoreet sapien et nulla bibendum, ac fermentum massa lacinia. Etiam ornare est lectus, et posuere velit elementum sed. Fusce sed felis ante. Integer consequat bibendum mi ut porta. Nulla quis egestas est.</p>
              <p>Duis ac risus congue, interdum felis sed, maximus ligula. Aenean mollis convallis libero, non efficitur justo blandit vel. Proin ultrices orci massa, vel pharetra ex convallis in. Mauris fringilla ullamcorper nibh a auctor. In consectetur justo sed tellus iaculis, in vehicula nibh sodales. Nullam tincidunt dignissim odio at vestibulum. Nullam in eros nisl. In vel arcu quis lacus pellentesque rhoncus. Suspendisse quis diam auctor, maximus odio sed, malesuada nulla. Duis rhoncus lorem elit, hendrerit volutpat eros suscipit ac. Cras id magna dui. Donec sit amet massa non libero malesuada sodales sit amet sed sapien. Praesent in arcu ut quam faucibus vehicula non at ligula.</p>
            </div>
        </div>
    </div>
</body>
</html>

And there you have it. With a little bit of finagling, you can get slightly more interesting layouts with a grid. You can see the result of this here…

View Demo »
, ,
Share Tweet Reccomend

Creating an MVC Express.js Application (Part 2): Middleware and Configuration

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 »

, , , ,
Share Tweet Reccomend

JavaScript Routing

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 »

, ,
Share Tweet Reccomend

Pagination in WordPress

You say “tomato” I say “tomoto.” You “pageination” I say “pagination.”

Whatever you call it pagination is something that has abounded on the web since forever. If you’re not 100% sure what term pagination refers to, its the numbered links at the bottom of a page of results. There are different variations, but it often looks kind of like this…

1 2 3 … 37 38 Next > Last >>

If you enter a Google, Yahoo, or Bing Search and scroll to the bottom you will see these numbered links that allow you to the next page of results. That’s one example, but it shows up in many other contexts on the web. There are certainly other ways to do things. Infinite scrolling, for example, which we explored here is another way that sites can give users continual amounts of content. Nonetheless, pagination still remains a very popular way to organize things on websites.

Speaking of popularity, (on a seemingly unrelated note) even as we enter 2015 — the time of writing this — WordPress is still one of the most popular content management systems on the Internet. Despite new up-and-comers on different platforms such as Ghost on Node.js, WordPress is currently still the dominant force for blogging and/or publishing content on the web. So it seems like it would be worth knowing how to fit these 2 popular entities (pagination and WordPress) together. So in what follows, we will look at how to implement this.

So the function we’ll be creating is fairly straightforward. We’ll be making use of the $paged global variable which set to the page number that WordPress is displaying. Then based off of this, we do a few conditionals to figure out where we are in the range of pages.

function create_pagination_markup($pages = '', $range = 4)
{
    $markup = '';
    
    $showitems = ($range * 2)+1;
    
    global $paged;
    if(empty($paged)) $paged = 1;
    
    if($pages == '')
    {
        global $wp_query;
        $pages = $wp_query->max_num_pages;
        if(!$pages)
        {
            $pages = 1;
        }
    }
    
    $pageText = __('Page','ninebit');
    $ofText = __('of','ninebit');
    $firstText = __('First','ninebit');
    $lastText = __('Last','ninebit');
    $previousText = __('Previous','ninebit');
    $nextText = __('Next','ninebit');
         
    if(1 != $pages)
    {
        $markup .= "<div class=\"pagination\"><span>".$pageText." ".$paged." ".$ofText." ".$pages."</span>";
        if($paged > 2 && $paged > $range+1 && $showitems < $pages) $markup .= "<a href='".get_pagenum_link(1)."'>&laquo; ".$firstText."</a>";
        if($paged > 1 && $showitems < $pages) $markup .= "<a href='".get_pagenum_link($paged - 1)."'>&lsaquo; ".$previousText."</a>";
    
        for ($i=1; $i <= $pages; $i++)
        {
            if (1 != $pages &&( !($i >= $paged+$range+1 || $i <= $paged-$range-1) || $pages <= $showitems ))
            {
                $markup .= ($paged == $i)? "<span class=\"current\">".$i."</span>":"<a href='".get_pagenum_link($i)."' class=\"inactive\">".$i."</a>";
            }
        }
    
        if ($paged < $pages && $showitems < $pages) $markup .= "<a href=\"".get_pagenum_link($paged + 1)."\">".$nextText." &rsaquo;</a>";
        if ($paged < $pages-1 &&  $paged+$range-1 < $pages && $showitems < $pages) $markup .= "<a href='".get_pagenum_link($pages)."'>".$lastText." &raquo;</a>";
        $markup .= "</div>\n";
    }
    
    return $markup;
}

Then all we need to do is echo it out where we need it…

<?php echo create_pagination_markup(); ?>

And voila, WordPress pagination.

,