Add the <main>-Element to Modernizr 2.6.2

We don’t need this anymore

With Modernizr v2.7.0 we don’t need this work around anymore. Please update to this version if you use <main>.

tl;dr: You can add the new main-element to Modernizr 2.6.2 by using HTML5 Shiv’s window.html5 option to add your own elements to the shiv.


Since I use some bleeding edge stuff in HTML and CSS in actual projects for clients I ran into one particular issue a couple of times lately and I thought I share a little workaround with you.

Modernizr’s current state

Modernizr includes HTML5 Shiv to make HTML5 elements like header, figure and time known and styleable in old IE. Due to development for Modernizr version 3 the current version is Modernizr 2.6.2 which was published nearly a year ago (September 2012) when the main-element wasn’t around yet. Thus the version of HTML5 Shiv does not include a shiv for the main-element.

Today main is part of the HTML5 specification and is implemented in Chrome, Firefox and Safari Nightlies. You can read more about its value especially for semantics and accessibility on MDN and in a recent article at HTML5 Doctor.

The guys behind HTML5 Shiv included the main-element some time ago (you can learn more about the process of including some kind of default styling for the element in another HTML5 Shiv issue (thanks Mathias for the pointer)) and it is available in version 3.6.2. Sadly the latest stable version of Modernizr only includes version 3.6.1 of the shiv and there is no date set for a new release of Modernizr since everyone on the team tries to push version 3 to be out as soon as possible which will them include the new version of the shiv.

The Workaround

Until then we need to work around the missing shiv for the main-element (along with dialog and template).
Luckily it is possible to extend the list of elements HTML5 Shiv operates upon via its html5.elements option that we can use as needed.

First of all we need to create an object html5 on the window object and then add all elements that we want to be shiv’d.

window.html5 = {
  elements: 'abbr article aside audio bdi canvas data datalist details dialog ' +
      'figcaption figure footer header hgroup main mark meter nav output progress ' +
      'section summary template time video'
};

It is useful to take the list from the current version of the shiv to include all elements that need the shiv.

This code needs to be included before Modernizr is actually invoked so it might be useful to place it inline right before you insert Modernizr itself.

There is another way to include only specific elements like for example the main-element after Modernizr is already included:

window.html5.elements = 'main';
window.html5.shivDocument(document); // re-invoke the `shivDocument` method

Conclusion

This method is pretty straightforward and saves you a lot of time debugging or working around the inclusion of the main-element if you use Modernizr anyway.

A Few More Words on Accessible Dialogs/Modals

tl;dr: It’s necessary to keep the focus within a dialog while tabbing through it. The function below is the easiest way to implement this behavior in JavaScript.


When I created CSS Modal I wanted it to be accessible for screen readers and people that only use the keyboard for navigation. Nicholas Zakas has a great post that helped me a lot with making CSS Modal accessible without too much work.

This posts explains a bit about aria roles, how to use tabindex and how you set focus to the element initially and bringing it back where it was before when the modal gets closed.

But there is one thing it misses and which was raised as an issue against CSS Modal: It should be possible to tab through the modal and keep the focus within the modal while it is active. A circular tabbing through a particular area of a page so to speak.

After some research I came up with a straightforward function that does exactly this. Let’s look at how this function is build and how you can use it.

I’ve created a Gist that you can use if you don’t want the walk-through.

Circular Focus

First of all we need to know what the first and the last element of out particular area is that might receive focus while tabbing through. We could give them an ID and find them with document.getElementById.
Let’s assume we don’t know what the content of that area is and we do not have any influence on the given IDs and stuff. This means we need to filter the first and the last tabbable element. There are some elements that are tabbable especially those which are links, user-input fields or have a tabindex attribute on them (from this answer on StackOverflow).

Here is a full list of CSS selectors:

a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]

This is the list of selectors we need to use to find the first and last tabbable element. So let’s put them into a variable we can use in our function.

var tabbableElements = 'a[href], area[href], input:not([disabled]),' +
	'select:not([disabled]), textarea:not([disabled]),' +
	'button:not([disabled]), iframe, object, embed, *[tabindex],' +
	'*[contenteditable]';

And here is how we find the elements in a given context context:

// First, let's find all tabbable elemets
var allTabbableElements = context.querySelectorAll(tabbableElements);
 
// The first of this list
var firstTabbableElement = allTabbableElements[0];
 
// And the last one
var lastTabbableElement = allTabbableElements[allTabbableElements.length - 1];

A keydown Listener

What we need next is a listener on the last element that will fire when we hit the TAB key on it.
Note: Please remember that IE8 does not support addEventListener, so please use attachEvent where needed.

lastTabbableElement.addEventListener('keydown', function () { /* More magic */ }, false);

The handler for the event listener might look something like that:

var keyCode = event.which || event.keyCode; // Get the current keycode
 
// If it is TAB
if (keyCode === 9) {
 
	// Prevent the default behavior
	if (event.preventDefault) {
		event.preventDefault();
	} else {
		event.returnValue = false;
	}
 
	// Move the focus to the first element that can be tabbed
	firstTabbableElement.focus();
}

So if we reach the end of the element we want to circle in, we just go back to the first tabbable element and focus this. We need to prevent the default behavior – which would be to jump the the next link, out of the element – though.

A Reusable Function

Let’s throw this all together and we get a neat little function that we can call on all elements where we want the focus to stay in.

var tabbableElements = 'a[href], area[href], input:not([disabled]),' +
	'select:not([disabled]), textarea:not([disabled]),' +
	'button:not([disabled]), iframe, object, embed, *[tabindex],' +
	'*[contenteditable]';
 
var keepFocus = function (context) {
	var allTabbableElements = context.querySelectorAll(tabbableElements);
	var firstTabbableElement = allTabbableElements[0];
	var lastTabbableElement = allTabbableElements[allTabbableElements.length - 1];
 
	var keyListener = function (event) {
		var keyCode = event.which || event.keyCode; // Get the current keycode
 
		// If it is TAB
		if (keyCode === 9) {
 
			// Prevent the default behavior
			if (event.preventDefault) {
				event.preventDefault();
			} else {
				event.returnValue = false;
			}
 
			// Move the focus to the first element that can be tabbed
			firstTabbableElement.focus();
		}
	};
 
	lastTabbableElement.addEventListener('keydown', keyListener, false);
};

Here is an example call:

var modal = document.querySelector('.modal');
keepFocus(modal);

This only works for single elements and needs to be called when setting the focus of the element initially.

You can find the complete function as a Gist and use it from there if this serves you better.

Since we are the cool kids, we don’t even need jQuery to help us with any of that. The DOM’s ya friend, y’all!

Conclusion

As we can see it is not very hard to make a dialog accessible by using JavaScript. Nicholas Zakas’ blog post shows some pretty easy methods to create an accessible modal and this circular tabbing method helps to keep focus within the dialog.

If you ask yourself why you would want to do this, I recommend you watch one of Marco Zehe’s talks and read his blog posts on accessibility.

As always there are a lot of smart people who documented this before I did and had better ideas. If you know of any please tell me via Twitter what’s wrong with my snippet and let me make it better. Also I’m not really into accessibility which is why this all might be nonsense.

Update – 01. July 2013

Jörn Zaefferer pointed out that it’s not only Tab that needs to be observed but also Shift + Tab. Totally true since users might want to go backwards through the selected area of the page.

I’ve now updated the function to reflect this behavior. But let’s do a quick walk through the changes.

First I wrote a small polyfill for event.preventDefault(); so we can easily reuse the function throughout the event handler:

// Polyfill to prevent the default behavior of events
event.preventDefault = event.preventDefault || function () {
	event.returnValue = false;
};

Another thing that has changed is the fact that we will now use event delegation instead of a single event on the lastTabbableElement since we need to listen to the first element too. This was suggested by Rodney Rehm too.

One part of this is the listener that changes:

context.addEventListener('keydown', keyListener, false);

The other part is the handler function. We need to match event.target – the currently selected element – against the first and last tabbable element while we have to watch out for the shift key to be pressed. Luckily event.shiftKey tells us that. This code is inspired by the code from jQuery UI’s Dialog component.

// Move focus to first element that can be tabbed if Shift isn't used
if (event.target === lastTabbableElement && !event.shiftKey) {
	event.preventDefault();
	firstTabbableElement.focus();
 
// Move focus to last element that can be tabbed if Shift is used
} else if (event.target === firstTabbableElement && event.shiftKey) {
	event.preventDefault();
	lastTabbableElement.focus();
}

If we put this together, we get the desired behavior: Whether you use Tab or Shift + Tab in the selected part of the page the focus stays in it.
The Gist is available with the updated function.

Is Mothereffin’ jQuery Up?

Some weeks ago I made a pull request for HTML5Boilerplate which should update jQuery to the latest version available on the Google CDN. How ever I copied the old version of minified jQuery because the uncompressed version was available but the minified wasn’t. Stupid thing!

That’s why I created Is Mothereffin’ jQuery up? The service checks three major CDNs for the availability of the latest jQuery version.

View Is Mothereffin’ jQuery up?

How to Check if the File is up

I had some difficulties to find the right method how to detect if a file is already available with JavaScript. If you don’t have to deal with cross-domain requests this is not a big thing and done pretty easy. But I need cross-domain requests.

If a file is not available on a server, the request dies with an error 404 and no callback will be called. See this Fiddle for a test-case. Even a try-catch-expression does not help.

I decided to check all files for availability and if the request ends up in an error nothing will happen. The script will check if all files are available after three seconds and will otherwise “tell” the user that it’s not. This is not a bullet-proof method as it could take more then three seconds to request all files. If you have a better idea please let me know.
For the moment the resources will be labeled as “available” when they are loaded even if they were labeled “not available” before. So you will not end up with wrong result, it just may take a second more to show you that.

The Styles

The project was build “mobile-first”. It makes use of the CSS3 Flexible Box Model instead of float and all the other stuff.

I’m not supporting IE in any way because I think most web-developer don’t use Internet Explorer.

Todo

  • Support more libraries such as Mootools, Dojo, Prototype, ExtJS and YUI
  • Let users submit other CDN via a form
  • Link buttons to their libraryDone with this commitsuggestion by Mathias

Let me know if you want some other features.

Contribute via GitHub

I’ve put this project up on GutHub. Feel free to contribute or just watch it.

Feature requests can also be placed in the issue-tracker there.

The Difference between Push and Pull

Push and Pull

You do know the nice message which is submitted to your smartphone when someone mentions you on Twitter?

iOS gets these messages via push. This means the server tells the app something like “Hey look, there’s something new on your Twitter-account”.
On Android this is done with push, too. It was introduced in version 2.1.0 in mid of July. Before this release they requested all Tweets via “pull”: The app asks the server “Yo server, somethin’ new here?”.

Draw-backs?

So where’s the difference besides the obvious?

  • with pull the app has to connect to the server in a certain time-interval
  • this means heigh power drain
  • it may take some time until you receive a message via pull*
  • push may hold an open connection to the server: more data is send

* Site note: I noticed that it also may take some time until a new message is delivered with push technology on iOS or Android (for Twitter-App). If anyone knows more on this issue please share your thoughts.

The way we do it today

If you’re coding an online app you have something where you’re displaying new messages or so. The known approach is to return asynchronously to the server via JavaScript and evaluate the answer. Something like this:

$.getJSON( 'messages.php' , function( data ) {
  // If there is a message
  if ( data.length &gt; 0 ) {
    $.each( data['msg'], function() {
      // Do some fancy stuff with messages…
    });
  }
});

This is “pull”. It is not enough to request the answer of this file once, because this would evaluate the data only once. This is why there has to be a kind of timed event which fires the request in an interval.

This is what it could like with an intervall of 1 minute:

! function pull_request() {
  $.getJSON( 'messages.php' , function( data ) {
    // If there is a message
    if ( data.length &gt; 0 ) {
      $.each( data['msg'], function() {
        // Do some fancy stuff with messages…
      });
    }
  });
 
  window.setTimeout( function() {
    pull_request();
  }, 1000 * 60 );
} ();

As you can see, there is an IIFE surrounding the code. I am doing this in order to call the timeout recursively. For more information please read Ben Almans article on this issue.

What else is possible

This will work totally fine. Let’s take a look at other possible ways.

The Wikipedia article about push sais:

Push technology, or server push, describes a style of Internet-based communication where the request for a given transaction is initiated by the publisher or central server.

With HTML5 the WHATWG introduces The WebSocket API.

WebSocket API

The WebSocket API enables websites and apps to communicate with a server. A polyfill for browsers that do not support WebSocket and as a framework you should definitely check out Socket.IO.

There were some definitions of this API in the spec that had some security problems and so browser vendors implemented some stuff that is outdated by now. There is a kinda “last call” specification for this API which are already implemented in Chrome dev channel (version 14) and Firefox 7. The API is available with a current version of Webkit so it should be in Safari soon.

Server-Sent Events

Furthermore there is the Server-Sent Event which is dedicated to fulfill push notifications. The event is already supported in stable versions of Safari, Chrome, Firefox and Opera. See When Can I Use… for more information.

The Server-Sent Event is a DOM event and can be accessed via new EventSource( file ); in JavaScript, while file is a server-file which publishes the notification. With the onmessage-event it is possible to listen to the changes of notifications.

var source = new EventSource( 'messages.cgi' );
source.onmessage = function( e ) {
  // do something with the notification, e.g. log it in the console.
  console.log( e.data );
}

Conclusion

With the given technologies it is possible to send notifications via push to the client-site. There are polyfills for “older” browsers (like pulling data). It is possible to use these tools today.

If you have any experience with the topic of pushing data, please share your thoughts and ideas in the comments.
Thanks for reading though.

I am going to develop a web-app with a friend of mine. We are using node.js for the server part. I am pretty exited to deal with it. We will definitely need something like a push event. We’ll see what will be best.

Read more and follow-up info:

  • Follow Ian Hickson on Twitter or Google+. He is the editor of the spec for Server-sent Events and The WebSocket API.
  • You should checkout the Modernizr Polyfill Wiki to get some information on polyfills for older browsers with WebSockets aso.