Categories
Development

AJAX Efficiency with jQuery and HTML5

It’s super-common in front-end development to load a lot of content dynamically via AJAX. It’s tempting to rely on jQuery selectors to initialize these elements. We’ve all seen it: a huge chunk of code with twenty anonymous functions, each one a callback to a jQuery `.each()` method. We like jQuery selector callbacks because they’re convenient–no code is executed unless a match is found. It’s a built-in if-statement! But querying the DOM is an expensive operation which can slow down the loading of your site and drive away users. It’s also lazy coding.

To counter this, consider offloading initializations to a single, generic callback that will minimize the performance hit while retaining the convenience of selector-based initialization. That’s a mouthful! In other words, let’s create a master function to call all the others for us–a `MapReduce()` for the front-end, if you will. Here’s how.

## Example Scenario

Let’s say we’re making a page with two dynamic blocks of content: *Recent Tweets* and *Upcoming Events*.

[codepen_embed height=”430″ theme_id=”0″ slug_hash=”djIzv” default_tab=”result” user=”njbair”]See the Pen djIzv by Nick Bair (@njbair) on CodePen.[/codepen_embed]

Normally, the static page markup might look something like this:

And the JavaScript:

$(document).ready(function(){
$(‘.recent-tweets’).each(function(){
// load some ajax or something
});

$(‘.upcoming-events’).each(function(){
// load some ajax or something
}
});

So we have two selectors, `recent-tweets` and `upcoming-events`, that essentially do the same thing–query the DOM tree for an element with the given class name and, if found, perform the specified function. Not a big deal when dealing with only two selectors as in this example, but as we add more and more dynamic blocks the performance hit adds up quickly, especially on low-powered devices like smartphones.

What if we could boil this down to a single selector? Like so:

Then we could initialize both blocks with `$(‘.init’).each()`. That would be cool! But we need some way to tell the function what code to run on each block. Enter the HTML5 `data-` attribute:

We’ve created a `data-init` attribute which contains a unique identifier for each block. In our JavaScript, we use those identifiers as the names of functions. Then we replace both selectors with a single, master selector. Observe:

function loadRecentTweets(theElement)
{
// load recent tweets from the local REST API
$.ajax(‘api/tweets’).done(function(response){
// display the data inside the container element
$(theElement).append(response.content);
});
}

function loadUpcomingEvents(theElement)
{
// load upcoming events from the local REST API
$.ajax(‘api/events’).done(function(response){
// display the data inside the container element
$(theElement).append(response.content);
});
}

// master selector
$(document).ready(function(){
$(‘.init’).each(function(){
var initFunction = $(this).data(‘init’);

// this funny-looking line calls the value of `data-init` as
// a function, and passes the element’s DOM node as an argument.
window[initFunction](this);
});
});

This is great, for several reasons:

– **Readability** – A cursory glance at the HTML markup tells us exactly which function affects it.
– **Portability** – This code can easily be moved or copied elsewhere without any concern about side-effects.
– **Abstraction** – We’ve minimized repetition, so changes are easier to make.

But those two functions still look awfully similar. It would be nice to combine them into something more generic…

## Putting data- to Work

Since our master selector callback passes the DOM node itself as an argument, our init functions can read in whatever attributes we want. That means we can do something like this:

function loadTheCode(theElement)
{
var ajaxUrl = $(theElement).data(‘url’);

// load some data from the specified URL
$.ajax(ajaxUrl).done(function(response){
// display the data inside the container element
$(theElement).append(response.content);
});
}

Now our markup would look like this:

This is getting awesomer. Later, when we decide we want a list of only certain tweets on a different page, all we have to do is add one line of markup:

We just made more AJAX happen without even touching our JavaScript!

## Infinite Possibilities

Using `data-` attributes, we can pass our loader function as many “arguments” as we want. How about `data-refresh` to specify an auto-refresh interval, or `data-cache` to control AJAX caching options? Together with a well-tuned REST API this method is virtually limitless.

Categories
Development

HOWTO: Fix “Keyword title is not registered” error in Joomla 3.0

If you’re working with Joomla using an HTML5 template and you try and validate your site using the [W3C Markup Validation Service](http://validator.w3.org), you may find yourself hit with the following validation error:

*Line 7, Column 44*: **Bad value title for attribute name on element meta: Keyword title is not registered.**

  <meta name="title" content="Who We Are" />
Syntax of metadata name:
A metadata name listed in the HTML specification or listed in the WHATWG wiki. You can register metadata names on the WHATWG wiki yourself.

The **title** meta keyword is a carryover from older versions of Joomla (pre-HTML5), back when the HTML specification did not restrict meta keywords as they do now. While it’s true that the error notice provides instructions on how to register a metadata name yourself, there is a quick fix that gets your site to validate and avoids involvement in deliberations over an emerging spec, and it can be applied **without** modifying Joomla core files.

To fix the error, simply add the following line to the opening PHP code block in your template’s **index.php**, right before the closing tag:

// remove “title” metadata keyword because it breaks HTML5 validation
$doc->setMetaData(‘title’, FALSE);

This line simply unsets the keyword so that the meta tag will not be rendered by the template engine. It assumes that your template code has already set the `$doc` variable using `JFactory::getDocument()`. If your Document object is assigned to a different variable, use that instead.

Categories
Administration Development Software

Displaying PHP errors with Xdebug in Ubuntu Server

Ubuntu Server packages are generally pretty well-configured right out of the box–usually requiring little or no configuration for simple operation. It’s one of the reasons why, despite my preference toward Arch Linux for the desktop, I’ve long advocated Ubuntu as a great starting point for a LAMP development server. Yet, on occasion, a package ships with a configuration that needs some work in order to be useful. Xdebug is such a package.

Xdebug’s most immediately helpful feature is the display of stack traces for all PHP errors. (Actually, it does a whole lot more than that, but that’s beyond the scope of this post.) Stack traces appear in place of the ordinary PHP error notices, so they require that the PHP config option **display_errors** is enabled. But Ubuntu disables this option by default.

This is actually a sane default, because error notices may potentially expose security holes or other sensitive data, and thus should be suppressed in production environments. But installing Xdebug implies that the target is a development and/or testing environment (for a lot of reasons, not the least of which is Xdebug’s non-trivial processing overhead). So it makes sense that display_errors should be enabled.

This is a simple fix. Edit */etc/php5/apache2/php.ini*, locate the **display_errors** option, and change its value from **Off** to **On**. The final result should look like this:

display_errors = On

Alternatively, you can add that line to the end of the Xdebug config file located in */etc/php5/conf.d/*. This allows you to enable/disable the display of errors at the same time as you enable/disable the Xdebug module. (This can be done by invoking either of the provided scripts **php5enmod** and **php5dismod** and reloading Apache.)

I have filed [a bug report]( https://bugs.launchpad.net/ubuntu/+source/xdebug/+bug/1096464) to notify the devs about this issue. I hope this post and an eventual bug fix will save other folks some frustration.

Categories
Development Software

File Access Bug in LAMP Virtual Machine

Using a VM as a web development test server is a great way to optimize workstation resources. My test VM is an Ubuntu installation with a standard Apache/MySQL/PHP stack. I use VirtualBox shared folders to grant the VM access to my development directory.

For some time I have been wrestling with an irritating bug that crops up when using shared folders with Apache: when a new file is created, and sometimes when existing files are modified, Apache fails to recognize the change. Any attempt to access the file via HTTP will result in a 404 error. Some searching led me to this VirtualBox bug report and the solution.

By default, Apache leverages the kernel’s *sendfile* mechanism to deliver resources to HTTP clients in order to optimize performance. But when a small file on a network share is altered, sometimes sendfile doesn’t bother to check its length or contents. Most of the time this is not an issue for production servers, which rarely use network storage and which don’t experience the frequent file changes of a development server. But in this case the default behavior needs to be changed.

To turn off sendfile in apache, add the following line to the Apache server configuration (i.e. **/etc/apache2.conf**):

EnableSendfile Off

Restart Apache to apply the new configuration.

###Related Links
* [vboxsf and small files](http://frankooh.wordpress.com/2011/01/21/vboxsf-and-small-files/)
* [Apache EnableSendfile Directive](http://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile)